source: Dev/branches/rest-dojo-ui/client/dojo/dnd/Selector.js @ 263

Last change on this file since 263 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 8.5 KB
Line 
1define(["../main", "./common", "./Container"], function(dojo) {
2        // module:
3        //              dojo/dnd/Selector
4        // summary:
5        //              TODOC
6
7
8/*
9        Container item states:
10                ""                      - an item is not selected
11                "Selected"      - an item is selected
12                "Anchor"        - an item is selected, and is an anchor for a "shift" selection
13*/
14
15/*=====
16dojo.declare("dojo.dnd.__SelectorArgs", [dojo.dnd.__ContainerArgs], {
17        //      singular: Boolean
18        //              allows selection of only one element, if true
19        singular: false,
20
21        //      autoSync: Boolean
22        //              autosynchronizes the source with its list of DnD nodes,
23        autoSync: false
24});
25=====*/
26
27dojo.declare("dojo.dnd.Selector", dojo.dnd.Container, {
28        // summary:
29        //              a Selector object, which knows how to select its children
30
31        /*=====
32        // selection: Set<String>
33        //              The set of id's that are currently selected, such that this.selection[id] == 1
34        //              if the node w/that id is selected.  Can iterate over selected node's id's like:
35        //      |               for(var id in this.selection)
36        selection: {},
37        =====*/
38
39        constructor: function(node, params){
40                // summary:
41                //              constructor of the Selector
42                // node: Node||String
43                //              node or node's id to build the selector on
44                // params: dojo.dnd.__SelectorArgs?
45                //              a dictionary of parameters
46                if(!params){ params = {}; }
47                this.singular = params.singular;
48                this.autoSync = params.autoSync;
49                // class-specific variables
50                this.selection = {};
51                this.anchor = null;
52                this.simpleSelection = false;
53                // set up events
54                this.events.push(
55                        dojo.connect(this.node, "onmousedown", this, "onMouseDown"),
56                        dojo.connect(this.node, "onmouseup",   this, "onMouseUp"));
57        },
58
59        // object attributes (for markup)
60        singular: false,        // is singular property
61
62        // methods
63        getSelectedNodes: function(){
64                // summary:
65                //              returns a list (an array) of selected nodes
66                var t = new dojo.NodeList();
67                var e = dojo.dnd._empty;
68                for(var i in this.selection){
69                        if(i in e){ continue; }
70                        t.push(dojo.byId(i));
71                }
72                return t;       // NodeList
73        },
74        selectNone: function(){
75                // summary:
76                //              unselects all items
77                return this._removeSelection()._removeAnchor(); // self
78        },
79        selectAll: function(){
80                // summary:
81                //              selects all items
82                this.forInItems(function(data, id){
83                        this._addItemClass(dojo.byId(id), "Selected");
84                        this.selection[id] = 1;
85                }, this);
86                return this._removeAnchor();    // self
87        },
88        deleteSelectedNodes: function(){
89                // summary:
90                //              deletes all selected items
91                var e = dojo.dnd._empty;
92                for(var i in this.selection){
93                        if(i in e){ continue; }
94                        var n = dojo.byId(i);
95                        this.delItem(i);
96                        dojo.destroy(n);
97                }
98                this.anchor = null;
99                this.selection = {};
100                return this;    // self
101        },
102        forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
103                // summary:
104                //              iterates over selected items;
105                //              see `dojo.dnd.Container.forInItems()` for details
106                o = o || dojo.global;
107                var s = this.selection, e = dojo.dnd._empty;
108                for(var i in s){
109                        if(i in e){ continue; }
110                        f.call(o, this.getItem(i), i, this);
111                }
112        },
113        sync: function(){
114                // summary:
115                //              sync up the node list with the data map
116
117                dojo.dnd.Selector.superclass.sync.call(this);
118
119                // fix the anchor
120                if(this.anchor){
121                        if(!this.getItem(this.anchor.id)){
122                                this.anchor = null;
123                        }
124                }
125
126                // fix the selection
127                var t = [], e = dojo.dnd._empty;
128                for(var i in this.selection){
129                        if(i in e){ continue; }
130                        if(!this.getItem(i)){
131                                t.push(i);
132                        }
133                }
134                dojo.forEach(t, function(i){
135                        delete this.selection[i];
136                }, this);
137
138                return this;    // self
139        },
140        insertNodes: function(addSelected, data, before, anchor){
141                // summary:
142                //              inserts new data items (see `dojo.dnd.Container.insertNodes()` method for details)
143                // addSelected: Boolean
144                //              all new nodes will be added to selected items, if true, no selection change otherwise
145                // data: Array
146                //              a list of data items, which should be processed by the creator function
147                // before: Boolean
148                //              insert before the anchor, if true, and after the anchor otherwise
149                // anchor: Node
150                //              the anchor node to be used as a point of insertion
151                var oldCreator = this._normalizedCreator;
152                this._normalizedCreator = function(item, hint){
153                        var t = oldCreator.call(this, item, hint);
154                        if(addSelected){
155                                if(!this.anchor){
156                                        this.anchor = t.node;
157                                        this._removeItemClass(t.node, "Selected");
158                                        this._addItemClass(this.anchor, "Anchor");
159                                }else if(this.anchor != t.node){
160                                        this._removeItemClass(t.node, "Anchor");
161                                        this._addItemClass(t.node, "Selected");
162                                }
163                                this.selection[t.node.id] = 1;
164                        }else{
165                                this._removeItemClass(t.node, "Selected");
166                                this._removeItemClass(t.node, "Anchor");
167                        }
168                        return t;
169                };
170                dojo.dnd.Selector.superclass.insertNodes.call(this, data, before, anchor);
171                this._normalizedCreator = oldCreator;
172                return this;    // self
173        },
174        destroy: function(){
175                // summary:
176                //              prepares the object to be garbage-collected
177                dojo.dnd.Selector.superclass.destroy.call(this);
178                this.selection = this.anchor = null;
179        },
180
181        // mouse events
182        onMouseDown: function(e){
183                // summary:
184                //              event processor for onmousedown
185                // e: Event
186                //              mouse event
187                if(this.autoSync){ this.sync(); }
188                if(!this.current){ return; }
189                if(!this.singular && !dojo.isCopyKey(e) && !e.shiftKey && (this.current.id in this.selection)){
190                        this.simpleSelection = true;
191                        if(e.button === dojo.mouseButtons.LEFT){
192                                // accept the left button and stop the event
193                                // for IE we don't stop event when multiple buttons are pressed
194                                dojo.stopEvent(e);
195                        }
196                        return;
197                }
198                if(!this.singular && e.shiftKey){
199                        if(!dojo.isCopyKey(e)){
200                                this._removeSelection();
201                        }
202                        var c = this.getAllNodes();
203                        if(c.length){
204                                if(!this.anchor){
205                                        this.anchor = c[0];
206                                        this._addItemClass(this.anchor, "Anchor");
207                                }
208                                this.selection[this.anchor.id] = 1;
209                                if(this.anchor != this.current){
210                                        var i = 0;
211                                        for(; i < c.length; ++i){
212                                                var node = c[i];
213                                                if(node == this.anchor || node == this.current){ break; }
214                                        }
215                                        for(++i; i < c.length; ++i){
216                                                var node = c[i];
217                                                if(node == this.anchor || node == this.current){ break; }
218                                                this._addItemClass(node, "Selected");
219                                                this.selection[node.id] = 1;
220                                        }
221                                        this._addItemClass(this.current, "Selected");
222                                        this.selection[this.current.id] = 1;
223                                }
224                        }
225                }else{
226                        if(this.singular){
227                                if(this.anchor == this.current){
228                                        if(dojo.isCopyKey(e)){
229                                                this.selectNone();
230                                        }
231                                }else{
232                                        this.selectNone();
233                                        this.anchor = this.current;
234                                        this._addItemClass(this.anchor, "Anchor");
235                                        this.selection[this.current.id] = 1;
236                                }
237                        }else{
238                                if(dojo.isCopyKey(e)){
239                                        if(this.anchor == this.current){
240                                                delete this.selection[this.anchor.id];
241                                                this._removeAnchor();
242                                        }else{
243                                                if(this.current.id in this.selection){
244                                                        this._removeItemClass(this.current, "Selected");
245                                                        delete this.selection[this.current.id];
246                                                }else{
247                                                        if(this.anchor){
248                                                                this._removeItemClass(this.anchor, "Anchor");
249                                                                this._addItemClass(this.anchor, "Selected");
250                                                        }
251                                                        this.anchor = this.current;
252                                                        this._addItemClass(this.current, "Anchor");
253                                                        this.selection[this.current.id] = 1;
254                                                }
255                                        }
256                                }else{
257                                        if(!(this.current.id in this.selection)){
258                                                this.selectNone();
259                                                this.anchor = this.current;
260                                                this._addItemClass(this.current, "Anchor");
261                                                this.selection[this.current.id] = 1;
262                                        }
263                                }
264                        }
265                }
266                dojo.stopEvent(e);
267        },
268        onMouseUp: function(e){
269                // summary:
270                //              event processor for onmouseup
271                // e: Event
272                //              mouse event
273                if(!this.simpleSelection){ return; }
274                this.simpleSelection = false;
275                this.selectNone();
276                if(this.current){
277                        this.anchor = this.current;
278                        this._addItemClass(this.anchor, "Anchor");
279                        this.selection[this.current.id] = 1;
280                }
281        },
282        onMouseMove: function(e){
283                // summary:
284                //              event processor for onmousemove
285                // e: Event
286                //              mouse event
287                this.simpleSelection = false;
288        },
289
290        // utilities
291        onOverEvent: function(){
292                // summary:
293                //              this function is called once, when mouse is over our container
294                this.onmousemoveEvent = dojo.connect(this.node, "onmousemove", this, "onMouseMove");
295        },
296        onOutEvent: function(){
297                // summary:
298                //              this function is called once, when mouse is out of our container
299                dojo.disconnect(this.onmousemoveEvent);
300                delete this.onmousemoveEvent;
301        },
302        _removeSelection: function(){
303                // summary:
304                //              unselects all items
305                var e = dojo.dnd._empty;
306                for(var i in this.selection){
307                        if(i in e){ continue; }
308                        var node = dojo.byId(i);
309                        if(node){ this._removeItemClass(node, "Selected"); }
310                }
311                this.selection = {};
312                return this;    // self
313        },
314        _removeAnchor: function(){
315                if(this.anchor){
316                        this._removeItemClass(this.anchor, "Anchor");
317                        this.anchor = null;
318                }
319                return this;    // self
320        }
321});
322
323return dojo.dnd.Selector;
324});
Note: See TracBrowser for help on using the repository browser.