]>
Commit | Line | Data |
---|---|---|
2f01fe57 AD |
1 | /* |
2 | Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. | |
3 | Available via Academic Free License >= 2.1 OR the modified BSD license. | |
4 | see: http://dojotoolkit.org/license for details | |
5 | */ | |
6 | ||
7 | ||
a089699c AD |
8 | if(!dojo._hasResource["dojo.dnd.Manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. |
9 | dojo._hasResource["dojo.dnd.Manager"] = true; | |
2f01fe57 | 10 | dojo.provide("dojo.dnd.Manager"); |
a089699c | 11 | |
2f01fe57 AD |
12 | dojo.require("dojo.dnd.common"); |
13 | dojo.require("dojo.dnd.autoscroll"); | |
14 | dojo.require("dojo.dnd.Avatar"); | |
a089699c AD |
15 | |
16 | dojo.declare("dojo.dnd.Manager", null, { | |
17 | // summary: | |
18 | // the manager of DnD operations (usually a singleton) | |
19 | constructor: function(){ | |
20 | this.avatar = null; | |
21 | this.source = null; | |
22 | this.nodes = []; | |
23 | this.copy = true; | |
24 | this.target = null; | |
25 | this.canDropFlag = false; | |
26 | this.events = []; | |
27 | }, | |
28 | ||
29 | // avatar's offset from the mouse | |
30 | OFFSET_X: 16, | |
31 | OFFSET_Y: 16, | |
32 | ||
33 | // methods | |
34 | overSource: function(source){ | |
35 | // summary: | |
36 | // called when a source detected a mouse-over condition | |
37 | // source: Object | |
38 | // the reporter | |
39 | if(this.avatar){ | |
40 | this.target = (source && source.targetState != "Disabled") ? source : null; | |
41 | this.canDropFlag = Boolean(this.target); | |
42 | this.avatar.update(); | |
43 | } | |
44 | dojo.publish("/dnd/source/over", [source]); | |
45 | }, | |
46 | outSource: function(source){ | |
47 | // summary: | |
48 | // called when a source detected a mouse-out condition | |
49 | // source: Object | |
50 | // the reporter | |
51 | if(this.avatar){ | |
52 | if(this.target == source){ | |
53 | this.target = null; | |
54 | this.canDropFlag = false; | |
55 | this.avatar.update(); | |
56 | dojo.publish("/dnd/source/over", [null]); | |
57 | } | |
58 | }else{ | |
59 | dojo.publish("/dnd/source/over", [null]); | |
60 | } | |
61 | }, | |
62 | startDrag: function(source, nodes, copy){ | |
63 | // summary: | |
64 | // called to initiate the DnD operation | |
65 | // source: Object | |
66 | // the source which provides items | |
67 | // nodes: Array | |
68 | // the list of transferred items | |
69 | // copy: Boolean | |
70 | // copy items, if true, move items otherwise | |
71 | this.source = source; | |
72 | this.nodes = nodes; | |
73 | this.copy = Boolean(copy); // normalizing to true boolean | |
74 | this.avatar = this.makeAvatar(); | |
75 | dojo.body().appendChild(this.avatar.node); | |
76 | dojo.publish("/dnd/start", [source, nodes, this.copy]); | |
77 | this.events = [ | |
78 | dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"), | |
79 | dojo.connect(dojo.doc, "onmouseup", this, "onMouseUp"), | |
80 | dojo.connect(dojo.doc, "onkeydown", this, "onKeyDown"), | |
81 | dojo.connect(dojo.doc, "onkeyup", this, "onKeyUp"), | |
82 | // cancel text selection and text dragging | |
83 | dojo.connect(dojo.doc, "ondragstart", dojo.stopEvent), | |
84 | dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent) | |
85 | ]; | |
86 | var c = "dojoDnd" + (copy ? "Copy" : "Move"); | |
87 | dojo.addClass(dojo.body(), c); | |
88 | }, | |
89 | canDrop: function(flag){ | |
90 | // summary: | |
91 | // called to notify if the current target can accept items | |
92 | var canDropFlag = Boolean(this.target && flag); | |
93 | if(this.canDropFlag != canDropFlag){ | |
94 | this.canDropFlag = canDropFlag; | |
95 | this.avatar.update(); | |
96 | } | |
97 | }, | |
98 | stopDrag: function(){ | |
99 | // summary: | |
100 | // stop the DnD in progress | |
101 | dojo.removeClass(dojo.body(), "dojoDndCopy"); | |
102 | dojo.removeClass(dojo.body(), "dojoDndMove"); | |
103 | dojo.forEach(this.events, dojo.disconnect); | |
104 | this.events = []; | |
105 | this.avatar.destroy(); | |
106 | this.avatar = null; | |
107 | this.source = this.target = null; | |
108 | this.nodes = []; | |
109 | }, | |
110 | makeAvatar: function(){ | |
111 | // summary: | |
112 | // makes the avatar; it is separate to be overwritten dynamically, if needed | |
113 | return new dojo.dnd.Avatar(this); | |
114 | }, | |
115 | updateAvatar: function(){ | |
116 | // summary: | |
117 | // updates the avatar; it is separate to be overwritten dynamically, if needed | |
118 | this.avatar.update(); | |
119 | }, | |
120 | ||
121 | // mouse event processors | |
122 | onMouseMove: function(e){ | |
123 | // summary: | |
124 | // event processor for onmousemove | |
125 | // e: Event | |
126 | // mouse event | |
127 | var a = this.avatar; | |
128 | if(a){ | |
129 | dojo.dnd.autoScrollNodes(e); | |
130 | //dojo.dnd.autoScroll(e); | |
131 | var s = a.node.style; | |
132 | s.left = (e.pageX + this.OFFSET_X) + "px"; | |
133 | s.top = (e.pageY + this.OFFSET_Y) + "px"; | |
134 | var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))); | |
135 | if(this.copy != copy){ | |
136 | this._setCopyStatus(copy); | |
137 | } | |
138 | } | |
139 | }, | |
140 | onMouseUp: function(e){ | |
141 | // summary: | |
142 | // event processor for onmouseup | |
143 | // e: Event | |
144 | // mouse event | |
145 | if(this.avatar){ | |
146 | if(this.target && this.canDropFlag){ | |
147 | var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))), | |
148 | params = [this.source, this.nodes, copy, this.target, e]; | |
149 | dojo.publish("/dnd/drop/before", params); | |
150 | dojo.publish("/dnd/drop", params); | |
151 | }else{ | |
152 | dojo.publish("/dnd/cancel"); | |
153 | } | |
154 | this.stopDrag(); | |
155 | } | |
156 | }, | |
157 | ||
158 | // keyboard event processors | |
159 | onKeyDown: function(e){ | |
160 | // summary: | |
161 | // event processor for onkeydown: | |
162 | // watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag | |
163 | // e: Event | |
164 | // keyboard event | |
165 | if(this.avatar){ | |
166 | switch(e.keyCode){ | |
167 | case dojo.keys.CTRL: | |
168 | var copy = Boolean(this.source.copyState(true)); | |
169 | if(this.copy != copy){ | |
170 | this._setCopyStatus(copy); | |
171 | } | |
172 | break; | |
173 | case dojo.keys.ESCAPE: | |
174 | dojo.publish("/dnd/cancel"); | |
175 | this.stopDrag(); | |
176 | break; | |
177 | } | |
178 | } | |
179 | }, | |
180 | onKeyUp: function(e){ | |
181 | // summary: | |
182 | // event processor for onkeyup, watching for CTRL for copy/move status | |
183 | // e: Event | |
184 | // keyboard event | |
185 | if(this.avatar && e.keyCode == dojo.keys.CTRL){ | |
186 | var copy = Boolean(this.source.copyState(false)); | |
187 | if(this.copy != copy){ | |
188 | this._setCopyStatus(copy); | |
189 | } | |
190 | } | |
191 | }, | |
192 | ||
193 | // utilities | |
194 | _setCopyStatus: function(copy){ | |
195 | // summary: | |
196 | // changes the copy status | |
197 | // copy: Boolean | |
198 | // the copy status | |
199 | this.copy = copy; | |
200 | this.source._markDndStatus(this.copy); | |
201 | this.updateAvatar(); | |
202 | dojo.removeClass(dojo.body(), "dojoDnd" + (this.copy ? "Move" : "Copy")); | |
203 | dojo.addClass(dojo.body(), "dojoDnd" + (this.copy ? "Copy" : "Move")); | |
204 | } | |
205 | }); | |
206 | ||
207 | // dojo.dnd._manager: | |
208 | // The manager singleton variable. Can be overwritten if needed. | |
209 | dojo.dnd._manager = null; | |
210 | ||
211 | dojo.dnd.manager = function(){ | |
212 | // summary: | |
213 | // Returns the current DnD manager. Creates one if it is not created yet. | |
214 | if(!dojo.dnd._manager){ | |
215 | dojo.dnd._manager = new dojo.dnd.Manager(); | |
216 | } | |
217 | return dojo.dnd._manager; // Object | |
2f01fe57 | 218 | }; |
a089699c | 219 | |
2f01fe57 | 220 | } |