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