]>
git.wh0rd.org - tt-rss.git/blob - lib/dijit/tree/_dndSelector.js.uncompressed.js
1 define("dijit/tree/_dndSelector", [
2 "dojo/_base/array", // array.filter array.forEach array.map
3 "dojo/_base/connect", // connect.isCopyKey
4 "dojo/_base/declare", // declare
5 "dojo/_base/lang", // lang.hitch
6 "dojo/mouse", // mouse.isLeft
9 "dojo/_base/window", // win.global
11 ], function(array
, connect
, declare
, lang
, mouse
, on
, touch
, win
, _dndContainer
){
14 // dijit/tree/_dndSelector
16 // This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
17 // It's based on `dojo.dnd.Selector`.
20 return declare("dijit.tree._dndSelector", _dndContainer
, {
22 // This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
23 // It's based on `dojo.dnd.Selector`.
28 // selection: Hash<String, DomNode>
29 // (id, DomNode) map for every TreeNode that's currently selected.
30 // The DOMNode is the TreeNode.rowNode.
34 constructor: function(){
43 this.tree
.domNode
.setAttribute("aria-multiselect", !this.singular
);
46 on(this.tree
.domNode
, touch
.press
, lang
.hitch(this,"onMouseDown")),
47 on(this.tree
.domNode
, touch
.release
, lang
.hitch(this,"onMouseUp")),
48 on(this.tree
.domNode
, touch
.move, lang
.hitch(this,"onMouseMove"))
53 // Allows selection of only one element, if true.
54 // Tree hasn't been tested in singular=true mode, unclear if it works.
58 getSelectedTreeNodes: function(){
60 // Returns a list of selected node(s).
61 // Used by dndSource on the start of a drag.
64 var nodes
=[], sel
= this.selection
;
71 selectNone: function(){
73 // Unselects all items
77 this.setSelection([]);
83 // Prepares the object to be garbage-collected
84 this.inherited(arguments
);
85 this.selection
= this.anchor
= null;
87 addTreeNode: function(/*dijit._TreeNode*/node
, /*Boolean?*/isAnchor
){
89 // add node to current selection
93 // Whether the node should become anchor.
95 this.setSelection(this.getSelectedTreeNodes().concat( [node
] ));
96 if(isAnchor
){ this.anchor
= node
; }
99 removeTreeNode: function(/*dijit._TreeNode*/node
){
101 // remove node from current selection
104 this.setSelection(this._setDifference(this.getSelectedTreeNodes(), [node
]));
107 isTreeNodeSelected: function(/*dijit._TreeNode*/node
){
109 // return true if node is currently selected
111 // the node to check whether it's in the current selection
113 return node
.id
&& !!this.selection
[node
.id
];
115 setSelection: function(/*dijit._treeNode[]*/ newSelection
){
117 // set the list of selected nodes to be exactly newSelection. All changes to the
118 // selection should be passed through this function, which ensures that derived
119 // attributes are kept up to date. Anchor will be deleted if it has been removed
120 // from the selection, but no new anchor will be added by this function.
121 // newSelection: Node[]
122 // list of tree nodes to make selected
123 var oldSelection
= this.getSelectedTreeNodes();
124 array
.forEach(this._setDifference(oldSelection
, newSelection
), lang
.hitch(this, function(node
){
125 node
.setSelected(false);
126 if(this.anchor
== node
){
129 delete this.selection
[node
.id
];
131 array
.forEach(this._setDifference(newSelection
, oldSelection
), lang
.hitch(this, function(node
){
132 node
.setSelected(true);
133 this.selection
[node
.id
] = node
;
135 this._updateSelectionProperties();
137 _setDifference: function(xs
,ys
){
139 // Returns a copy of xs which lacks any objects
140 // occurring in ys. Checks for membership by
141 // modifying and then reading the object, so it will
142 // not properly handle sets of numbers or strings.
144 array
.forEach(ys
, function(y
){ y
.__exclude__
= true; });
145 var ret
= array
.filter(xs
, function(x
){ return !x
.__exclude__
; });
147 // clean up after ourselves.
148 array
.forEach(ys
, function(y
){ delete y
['__exclude__'] });
151 _updateSelectionProperties: function(){
153 // Update the following tree properties from the current selection:
154 // path[s], selectedItem[s], selectedNode[s]
156 var selected
= this.getSelectedTreeNodes();
157 var paths
= [], nodes
= [];
158 array
.forEach(selected
, function(node
){
160 paths
.push(node
.getTreePath());
162 var items
= array
.map(nodes
,function(node
){ return node
.item
; });
163 this.tree
._set("paths", paths
);
164 this.tree
._set("path", paths
[0] || []);
165 this.tree
._set("selectedNodes", nodes
);
166 this.tree
._set("selectedNode", nodes
[0] || null);
167 this.tree
._set("selectedItems", items
);
168 this.tree
._set("selectedItem", items
[0] || null);
171 onMouseDown: function(e
){
173 // Event processor for onmousedown/ontouchstart
175 // onmousedown/ontouchstart event
179 // ignore click on expando node
180 if(!this.current
|| this.tree
.isExpandoNode(e
.target
, this.current
)){ return; }
182 if(!mouse
.isLeft(e
)){ return; } // ignore right-click
186 var treeNode
= this.current
,
187 copy
= connect
.isCopyKey(e
), id
= treeNode
.id
;
189 // if shift key is not pressed, and the node is already in the selection,
190 // delay deselection until onmouseup so in the case of DND, deselection
191 // will be canceled by onmousemove.
192 if(!this.singular
&& !e
.shiftKey
&& this.selection
[id
]){
193 this._doDeselect
= true;
196 this._doDeselect
= false;
198 this.userSelect(treeNode
, copy
, e
.shiftKey
);
201 onMouseUp: function(e
){
203 // Event processor for onmouseup/ontouchend
205 // onmouseup/ontouchend event
209 // _doDeselect is the flag to indicate that the user wants to either ctrl+click on
210 // a already selected item (to deselect the item), or click on a not-yet selected item
211 // (which should remove all current selection, and add the clicked item). This can not
212 // be done in onMouseDown, because the user may start a drag after mousedown. By moving
213 // the deselection logic here, the user can drags an already selected item.
214 if(!this._doDeselect
){ return; }
215 this._doDeselect
= false;
216 this.userSelect(this.current
, connect
.isCopyKey(e
), e
.shiftKey
);
218 onMouseMove: function(/*===== e =====*/){
220 // event processor for onmousemove/ontouchmove
222 // onmousemove/ontouchmove event
223 this._doDeselect
= false;
226 _compareNodes: function(n1
, n2
){
231 if('sourceIndex' in document
.documentElement
){ //IE
232 //TODO: does not yet work if n1 and/or n2 is a text node
233 return n1
.sourceIndex
- n2
.sourceIndex
;
234 }else if('compareDocumentPosition' in document
.documentElement
){ //FF, Opera
235 return n1
.compareDocumentPosition(n2
) & 2 ? 1: -1;
236 }else if(document
.createRange
){ //Webkit
237 var r1
= doc
.createRange();
238 r1
.setStartBefore(n1
);
240 var r2
= doc
.createRange();
241 r2
.setStartBefore(n2
);
243 return r1
.compareBoundaryPoints(r1
.END_TO_END
, r2
);
245 throw Error("dijit.tree._compareNodes don't know how to compare two different nodes in this browser");
249 userSelect: function(node
, multi
, range
){
251 // Add or remove the given node from selection, responding
252 // to a user action such as a click or keypress.
254 // Indicates whether this is meant to be a multi-select action (e.g. ctrl-click)
256 // Indicates whether this is meant to be a ranged action (e.g. shift-click)
261 if(this.anchor
== node
&& multi
){
264 this.setSelection([node
]);
268 if(range
&& this.anchor
){
269 var cr
= this._compareNodes(this.anchor
.rowNode
, node
.rowNode
),
270 begin
, end
, anchor
= this.anchor
;
272 if(cr
< 0){ //current is after anchor
275 }else{ //current is before anchor
280 //add everything betweeen begin and end inclusively
283 begin
= this.tree
._getNextNode(begin
);
287 this.setSelection(nodes
);
289 if( this.selection
[ node
.id
] && multi
){
290 this.removeTreeNode( node
);
292 this.addTreeNode(node
, true);
294 this.setSelection([node
]);
301 getItem: function(/*String*/ key
){
303 // Returns the dojo.dnd.Item (representing a dragged node) by it's key (id).
304 // Called by dojo.dnd.Source.checkAcceptance().
308 var widget
= this.selection
[key
];
315 forInSelectedItems: function(/*Function*/ f
, /*Object?*/ o
){
317 // Iterates over selected items;
318 // see `dojo.dnd.Container.forInItems()` for details
320 for(var id
in this.selection
){
321 // console.log("selected item id: " + id);
322 f
.call(o
, this.getItem(id
), id
, this);