source: Dev/trunk/src/client/dojo/dnd/Manager.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 6.2 KB
Line 
1define([
2        "../_base/array",  "../_base/declare", "../_base/lang", "../_base/window",
3        "../dom-class", "../Evented", "../has", "../keys", "../on", "../topic", "../touch",
4        "./common", "./autoscroll", "./Avatar"
5], function(array, declare, lang, win, domClass, Evented, has, keys, on, topic, touch,
6        dnd, autoscroll, Avatar){
7
8// module:
9//              dojo/dnd/Manager
10
11var Manager = declare("dojo.dnd.Manager", [Evented], {
12        // summary:
13        //              the manager of DnD operations (usually a singleton)
14        constructor: function(){
15                this.avatar  = null;
16                this.source = null;
17                this.nodes = [];
18                this.copy  = true;
19                this.target = null;
20                this.canDropFlag = false;
21                this.events = [];
22        },
23
24        // avatar's offset from the mouse
25        OFFSET_X: has("touch") ? 0 : 16,
26        OFFSET_Y: has("touch") ? -64 : 16,
27
28        // methods
29        overSource: function(source){
30                // summary:
31                //              called when a source detected a mouse-over condition
32                // source: Object
33                //              the reporter
34                if(this.avatar){
35                        this.target = (source && source.targetState != "Disabled") ? source : null;
36                        this.canDropFlag = Boolean(this.target);
37                        this.avatar.update();
38                }
39                topic.publish("/dnd/source/over", source);
40        },
41        outSource: function(source){
42                // summary:
43                //              called when a source detected a mouse-out condition
44                // source: Object
45                //              the reporter
46                if(this.avatar){
47                        if(this.target == source){
48                                this.target = null;
49                                this.canDropFlag = false;
50                                this.avatar.update();
51                                topic.publish("/dnd/source/over", null);
52                        }
53                }else{
54                        topic.publish("/dnd/source/over", null);
55                }
56        },
57        startDrag: function(source, nodes, copy){
58                // summary:
59                //              called to initiate the DnD operation
60                // source: Object
61                //              the source which provides items
62                // nodes: Array
63                //              the list of transferred items
64                // copy: Boolean
65                //              copy items, if true, move items otherwise
66
67                // Tell autoscroll that a drag is starting
68                autoscroll.autoScrollStart(win.doc);
69
70                this.source = source;
71                this.nodes  = nodes;
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);
76
77                function stopEvent(e){
78                        e.preventDefault();
79                        e.stopPropagation();
80                }
81
82                this.events = [
83                        on(win.doc, touch.move, lang.hitch(this, "onMouseMove")),
84                        on(win.doc, touch.release,   lang.hitch(this, "onMouseUp")),
85                        on(win.doc, "keydown",   lang.hitch(this, "onKeyDown")),
86                        on(win.doc, "keyup",     lang.hitch(this, "onKeyUp")),
87
88                        // cancel text selection and text dragging
89                        on(win.doc, "dragstart",   stopEvent),
90                        on(win.body(), "selectstart", stopEvent)
91                ];
92                var c = "dojoDnd" + (copy ? "Copy" : "Move");
93                domClass.add(win.body(), c);
94        },
95        canDrop: function(flag){
96                // summary:
97                //              called to notify if the current target can accept items
98                var canDropFlag = Boolean(this.target && flag);
99                if(this.canDropFlag != canDropFlag){
100                        this.canDropFlag = canDropFlag;
101                        this.avatar.update();
102                }
103        },
104        stopDrag: function(){
105                // summary:
106                //              stop the DnD in progress
107                domClass.remove(win.body(), ["dojoDndCopy", "dojoDndMove"]);
108                array.forEach(this.events, function(handle){ handle.remove(); });
109                this.events = [];
110                this.avatar.destroy();
111                this.avatar = null;
112                this.source = this.target = null;
113                this.nodes = [];
114        },
115        makeAvatar: function(){
116                // summary:
117                //              makes the avatar; it is separate to be overwritten dynamically, if needed
118                return new Avatar(this);
119        },
120        updateAvatar: function(){
121                // summary:
122                //              updates the avatar; it is separate to be overwritten dynamically, if needed
123                this.avatar.update();
124        },
125
126        // mouse event processors
127        onMouseMove: function(e){
128                // summary:
129                //              event processor for onmousemove
130                // e: Event
131                //              mouse event
132                var a = this.avatar;
133                if(a){
134                        autoscroll.autoScrollNodes(e);
135                        //autoscroll.autoScroll(e);
136                        var s = a.node.style;
137                        s.left = (e.pageX + this.OFFSET_X) + "px";
138                        s.top  = (e.pageY + this.OFFSET_Y) + "px";
139                        var copy = Boolean(this.source.copyState(dnd.getCopyKeyState(e)));
140                        if(this.copy != copy){
141                                this._setCopyStatus(copy);
142                        }
143                }
144                if(has("touch")){
145                        // Prevent page from scrolling so that user can drag instead.
146                        e.preventDefault();
147                }
148        },
149        onMouseUp: function(e){
150                // summary:
151                //              event processor for onmouseup
152                // e: Event
153                //              mouse event
154                if(this.avatar){
155                        if(this.target && this.canDropFlag){
156                                var copy = Boolean(this.source.copyState(dnd.getCopyKeyState(e)));
157                                topic.publish("/dnd/drop/before", this.source, this.nodes, copy, this.target, e);
158                                topic.publish("/dnd/drop", this.source, this.nodes, copy, this.target, e);
159                        }else{
160                                topic.publish("/dnd/cancel");
161                        }
162                        this.stopDrag();
163                }
164        },
165
166        // keyboard event processors
167        onKeyDown: function(e){
168                // summary:
169                //              event processor for onkeydown:
170                //              watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
171                // e: Event
172                //              keyboard event
173                if(this.avatar){
174                        switch(e.keyCode){
175                                case keys.CTRL:
176                                        var copy = Boolean(this.source.copyState(true));
177                                        if(this.copy != copy){
178                                                this._setCopyStatus(copy);
179                                        }
180                                        break;
181                                case keys.ESCAPE:
182                                        topic.publish("/dnd/cancel");
183                                        this.stopDrag();
184                                        break;
185                        }
186                }
187        },
188        onKeyUp: function(e){
189                // summary:
190                //              event processor for onkeyup, watching for CTRL for copy/move status
191                // e: Event
192                //              keyboard event
193                if(this.avatar && e.keyCode == keys.CTRL){
194                        var copy = Boolean(this.source.copyState(false));
195                        if(this.copy != copy){
196                                this._setCopyStatus(copy);
197                        }
198                }
199        },
200
201        // utilities
202        _setCopyStatus: function(copy){
203                // summary:
204                //              changes the copy status
205                // copy: Boolean
206                //              the copy status
207                this.copy = copy;
208                this.source._markDndStatus(this.copy);
209                this.updateAvatar();
210                domClass.replace(win.body(),
211                        "dojoDnd" + (this.copy ? "Copy" : "Move"),
212                        "dojoDnd" + (this.copy ? "Move" : "Copy"));
213        }
214});
215
216// dnd._manager:
217//              The manager singleton variable. Can be overwritten if needed.
218dnd._manager = null;
219
220Manager.manager = dnd.manager = function(){
221        // summary:
222        //              Returns the current DnD manager.  Creates one if it is not created yet.
223        if(!dnd._manager){
224                dnd._manager = new Manager();
225        }
226        return dnd._manager;    // Object
227};
228
229// TODO: for 2.0, store _manager and manager in Manager only.   Don't access dnd or dojo.dnd.
230
231return Manager;
232});
Note: See TracBrowser for help on using the repository browser.