Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / data / Tree.js
index 2a1a1c8..ba22ba6 100644 (file)
@@ -1,37 +1,53 @@
+/*
+
+This file is part of Ext JS 4
+
+Copyright (c) 2011 Sencha Inc
+
+Contact:  http://www.sencha.com/contact
+
+GNU General Public License Usage
+This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
+
+*/
 /**
  * @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}. 
+ * 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 
+ * 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.
  *
- * @constructor
- * @param {Node} root (optional) The root node
  */
 Ext.define('Ext.data.Tree', {
     alias: 'data.tree',
-    
+
     mixins: {
         observable: "Ext.util.Observable"
     },
 
     /**
+     * @property {Ext.data.NodeInterface}
      * The root node for this tree
-     * @type Node
      */
     root: null,
-        
+
+    /**
+     * Creates new Tree object.
+     * @param {Ext.data.NodeInterface} root (optional) The root node
+     */
     constructor: function(root) {
         var me = this;
+
         
-        me.nodeHash = {};
 
         me.mixins.observable.constructor.call(me);
-                        
+
         if (root) {
             me.setRootNode(root);
         }
@@ -52,119 +68,84 @@ Ext.define('Ext.data.Tree', {
      */
     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
+                 * @alias Ext.data.NodeInterface#append
                  */
                 "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
+                 * @alias Ext.data.NodeInterface#remove
                  */
                 "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
+                 * @alias Ext.data.NodeInterface#move
                  */
                 "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
+                 * @alias Ext.data.NodeInterface#insert
                  */
                 "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
+                 * @alias Ext.data.NodeInterface#beforeappend
                  */
                 "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
+                 * @alias Ext.data.NodeInterface#beforeremove
                  */
                 "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
+                 * @alias Ext.data.NodeInterface#beforemove
                  */
                 "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
+                 * @alias Ext.data.NodeInterface#beforeinsert
                  */
                 "beforeinsert",
 
                  /**
                   * @event expand
-                  * Fires when this node is expanded.
-                  * @param {Node} this The expanding node
+                  * @alias Ext.data.NodeInterface#expand
                   */
                  "expand",
 
                  /**
                   * @event collapse
-                  * Fires when this node is collapsed.
-                  * @param {Node} this The collapsing node
+                  * @alias Ext.data.NodeInterface#collapse
                   */
                  "collapse",
 
                  /**
                   * @event beforeexpand
-                  * Fires before this node is expanded.
-                  * @param {Node} this The expanding node
+                  * @alias Ext.data.NodeInterface#beforeexpand
                   */
                  "beforeexpand",
 
                  /**
                   * @event beforecollapse
-                  * Fires before this node is collapsed.
-                  * @param {Node} this The collapsing node
+                  * @alias Ext.data.NodeInterface#beforecollapse
                   */
                  "beforecollapse" ,
 
@@ -175,7 +156,7 @@ Ext.define('Ext.data.Tree', {
                   */
                  "rootchange"
             ]);
-            
+
             node.on({
                 scope: me,
                 insert: me.onNodeInsert,
@@ -183,24 +164,25 @@ Ext.define('Ext.data.Tree', {
                 remove: me.onNodeRemove
             });
 
-            me.registerNode(node);        
+            me.nodeHash = {};
+            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.
+     * @return {Ext.data.NodeInterface[]} The flattened nodes.
      */
     flatten: function(){
         var nodes = [],
             hash = this.nodeHash,
             key;
-            
+
         for (key in hash) {
             if (hash.hasOwnProperty(key)) {
                 nodes.push(hash[key]);
@@ -208,7 +190,7 @@ Ext.define('Ext.data.Tree', {
         }
         return nodes;
     },
-    
+
     /**
      * Fired when a node is inserted into the root or one of it's children
      * @private
@@ -216,9 +198,9 @@ Ext.define('Ext.data.Tree', {
      * @param {Ext.data.NodeInterface} node The inserted node
      */
     onNodeInsert: function(parent, node) {
-        this.registerNode(node);
+        this.registerNode(node, true);
     },
-    
+
     /**
      * Fired when a node is appended into the root or one of it's children
      * @private
@@ -226,9 +208,9 @@ Ext.define('Ext.data.Tree', {
      * @param {Ext.data.NodeInterface} node The appended node
      */
     onNodeAppend: function(parent, node) {
-        this.registerNode(node);
+        this.registerNode(node, true);
     },
-    
+
     /**
      * Fired when a node is removed from the root or one of it's children
      * @private
@@ -236,7 +218,7 @@ Ext.define('Ext.data.Tree', {
      * @param {Ext.data.NodeInterface} node The removed node
      */
     onNodeRemove: function(parent, node) {
-        this.unregisterNode(node);
+        this.unregisterNode(node, true);
     },
 
     /**
@@ -252,20 +234,32 @@ Ext.define('Ext.data.Tree', {
      * Registers a node with the tree
      * @private
      * @param {Ext.data.NodeInterface} The node to register
+     * @param {Boolean} [includeChildren] True to unregister any child nodes
      */
-    registerNode : function(node) {
+    registerNode : function(node, includeChildren) {
         this.nodeHash[node.getId() || node.internalId] = node;
+        if (includeChildren === true) {
+            node.eachChild(function(child){
+                this.registerNode(child, true);
+            }, this);
+        }
     },
 
     /**
      * Unregisters a node with the tree
      * @private
      * @param {Ext.data.NodeInterface} The node to unregister
+     * @param {Boolean} [includeChildren] True to unregister any child nodes
      */
-    unregisterNode : function(node) {
+    unregisterNode : function(node, includeChildren) {
         delete this.nodeHash[node.getId() || node.internalId];
+        if (includeChildren === true) {
+            node.eachChild(function(child){
+                this.unregisterNode(child, true);
+            }, this);
+        }
     },
-    
+
     /**
      * Sorts this tree
      * @private
@@ -275,7 +269,7 @@ Ext.define('Ext.data.Tree', {
     sort: function(sorterFn, recursive) {
         this.getRootNode().sort(sorterFn, recursive);
     },
-    
+
      /**
      * Filters this tree
      * @private
@@ -285,4 +279,4 @@ Ext.define('Ext.data.Tree', {
     filter: function(filters, recursive) {
         this.getRootNode().filter(filters, recursive);
     }
-});
\ No newline at end of file
+});