]> git.wh0rd.org - tt-rss.git/blame - lib/dojo/dnd/Selector.js
upgrade Dojo to 1.6.1
[tt-rss.git] / lib / dojo / dnd / Selector.js
CommitLineData
2f01fe57 1/*
81bea17a 2 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
2f01fe57
AD
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
5*/
6
7
a089699c
AD
8if(!dojo._hasResource["dojo.dnd.Selector"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9dojo._hasResource["dojo.dnd.Selector"] = true;
2f01fe57
AD
10dojo.provide("dojo.dnd.Selector");
11dojo.require("dojo.dnd.common");
12dojo.require("dojo.dnd.Container");
a089699c 13
81bea17a 14
a089699c
AD
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/*=====
23dojo.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
34dojo.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
2f01fe57 336}