/*
Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
Available via Academic Free License >= 2.1 OR the modified BSD license.
see: http://dojotoolkit.org/license for details
*/
if(!dojo._hasResource["dojox.mdnd.Moveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.mdnd.Moveable"] = true;
dojo.provide("dojox.mdnd.Moveable");
dojo.declare(
"dojox.mdnd.Moveable",
null,
{
// summary:
// Allow end-users to track a DOM node into the web page
// handle: DOMNode
// The node on which the user clicks to drag the main node.
handle: null,
// skip: Boolean
// A flag to control a drag action if a form element has been focused.
// If true, the drag action is not executed.
skip: true,
// dragDistance: Integer
// The user clicks on the handle, but the drag action will really begin
// if he tracks the main node to more than 3 pixels.
dragDistance: 3,
constructor: function(/*Object*/params, /*DOMNode*/node){
// summary:
// Configure parameters and listen to mousedown events from handle
// node.
// params:
// Hash of parameters
// node:
// The draggable node
//console.log("dojox.mdnd.Moveable ::: constructor");
this.node = dojo.byId(node);
this.d = this.node.ownerDocument;
if(!params){ params = {}; }
this.handle = params.handle ? dojo.byId(params.handle) : null;
if(!this.handle){ this.handle = this.node; }
this.skip = params.skip;
this.events = [
dojo.connect(this.handle, "onmousedown", this, "onMouseDown")
];
if(dojox.mdnd.autoScroll){
this.autoScroll = dojox.mdnd.autoScroll;
}
},
isFormElement: function(/*DOMEvent*/ e){
// summary:
// identify the type of target node associated with a DOM event.
// e:
// a DOM event
// returns:
// if true, the target is one of those specific nodes.
//console.log("dojox.mdnd.Moveable ::: isFormElement");
var t = e.target;
if(t.nodeType == 3 /*TEXT_NODE*/){
t = t.parentNode;
}
return " a button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0; // Boolean
},
onMouseDown: function(/*DOMEvent*/e){
// summary:
// Occurs when the user clicks on the handle node.
// Skip the drag action if a specific node is targeted.
// Listens to mouseup and mousemove events on to the HTML document.
// e:
// a DOM event
// tags:
// callback
//console.log("dojox.mdnd.Moveable ::: onMouseDown");
if(this._isDragging){ return;}
var isLeftButton = dojo.isIE ? (e.button == 1) : (e.which == 1);
if(!isLeftButton){
return;
}
if(this.skip && this.isFormElement(e)){ return; }
if(this.autoScroll){
this.autoScroll.setAutoScrollNode(this.node);
this.autoScroll.setAutoScrollMaxPage();
}
this.events.push(dojo.connect(this.d, "onmouseup", this, "onMouseUp"));
this.events.push(dojo.connect(this.d, "onmousemove", this, "onFirstMove"));
this._selectStart = dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent);
this._firstX = e.clientX;
this._firstY = e.clientY;
dojo.stopEvent(e);
},
onFirstMove: function(/*DOMEvent*/e){
// summary:
// Occurs when the user moves the mouse after clicking on the
// handle.
// Determinate when the drag action will have to begin (see
// dragDistance).
// e:
// A DOM event
// tags:
// callback
//console.log("dojox.mdnd.Moveable ::: onFirstMove");
dojo.stopEvent(e);
var d = (this._firstX - e.clientX) * (this._firstX - e.clientX)
+ (this._firstY - e.clientY) * (this._firstY - e.clientY);
if(d > this.dragDistance * this.dragDistance){
this._isDragging = true;
dojo.disconnect(this.events.pop());
dojo.style(this.node, "width", dojo.contentBox(this.node).w + "px");
this.initOffsetDrag(e);
this.events.push(dojo.connect(this.d, "onmousemove", this, "onMove"));
}
},
initOffsetDrag: function(/*DOMEvent*/e){
// summary:
// Initialize the gap between main node coordinates and the clicked point.
// Call the onDragStart method.
// e:
// A DOM event
//console.log("dojox.mdnd.Moveable ::: initOffsetDrag");
this.offsetDrag = { 'l': e.pageX, 't': e.pageY };
var s = this.node.style;
var position = dojo.position(this.node, true);
/*if(s.position == "relative" || s.position == ""){
s.position = "absolute"; // enforcing the absolute mode
}*/
this.offsetDrag.l = position.x - this.offsetDrag.l;
this.offsetDrag.t = position.y - this.offsetDrag.t;
var coords = {
'x': position.x,
'y': position.y
};
this.size = {
'w': position.w,
'h': position.h
};
// method to catch
this.onDragStart(this.node, coords, this.size);
},
onMove: function(/*DOMEvent*/e){
// summary:
// Occurs when the user moves the mouse.
// Calls the onDrag method.
// e:
// a DOM event
// tags:
// callback
//console.log("dojox.mdnd.Moveable ::: onMove");
dojo.stopEvent(e);
// hack to avoid too many calls to onMove in IE8 causing sometimes slowness
if(dojo.isIE == 8 && new Date() - this.date < 20){
return;
}
if(this.autoScroll){
this.autoScroll.checkAutoScroll(e);
}
var coords = {
'x': this.offsetDrag.l + e.pageX,
'y': this.offsetDrag.t + e.pageY
};
var s = this.node.style;
s.left = coords.x + "px";
s.top = coords.y + "px";
// method to catch
this.onDrag(this.node, coords, this.size, {'x':e.pageX, 'y':e.pageY});
if(dojo.isIE == 8){
this.date = new Date();
}
},
onMouseUp: function(/*DOMEvent*/e){
// summary:
// Occurs when the user releases the mouse
// Calls the onDragEnd method.
// e:
// a DOM event
if (this._isDragging){
dojo.stopEvent(e);
this._isDragging = false;
if(this.autoScroll){
this.autoScroll.stopAutoScroll();
}
delete this.onMove;
this.onDragEnd(this.node);
this.node.focus();
}
dojo.disconnect(this.events.pop());
dojo.disconnect(this.events.pop());
},
onDragStart: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size){
// summary:
// Stub function.
// Notes : border box model
// node:
// a DOM node
// coords:
// absolute position of the main node
// size:
// an object encapsulating width an height values
// tags:
// callback
},
onDragEnd: function(/*DOMNode*/node){
// summary:
// Stub function
// Notes : Coordinates don't contain margins
// node:
// a DOM node
// tags:
// callback
},
onDrag: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size, /*Object*/mousePosition){
// summary:
// Stub function.
// Notes : border box model for size value, margin box model for coordinates
// node:
// a DOM node
// coords:
// position of the main node (equals to css left/top properties)
// size:
// an object encapsulating width and height values
// mousePosition:
// coordiantes of mouse
// tags:
// callback
},
destroy: function(){
// summary:
// Delecte associated events
// console.log("dojox.mdnd.Moveable ::: destroy");
dojo.forEach(this.events, dojo.disconnect);
this.events = this.node = null;
}
});
}