/** * @class Ext.data.Tree * * This class is used as a container for a series of nodes. The nodes themselves maintain * the relationship between parent/child. The tree itself acts as a manager. It gives functionality * to retrieve a node by its identifier: {@link #getNodeById}. * * The tree also relays events from any of it's child nodes, allowing them to be handled in a * centralized fashion. In general this class is not used directly, rather used internally * by other parts of the framework. * */ Ext.define('Ext.data.Tree', { alias: 'data.tree', mixins: { observable: "Ext.util.Observable" }, /** * The root node for this tree * @type Node */ root: null, /** * Creates new Tree object. * @param {Node} root (optional) The root node */ constructor: function(root) { var me = this; me.nodeHash = {}; me.mixins.observable.constructor.call(me); if (root) { me.setRootNode(root); } }, /** * Returns the root node for this tree. * @return {Ext.data.NodeInterface} */ getRootNode : function() { return this.root; }, /** * Sets the root node for this tree. * @param {Ext.data.NodeInterface} node * @return {Ext.data.NodeInterface} The root node */ setRootNode : function(node) { var me = this; me.root = node; Ext.data.NodeInterface.decorate(node); if (me.fireEvent('beforeappend', null, node) !== false) { node.set('root', true); node.updateInfo(); me.relayEvents(node, [ /** * @event append * Fires when a new child node is appended to a node in this tree. * @param {Tree} tree The owner tree * @param {Node} parent The parent node * @param {Node} node The newly appended node * @param {Number} index The index of the newly appended node */ "append", /** * @event remove * Fires when a child node is removed from a node in this tree. * @param {Tree} tree The owner tree * @param {Node} parent The parent node * @param {Node} node The child node removed */ "remove", /** * @event move * Fires when a node is moved to a new location in the tree * @param {Tree} tree The owner tree * @param {Node} node The node moved * @param {Node} oldParent The old parent of this node * @param {Node} newParent The new parent of this node * @param {Number} index The index it was moved to */ "move", /** * @event insert * Fires when a new child node is inserted in a node in this tree. * @param {Tree} tree The owner tree * @param {Node} parent The parent node * @param {Node} node The child node inserted * @param {Node} refNode The child node the node was inserted before */ "insert", /** * @event beforeappend * Fires before a new child is appended to a node in this tree, return false to cancel the append. * @param {Tree} tree The owner tree * @param {Node} parent The parent node * @param {Node} node The child node to be appended */ "beforeappend", /** * @event beforeremove * Fires before a child is removed from a node in this tree, return false to cancel the remove. * @param {Tree} tree The owner tree * @param {Node} parent The parent node * @param {Node} node The child node to be removed */ "beforeremove", /** * @event beforemove * Fires before a node is moved to a new location in the tree. Return false to cancel the move. * @param {Tree} tree The owner tree * @param {Node} node The node being moved * @param {Node} oldParent The parent of the node * @param {Node} newParent The new parent the node is moving to * @param {Number} index The index it is being moved to */ "beforemove", /** * @event beforeinsert * Fires before a new child is inserted in a node in this tree, return false to cancel the insert. * @param {Tree} tree The owner tree * @param {Node} parent The parent node * @param {Node} node The child node to be inserted * @param {Node} refNode The child node the node is being inserted before */ "beforeinsert", /** * @event expand * Fires when this node is expanded. * @param {Node} this The expanding node */ "expand", /** * @event collapse * Fires when this node is collapsed. * @param {Node} this The collapsing node */ "collapse", /** * @event beforeexpand * Fires before this node is expanded. * @param {Node} this The expanding node */ "beforeexpand", /** * @event beforecollapse * Fires before this node is collapsed. * @param {Node} this The collapsing node */ "beforecollapse" , /** * @event rootchange * Fires whenever the root node is changed in the tree. * @param {Ext.data.Model} root The new root */ "rootchange" ]); node.on({ scope: me, insert: me.onNodeInsert, append: me.onNodeAppend, remove: me.onNodeRemove }); me.registerNode(node); me.fireEvent('append', null, node); me.fireEvent('rootchange', node); } return node; }, /** * Flattens all the nodes in the tree into an array. * @private * @return {Array} The flattened nodes. */ flatten: function(){ var nodes = [], hash = this.nodeHash, key; for (key in hash) { if (hash.hasOwnProperty(key)) { nodes.push(hash[key]); } } return nodes; }, /** * Fired when a node is inserted into the root or one of it's children * @private * @param {Ext.data.NodeInterface} parent The parent node * @param {Ext.data.NodeInterface} node The inserted node */ onNodeInsert: function(parent, node) { this.registerNode(node); }, /** * Fired when a node is appended into the root or one of it's children * @private * @param {Ext.data.NodeInterface} parent The parent node * @param {Ext.data.NodeInterface} node The appended node */ onNodeAppend: function(parent, node) { this.registerNode(node); }, /** * Fired when a node is removed from the root or one of it's children * @private * @param {Ext.data.NodeInterface} parent The parent node * @param {Ext.data.NodeInterface} node The removed node */ onNodeRemove: function(parent, node) { this.unregisterNode(node); }, /** * Gets a node in this tree by its id. * @param {String} id * @return {Ext.data.NodeInterface} The match node. */ getNodeById : function(id) { return this.nodeHash[id]; }, /** * Registers a node with the tree * @private * @param {Ext.data.NodeInterface} The node to register */ registerNode : function(node) { this.nodeHash[node.getId() || node.internalId] = node; }, /** * Unregisters a node with the tree * @private * @param {Ext.data.NodeInterface} The node to unregister */ unregisterNode : function(node) { delete this.nodeHash[node.getId() || node.internalId]; }, /** * Sorts this tree * @private * @param {Function} sorterFn The function to use for sorting * @param {Boolean} recursive True to perform recursive sorting */ sort: function(sorterFn, recursive) { this.getRootNode().sort(sorterFn, recursive); }, /** * Filters this tree * @private * @param {Function} sorterFn The function to use for filtering * @param {Boolean} recursive True to perform recursive filtering */ filter: function(filters, recursive) { this.getRootNode().filter(filters, recursive); } });