3 * Copyright(c) 2006-2010 Ext JS, Inc.
5 * http://www.extjs.com/license
8 * @class Ext.tree.DefaultSelectionModel
9 * @extends Ext.util.Observable
10 * The default single selection for a TreePanel.
12 Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
14 constructor : function(config){
19 * @event selectionchange
20 * Fires when the selected node changes
21 * @param {DefaultSelectionModel} this
22 * @param {TreeNode} node the new selection
28 * Fires before the selected node changes, return false to cancel the change
29 * @param {DefaultSelectionModel} this
30 * @param {TreeNode} node the new selection
31 * @param {TreeNode} node the old selection
36 Ext.apply(this, config);
37 Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
40 init : function(tree){
42 tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
43 tree.on('click', this.onNodeClick, this);
46 onNodeClick : function(node, e){
52 * @param {TreeNode} node The node to select
53 * @return {TreeNode} The selected node
55 select : function(node, /* private*/ selectNextNode){
56 // If node is hidden, select the next node in whatever direction was being moved in.
57 if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
58 return selectNextNode.call(this, node);
60 var last = this.selNode;
62 node.ui.onSelectedChange(true);
63 }else if(this.fireEvent('beforeselect', this, node, last) !== false){
65 last.ui.onSelectedChange(false);
68 node.ui.onSelectedChange(true);
69 this.fireEvent('selectionchange', this, node, last);
76 * @param {TreeNode} node The node to unselect
77 * @param {Boolean} silent True to stop the selectionchange event from firing.
79 unselect : function(node, silent){
80 if(this.selNode == node){
81 this.clearSelections(silent);
86 * Clear all selections
87 * @param {Boolean} silent True to stop the selectionchange event from firing.
89 clearSelections : function(silent){
92 n.ui.onSelectedChange(false);
95 this.fireEvent('selectionchange', this, null);
102 * Get the selected node
103 * @return {TreeNode} The selected node
105 getSelectedNode : function(){
110 * Returns true if the node is selected
111 * @param {TreeNode} node The node to check
114 isSelected : function(node){
115 return this.selNode == node;
119 * Selects the node above the selected node in the tree, intelligently walking the nodes
120 * @return TreeNode The new selection
122 selectPrevious : function(/* private */ s){
123 if(!(s = s || this.selNode || this.lastSelNode)){
126 // Here we pass in the current function to select to indicate the direction we're moving
127 var ps = s.previousSibling;
129 if(!ps.isExpanded() || ps.childNodes.length < 1){
130 return this.select(ps, this.selectPrevious);
132 var lc = ps.lastChild;
133 while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
136 return this.select(lc, this.selectPrevious);
138 } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
139 return this.select(s.parentNode, this.selectPrevious);
145 * Selects the node above the selected node in the tree, intelligently walking the nodes
146 * @return TreeNode The new selection
148 selectNext : function(/* private */ s){
149 if(!(s = s || this.selNode || this.lastSelNode)){
152 // Here we pass in the current function to select to indicate the direction we're moving
153 if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
154 return this.select(s.firstChild, this.selectNext);
155 }else if(s.nextSibling){
156 return this.select(s.nextSibling, this.selectNext);
157 }else if(s.parentNode){
159 s.parentNode.bubble(function(){
160 if(this.nextSibling){
161 newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
170 onKeyDown : function(e){
171 var s = this.selNode || this.lastSelNode;
172 // undesirable, but required
185 this.selectPrevious();
189 if(s.hasChildNodes()){
192 }else if(s.firstChild){
193 this.select(s.firstChild, e);
199 if(s.hasChildNodes() && s.isExpanded()){
201 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
202 this.select(s.parentNode, e);
210 * @class Ext.tree.MultiSelectionModel
211 * @extends Ext.util.Observable
212 * Multi selection for a TreePanel.
214 Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
216 constructor : function(config){
221 * @event selectionchange
222 * Fires when the selected nodes change
223 * @param {MultiSelectionModel} this
224 * @param {Array} nodes Array of the selected nodes
228 Ext.apply(this, config);
229 Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
232 init : function(tree){
234 tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
235 tree.on('click', this.onNodeClick, this);
238 onNodeClick : function(node, e){
239 if(e.ctrlKey && this.isSelected(node)){
242 this.select(node, e, e.ctrlKey);
248 * @param {TreeNode} node The node to select
249 * @param {EventObject} e (optional) An event associated with the selection
250 * @param {Boolean} keepExisting True to retain existing selections
251 * @return {TreeNode} The selected node
253 select : function(node, e, keepExisting){
254 if(keepExisting !== true){
255 this.clearSelections(true);
257 if(this.isSelected(node)){
258 this.lastSelNode = node;
261 this.selNodes.push(node);
262 this.selMap[node.id] = node;
263 this.lastSelNode = node;
264 node.ui.onSelectedChange(true);
265 this.fireEvent('selectionchange', this, this.selNodes);
271 * @param {TreeNode} node The node to unselect
273 unselect : function(node){
274 if(this.selMap[node.id]){
275 node.ui.onSelectedChange(false);
276 var sn = this.selNodes;
277 var index = sn.indexOf(node);
279 this.selNodes.splice(index, 1);
281 delete this.selMap[node.id];
282 this.fireEvent('selectionchange', this, this.selNodes);
287 * Clear all selections
289 clearSelections : function(suppressEvent){
290 var sn = this.selNodes;
292 for(var i = 0, len = sn.length; i < len; i++){
293 sn[i].ui.onSelectedChange(false);
297 if(suppressEvent !== true){
298 this.fireEvent('selectionchange', this, this.selNodes);
304 * Returns true if the node is selected
305 * @param {TreeNode} node The node to check
308 isSelected : function(node){
309 return this.selMap[node.id] ? true : false;
313 * Returns an array of the selected nodes
316 getSelectedNodes : function(){
317 return this.selNodes.concat([]);
320 onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
322 selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
324 selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious