/*! * Ext JS Library 3.0.0 * Copyright(c) 2006-2009 Ext JS, LLC * licensing@extjs.com * http://www.extjs.com/license */ /** * @class Ext.tree.DefaultSelectionModel * @extends Ext.util.Observable * The default single selection for a TreePanel. */ Ext.tree.DefaultSelectionModel = function(config){ this.selNode = null; this.addEvents( /** * @event selectionchange * Fires when the selected node changes * @param {DefaultSelectionModel} this * @param {TreeNode} node the new selection */ "selectionchange", /** * @event beforeselect * Fires before the selected node changes, return false to cancel the change * @param {DefaultSelectionModel} this * @param {TreeNode} node the new selection * @param {TreeNode} node the old selection */ "beforeselect" ); Ext.apply(this, config); Ext.tree.DefaultSelectionModel.superclass.constructor.call(this); }; Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, { init : function(tree){ this.tree = tree; tree.getTreeEl().on("keydown", this.onKeyDown, this); tree.on("click", this.onNodeClick, this); }, onNodeClick : function(node, e){ this.select(node); }, /** * Select a node. * @param {TreeNode} node The node to select * @return {TreeNode} The selected node */ select : function(node){ var last = this.selNode; if(node == last){ node.ui.onSelectedChange(true); }else if(this.fireEvent('beforeselect', this, node, last) !== false){ if(last){ last.ui.onSelectedChange(false); } this.selNode = node; node.ui.onSelectedChange(true); this.fireEvent("selectionchange", this, node, last); } return node; }, /** * Deselect a node. * @param {TreeNode} node The node to unselect */ unselect : function(node){ if(this.selNode == node){ this.clearSelections(); } }, /** * Clear all selections */ clearSelections : function(){ var n = this.selNode; if(n){ n.ui.onSelectedChange(false); this.selNode = null; this.fireEvent("selectionchange", this, null); } return n; }, /** * Get the selected node * @return {TreeNode} The selected node */ getSelectedNode : function(){ return this.selNode; }, /** * Returns true if the node is selected * @param {TreeNode} node The node to check * @return {Boolean} */ isSelected : function(node){ return this.selNode == node; }, /** * Selects the node above the selected node in the tree, intelligently walking the nodes * @return TreeNode The new selection */ selectPrevious : function(){ var s = this.selNode || this.lastSelNode; if(!s){ return null; } var ps = s.previousSibling; if(ps){ if(!ps.isExpanded() || ps.childNodes.length < 1){ return this.select(ps); } else{ var lc = ps.lastChild; while(lc && lc.isExpanded() && lc.childNodes.length > 0){ lc = lc.lastChild; } return this.select(lc); } } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){ return this.select(s.parentNode); } return null; }, /** * Selects the node above the selected node in the tree, intelligently walking the nodes * @return TreeNode The new selection */ selectNext : function(){ var s = this.selNode || this.lastSelNode; if(!s){ return null; } if(s.firstChild && s.isExpanded()){ return this.select(s.firstChild); }else if(s.nextSibling){ return this.select(s.nextSibling); }else if(s.parentNode){ var newS = null; s.parentNode.bubble(function(){ if(this.nextSibling){ newS = this.getOwnerTree().selModel.select(this.nextSibling); return false; } }); return newS; } return null; }, onKeyDown : function(e){ var s = this.selNode || this.lastSelNode; // undesirable, but required var sm = this; if(!s){ return; } var k = e.getKey(); switch(k){ case e.DOWN: e.stopEvent(); this.selectNext(); break; case e.UP: e.stopEvent(); this.selectPrevious(); break; case e.RIGHT: e.preventDefault(); if(s.hasChildNodes()){ if(!s.isExpanded()){ s.expand(); }else if(s.firstChild){ this.select(s.firstChild, e); } } break; case e.LEFT: e.preventDefault(); if(s.hasChildNodes() && s.isExpanded()){ s.collapse(); }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){ this.select(s.parentNode, e); } break; }; } }); /** * @class Ext.tree.MultiSelectionModel * @extends Ext.util.Observable * Multi selection for a TreePanel. */ Ext.tree.MultiSelectionModel = function(config){ this.selNodes = []; this.selMap = {}; this.addEvents( /** * @event selectionchange * Fires when the selected nodes change * @param {MultiSelectionModel} this * @param {Array} nodes Array of the selected nodes */ "selectionchange" ); Ext.apply(this, config); Ext.tree.MultiSelectionModel.superclass.constructor.call(this); }; Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, { init : function(tree){ this.tree = tree; tree.getTreeEl().on("keydown", this.onKeyDown, this); tree.on("click", this.onNodeClick, this); }, onNodeClick : function(node, e){ if(e.ctrlKey && this.isSelected(node)){ this.unselect(node); }else{ this.select(node, e, e.ctrlKey); } }, /** * Select a node. * @param {TreeNode} node The node to select * @param {EventObject} e (optional) An event associated with the selection * @param {Boolean} keepExisting True to retain existing selections * @return {TreeNode} The selected node */ select : function(node, e, keepExisting){ if(keepExisting !== true){ this.clearSelections(true); } if(this.isSelected(node)){ this.lastSelNode = node; return node; } this.selNodes.push(node); this.selMap[node.id] = node; this.lastSelNode = node; node.ui.onSelectedChange(true); this.fireEvent("selectionchange", this, this.selNodes); return node; }, /** * Deselect a node. * @param {TreeNode} node The node to unselect */ unselect : function(node){ if(this.selMap[node.id]){ node.ui.onSelectedChange(false); var sn = this.selNodes; var index = sn.indexOf(node); if(index != -1){ this.selNodes.splice(index, 1); } delete this.selMap[node.id]; this.fireEvent("selectionchange", this, this.selNodes); } }, /** * Clear all selections */ clearSelections : function(suppressEvent){ var sn = this.selNodes; if(sn.length > 0){ for(var i = 0, len = sn.length; i < len; i++){ sn[i].ui.onSelectedChange(false); } this.selNodes = []; this.selMap = {}; if(suppressEvent !== true){ this.fireEvent("selectionchange", this, this.selNodes); } } }, /** * Returns true if the node is selected * @param {TreeNode} node The node to check * @return {Boolean} */ isSelected : function(node){ return this.selMap[node.id] ? true : false; }, /** * Returns an array of the selected nodes * @return {Array} */ getSelectedNodes : function(){ return this.selNodes; }, onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown, selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext, selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious });