1 define("dojo/dnd/Manager", [
2 "../_base/array", "../_base/declare", "../_base/event", "../_base/lang", "../_base/window",
3 "../dom-class", "../Evented", "../has", "../keys", "../on", "../topic", "../touch",
4 "./common", "./autoscroll", "./Avatar"
5 ], function(array, declare, event, lang, win, domClass, Evented, has, keys, on, topic, touch,
6 dnd, autoscroll, Avatar){
11 var Manager = declare("dojo.dnd.Manager", [Evented], {
13 // the manager of DnD operations (usually a singleton)
14 constructor: function(){
20 this.canDropFlag = false;
24 // avatar's offset from the mouse
25 OFFSET_X: has("touch") ? 0 : 16,
26 OFFSET_Y: has("touch") ? -64 : 16,
29 overSource: function(source){
31 // called when a source detected a mouse-over condition
35 this.target = (source && source.targetState != "Disabled") ? source : null;
36 this.canDropFlag = Boolean(this.target);
39 topic.publish("/dnd/source/over", source);
41 outSource: function(source){
43 // called when a source detected a mouse-out condition
47 if(this.target == source){
49 this.canDropFlag = false;
51 topic.publish("/dnd/source/over", null);
54 topic.publish("/dnd/source/over", null);
57 startDrag: function(source, nodes, copy){
59 // called to initiate the DnD operation
61 // the source which provides items
63 // the list of transferred items
65 // copy items, if true, move items otherwise
67 // Tell autoscroll that a drag is starting
68 autoscroll.autoScrollStart(win.doc);
72 this.copy = Boolean(copy); // normalizing to true boolean
73 this.avatar = this.makeAvatar();
74 win.body().appendChild(this.avatar.node);
75 topic.publish("/dnd/start", source, nodes, this.copy);
77 on(win.doc, touch.move, lang.hitch(this, "onMouseMove")),
78 on(win.doc, touch.release, lang.hitch(this, "onMouseUp")),
79 on(win.doc, "keydown", lang.hitch(this, "onKeyDown")),
80 on(win.doc, "keyup", lang.hitch(this, "onKeyUp")),
81 // cancel text selection and text dragging
82 on(win.doc, "dragstart", event.stop),
83 on(win.body(), "selectstart", event.stop)
85 var c = "dojoDnd" + (copy ? "Copy" : "Move");
86 domClass.add(win.body(), c);
88 canDrop: function(flag){
90 // called to notify if the current target can accept items
91 var canDropFlag = Boolean(this.target && flag);
92 if(this.canDropFlag != canDropFlag){
93 this.canDropFlag = canDropFlag;
99 // stop the DnD in progress
100 domClass.remove(win.body(), ["dojoDndCopy", "dojoDndMove"]);
101 array.forEach(this.events, function(handle){ handle.remove(); });
103 this.avatar.destroy();
105 this.source = this.target = null;
108 makeAvatar: function(){
110 // makes the avatar; it is separate to be overwritten dynamically, if needed
111 return new Avatar(this);
113 updateAvatar: function(){
115 // updates the avatar; it is separate to be overwritten dynamically, if needed
116 this.avatar.update();
119 // mouse event processors
120 onMouseMove: function(e){
122 // event processor for onmousemove
127 autoscroll.autoScrollNodes(e);
128 //autoscroll.autoScroll(e);
129 var s = a.node.style;
130 s.left = (e.pageX + this.OFFSET_X) + "px";
131 s.top = (e.pageY + this.OFFSET_Y) + "px";
132 var copy = Boolean(this.source.copyState(dnd.getCopyKeyState(e)));
133 if(this.copy != copy){
134 this._setCopyStatus(copy);
138 // Prevent page from scrolling so that user can drag instead.
142 onMouseUp: function(e){
144 // event processor for onmouseup
148 if(this.target && this.canDropFlag){
149 var copy = Boolean(this.source.copyState(dnd.getCopyKeyState(e)));
150 topic.publish("/dnd/drop/before", this.source, this.nodes, copy, this.target, e);
151 topic.publish("/dnd/drop", this.source, this.nodes, copy, this.target, e);
153 topic.publish("/dnd/cancel");
159 // keyboard event processors
160 onKeyDown: function(e){
162 // event processor for onkeydown:
163 // watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
169 var copy = Boolean(this.source.copyState(true));
170 if(this.copy != copy){
171 this._setCopyStatus(copy);
175 topic.publish("/dnd/cancel");
181 onKeyUp: function(e){
183 // event processor for onkeyup, watching for CTRL for copy/move status
186 if(this.avatar && e.keyCode == keys.CTRL){
187 var copy = Boolean(this.source.copyState(false));
188 if(this.copy != copy){
189 this._setCopyStatus(copy);
195 _setCopyStatus: function(copy){
197 // changes the copy status
201 this.source._markDndStatus(this.copy);
203 domClass.replace(win.body(),
204 "dojoDnd" + (this.copy ? "Copy" : "Move"),
205 "dojoDnd" + (this.copy ? "Move" : "Copy"));
210 // The manager singleton variable. Can be overwritten if needed.
213 Manager.manager = dnd.manager = function(){
215 // Returns the current DnD manager. Creates one if it is not created yet.
217 dnd._manager = new Manager();
219 return dnd._manager; // Object