1 define("dojo/dnd/Mover", ["../main", "../Evented", "../touch", "./common", "./autoscroll"], function(dojo, Evented, touch) {
8 dojo.declare("dojo.dnd.Mover", [Evented], {
9 constructor: function(node, e, host){
11 // an object which makes a node follow the mouse, or touch-drag on touch devices.
12 // Used as a default mover, and as a base class for custom movers.
14 // a node (or node's id) to be moved
16 // a mouse event, which started the move;
17 // only pageX and pageY properties are used
19 // object which implements the functionality of the move,
20 // and defines proper events (onMoveStart and onMoveStop)
21 this.node = dojo.byId(node);
22 this.marginBox = {l: e.pageX, t: e.pageY};
23 this.mouseButton = e.button;
24 var h = (this.host = host), d = node.ownerDocument;
26 // At the start of a drag, onFirstMove is called, and then the following two
27 // connects are disconnected
28 dojo.connect(d, touch.move, this, "onFirstMove"),
30 // These are called continually during the drag
31 dojo.connect(d, touch.move, this, "onMouseMove"),
33 // And these are called at the end of the drag
34 dojo.connect(d, touch.release, this, "onMouseUp"),
36 // cancel text selection and text dragging
37 dojo.connect(d, "ondragstart", dojo.stopEvent),
38 dojo.connect(d.body, "onselectstart", dojo.stopEvent)
40 // notify that the move has started
41 if(h && h.onMoveStart){
45 // mouse event processors
46 onMouseMove: function(e){
48 // event processor for onmousemove/ontouchmove
51 dojo.dnd.autoScroll(e);
52 var m = this.marginBox;
53 this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, e);
56 onMouseUp: function(e){
57 if(dojo.isWebKit && dojo.isMac && this.mouseButton == 2 ?
58 e.button == 0 : this.mouseButton == e.button){ // TODO Should condition be met for touch devices, too?
64 onFirstMove: function(e){
66 // makes the node absolute; it is meant to be called only once.
67 // relative and absolutely positioned nodes are assumed to use pixel units
68 var s = this.node.style, l, t, h = this.host;
72 // assume that left and top values are in pixels already
73 l = Math.round(parseFloat(s.left)) || 0;
74 t = Math.round(parseFloat(s.top)) || 0;
77 s.position = "absolute"; // enforcing the absolute mode
78 var m = dojo.marginBox(this.node);
79 // event.pageX/pageY (which we used to generate the initial
80 // margin box) includes padding and margin set on the body.
81 // However, setting the node's position to absolute and then
82 // doing dojo.marginBox on it *doesn't* take that additional
83 // space into account - so we need to subtract the combined
84 // padding and margin. We use getComputedStyle and
85 // _getMarginBox/_getContentBox to avoid the extra lookup of
86 // the computed style.
87 var b = dojo.doc.body;
88 var bs = dojo.getComputedStyle(b);
89 var bm = dojo._getMarginBox(b, bs);
90 var bc = dojo._getContentBox(b, bs);
91 l = m.l - (bc.l - bm.l);
92 t = m.t - (bc.t - bm.t);
95 this.marginBox.l = l - this.marginBox.l;
96 this.marginBox.t = t - this.marginBox.t;
97 if(h && h.onFirstMove){
98 h.onFirstMove(this, e);
101 // Disconnect onmousemove and ontouchmove events that call this function
102 dojo.disconnect(this.events.shift());
106 // stops the move, deletes all references, so the object can be garbage-collected
107 dojo.forEach(this.events, dojo.disconnect);
108 // undo global settings
110 if(h && h.onMoveStop){
114 this.events = this.node = this.host = null;
118 return dojo.dnd.Mover;