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