1 | define(["../main", "../Evented", "../touch", "./common", "./autoscroll"], function(dojo, Evented, touch) { |
---|
2 | // module: |
---|
3 | // dojo/dnd/Mover |
---|
4 | // summary: |
---|
5 | // TODOC |
---|
6 | |
---|
7 | |
---|
8 | dojo.declare("dojo.dnd.Mover", [Evented], { |
---|
9 | constructor: function(node, e, host){ |
---|
10 | // summary: |
---|
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. |
---|
13 | // node: Node |
---|
14 | // a node (or node's id) to be moved |
---|
15 | // e: Event |
---|
16 | // a mouse event, which started the move; |
---|
17 | // only pageX and pageY properties are used |
---|
18 | // host: Object? |
---|
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; |
---|
25 | this.events = [ |
---|
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"), |
---|
29 | |
---|
30 | // These are called continually during the drag |
---|
31 | dojo.connect(d, touch.move, this, "onMouseMove"), |
---|
32 | |
---|
33 | // And these are called at the end of the drag |
---|
34 | dojo.connect(d, touch.release, this, "onMouseUp"), |
---|
35 | |
---|
36 | // cancel text selection and text dragging |
---|
37 | dojo.connect(d, "ondragstart", dojo.stopEvent), |
---|
38 | dojo.connect(d.body, "onselectstart", dojo.stopEvent) |
---|
39 | ]; |
---|
40 | // notify that the move has started |
---|
41 | if(h && h.onMoveStart){ |
---|
42 | h.onMoveStart(this); |
---|
43 | } |
---|
44 | }, |
---|
45 | // mouse event processors |
---|
46 | onMouseMove: function(e){ |
---|
47 | // summary: |
---|
48 | // event processor for onmousemove/ontouchmove |
---|
49 | // e: Event |
---|
50 | // mouse/touch event |
---|
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); |
---|
54 | dojo.stopEvent(e); |
---|
55 | }, |
---|
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? |
---|
59 | this.destroy(); |
---|
60 | } |
---|
61 | dojo.stopEvent(e); |
---|
62 | }, |
---|
63 | // utilities |
---|
64 | onFirstMove: function(e){ |
---|
65 | // summary: |
---|
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; |
---|
69 | switch(s.position){ |
---|
70 | case "relative": |
---|
71 | case "absolute": |
---|
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; |
---|
75 | break; |
---|
76 | default: |
---|
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); |
---|
93 | break; |
---|
94 | } |
---|
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); |
---|
99 | } |
---|
100 | |
---|
101 | // Disconnect onmousemove and ontouchmove events that call this function |
---|
102 | dojo.disconnect(this.events.shift()); |
---|
103 | }, |
---|
104 | destroy: function(){ |
---|
105 | // summary: |
---|
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 |
---|
109 | var h = this.host; |
---|
110 | if(h && h.onMoveStop){ |
---|
111 | h.onMoveStop(this); |
---|
112 | } |
---|
113 | // destroy objects |
---|
114 | this.events = this.node = this.host = null; |
---|
115 | } |
---|
116 | }); |
---|
117 | |
---|
118 | return dojo.dnd.Mover; |
---|
119 | }); |
---|