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 = function(config){
17 * @event selectionchange
18 * Fires when the selected node changes
19 * @param {DefaultSelectionModel} this
20 * @param {TreeNode} node the new selection
26 * Fires before the selected node changes, return false to cancel the change
27 * @param {DefaultSelectionModel} this
28 * @param {TreeNode} node the new selection
29 * @param {TreeNode} node the old selection
34 Ext.apply(this, config);
35 Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
38 Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
39 init : function(tree){
41 tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
42 tree.on('click', this.onNodeClick, this);
45 onNodeClick : function(node, e){
51 * @param {TreeNode} node The node to select
52 * @return {TreeNode} The selected node
54 select : function(node, /* private*/ selectNextNode){
55 // If node is hidden, select the next node in whatever direction was being moved in.
56 if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
57 return selectNextNode.call(this, node);
59 var last = this.selNode;
61 node.ui.onSelectedChange(true);
62 }else if(this.fireEvent('beforeselect', this, node, last) !== false){
64 last.ui.onSelectedChange(false);
67 node.ui.onSelectedChange(true);
68 this.fireEvent('selectionchange', this, node, last);
75 * @param {TreeNode} node The node to unselect
76 * @param {Boolean} silent True to stop the selectionchange event from firing.
78 unselect : function(node, silent){
79 if(this.selNode == node){
80 this.clearSelections(silent);
85 * Clear all selections
86 * @param {Boolean} silent True to stop the selectionchange event from firing.
88 clearSelections : function(silent){
91 n.ui.onSelectedChange(false);
94 this.fireEvent('selectionchange', this, null);
101 * Get the selected node
102 * @return {TreeNode} The selected node
104 getSelectedNode : function(){
109 * Returns true if the node is selected
110 * @param {TreeNode} node The node to check
113 isSelected : function(node){
114 return this.selNode == node;
118 * Selects the node above the selected node in the tree, intelligently walking the nodes
119 * @return TreeNode The new selection
121 selectPrevious : function(/* private */ s){
122 if(!(s = s || this.selNode || this.lastSelNode)){
125 // Here we pass in the current function to select to indicate the direction we're moving
126 var ps = s.previousSibling;
128 if(!ps.isExpanded() || ps.childNodes.length < 1){
129 return this.select(ps, this.selectPrevious);
131 var lc = ps.lastChild;
132 while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
135 return this.select(lc, this.selectPrevious);
137 } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
138 return this.select(s.parentNode, this.selectPrevious);
144 * Selects the node above the selected node in the tree, intelligently walking the nodes
145 * @return TreeNode The new selection
147 selectNext : function(/* private */ s){
148 if(!(s = s || this.selNode || this.lastSelNode)){
151 // Here we pass in the current function to select to indicate the direction we're moving
152 if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
153 return this.select(s.firstChild, this.selectNext);
154 }else if(s.nextSibling){
155 return this.select(s.nextSibling, this.selectNext);
156 }else if(s.parentNode){
158 s.parentNode.bubble(function(){
159 if(this.nextSibling){
160 newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
169 onKeyDown : function(e){
170 var s = this.selNode || this.lastSelNode;
171 // undesirable, but required
184 this.selectPrevious();
188 if(s.hasChildNodes()){
191 }else if(s.firstChild){
192 this.select(s.firstChild, e);
198 if(s.hasChildNodes() && s.isExpanded()){
200 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
201 this.select(s.parentNode, e);
209 * @class Ext.tree.MultiSelectionModel
210 * @extends Ext.util.Observable
211 * Multi selection for a TreePanel.
213 Ext.tree.MultiSelectionModel = function(config){
218 * @event selectionchange
219 * Fires when the selected nodes change
220 * @param {MultiSelectionModel} this
221 * @param {Array} nodes Array of the selected nodes
225 Ext.apply(this, config);
226 Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
229 Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
230 init : function(tree){
232 tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
233 tree.on('click', this.onNodeClick, this);
236 onNodeClick : function(node, e){
237 if(e.ctrlKey && this.isSelected(node)){
240 this.select(node, e, e.ctrlKey);
246 * @param {TreeNode} node The node to select
247 * @param {EventObject} e (optional) An event associated with the selection
248 * @param {Boolean} keepExisting True to retain existing selections
249 * @return {TreeNode} The selected node
251 select : function(node, e, keepExisting){
252 if(keepExisting !== true){
253 this.clearSelections(true);
255 if(this.isSelected(node)){
256 this.lastSelNode = node;
259 this.selNodes.push(node);
260 this.selMap[node.id] = node;
261 this.lastSelNode = node;
262 node.ui.onSelectedChange(true);
263 this.fireEvent('selectionchange', this, this.selNodes);
269 * @param {TreeNode} node The node to unselect
271 unselect : function(node){
272 if(this.selMap[node.id]){
273 node.ui.onSelectedChange(false);
274 var sn = this.selNodes;
275 var index = sn.indexOf(node);
277 this.selNodes.splice(index, 1);
279 delete this.selMap[node.id];
280 this.fireEvent('selectionchange', this, this.selNodes);
285 * Clear all selections
287 clearSelections : function(suppressEvent){
288 var sn = this.selNodes;
290 for(var i = 0, len = sn.length; i < len; i++){
291 sn[i].ui.onSelectedChange(false);
295 if(suppressEvent !== true){
296 this.fireEvent('selectionchange', this, this.selNodes);
302 * Returns true if the node is selected
303 * @param {TreeNode} node The node to check
306 isSelected : function(node){
307 return this.selMap[node.id] ? true : false;
311 * Returns an array of the selected nodes
314 getSelectedNodes : function(){
315 return this.selNodes;
318 onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
320 selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
322 selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious