Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / pkgs / pkg-tree-debug.js
index 39f9880..2553a85 100644 (file)
@@ -1,5 +1,5 @@
 /*!
 /*!
- * Ext JS Library 3.0.3
+ * Ext JS Library 3.1.0
  * Copyright(c) 2006-2009 Ext JS, LLC
  * licensing@extjs.com
  * http://www.extjs.com/license
  * Copyright(c) 2006-2009 Ext JS, LLC
  * licensing@extjs.com
  * http://www.extjs.com/license
@@ -118,18 +118,19 @@ new Ext.Viewport({
  */\r
 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {\r
     rootVisible : true,\r
  */\r
 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {\r
     rootVisible : true,\r
-    animate: Ext.enableFx,\r
+    animate : Ext.enableFx,\r
     lines : true,\r
     enableDD : false,\r
     hlDrop : Ext.enableFx,\r
     lines : true,\r
     enableDD : false,\r
     hlDrop : Ext.enableFx,\r
-    pathSeparator: "/",\r
-    \r
+    pathSeparator : '/',\r
+\r
     /**\r
      * @cfg {Array} bubbleEvents\r
      * <p>An array of events that, when fired, should be bubbled to any parent container.\r
     /**\r
      * @cfg {Array} bubbleEvents\r
      * <p>An array of events that, when fired, should be bubbled to any parent container.\r
-     * Defaults to <tt>['add', 'remove']</tt>.\r
+     * See {@link Ext.util.Observable#enableBubble}.\r
+     * Defaults to <tt>[]</tt>.\r
      */\r
      */\r
-    bubbleEvents: [],\r
+    bubbleEvents : [],\r
 \r
     initComponent : function(){\r
         Ext.tree.TreePanel.superclass.initComponent.call(this);\r
 \r
     initComponent : function(){\r
         Ext.tree.TreePanel.superclass.initComponent.call(this);\r
@@ -145,7 +146,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
                 dataUrl: this.dataUrl,\r
                 requestMethod: this.requestMethod\r
             });\r
                 dataUrl: this.dataUrl,\r
                 requestMethod: this.requestMethod\r
             });\r
-        }else if(typeof l == 'object' && !l.load){\r
+        }else if(Ext.isObject(l) && !l.load){\r
             l = new Ext.tree.TreeLoader(l);\r
         }\r
         this.loader = l;\r
             l = new Ext.tree.TreeLoader(l);\r
         }\r
         this.loader = l;\r
@@ -174,7 +175,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} node The newly appended node\r
             * @param {Number} index The index of the newly appended node\r
             */\r
             * @param {Node} node The newly appended node\r
             * @param {Number} index The index of the newly appended node\r
             */\r
-           "append",\r
+           'append',\r
            /**\r
             * @event remove\r
             * Fires when a child node is removed from a node in this tree.\r
            /**\r
             * @event remove\r
             * Fires when a child node is removed from a node in this tree.\r
@@ -182,7 +183,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node removed\r
             */\r
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node removed\r
             */\r
-           "remove",\r
+           'remove',\r
            /**\r
             * @event movenode\r
             * Fires when a node is moved to a new location in the tree\r
            /**\r
             * @event movenode\r
             * Fires when a node is moved to a new location in the tree\r
@@ -192,7 +193,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} newParent The new parent of this node\r
             * @param {Number} index The index it was moved to\r
             */\r
             * @param {Node} newParent The new parent of this node\r
             * @param {Number} index The index it was moved to\r
             */\r
-           "movenode",\r
+           'movenode',\r
            /**\r
             * @event insert\r
             * Fires when a new child node is inserted in a node in this tree.\r
            /**\r
             * @event insert\r
             * Fires when a new child node is inserted in a node in this tree.\r
@@ -201,7 +202,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} node The child node inserted\r
             * @param {Node} refNode The child node the node was inserted before\r
             */\r
             * @param {Node} node The child node inserted\r
             * @param {Node} refNode The child node the node was inserted before\r
             */\r
-           "insert",\r
+           'insert',\r
            /**\r
             * @event beforeappend\r
             * Fires before a new child is appended to a node in this tree, return false to cancel the append.\r
            /**\r
             * @event beforeappend\r
             * Fires before a new child is appended to a node in this tree, return false to cancel the append.\r
@@ -209,7 +210,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node to be appended\r
             */\r
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node to be appended\r
             */\r
-           "beforeappend",\r
+           'beforeappend',\r
            /**\r
             * @event beforeremove\r
             * Fires before a child is removed from a node in this tree, return false to cancel the remove.\r
            /**\r
             * @event beforeremove\r
             * Fires before a child is removed from a node in this tree, return false to cancel the remove.\r
@@ -217,7 +218,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node to be removed\r
             */\r
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node to be removed\r
             */\r
-           "beforeremove",\r
+           'beforeremove',\r
            /**\r
             * @event beforemovenode\r
             * Fires before a node is moved to a new location in the tree. Return false to cancel the move.\r
            /**\r
             * @event beforemovenode\r
             * Fires before a node is moved to a new location in the tree. Return false to cancel the move.\r
@@ -227,7 +228,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} newParent The new parent the node is moving to\r
             * @param {Number} index The index it is being moved to\r
             */\r
             * @param {Node} newParent The new parent the node is moving to\r
             * @param {Number} index The index it is being moved to\r
             */\r
-           "beforemovenode",\r
+           'beforemovenode',\r
            /**\r
             * @event beforeinsert\r
             * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.\r
            /**\r
             * @event beforeinsert\r
             * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.\r
@@ -236,20 +237,20 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} node The child node to be inserted\r
             * @param {Node} refNode The child node the node is being inserted before\r
             */\r
             * @param {Node} node The child node to be inserted\r
             * @param {Node} refNode The child node the node is being inserted before\r
             */\r
-            "beforeinsert",\r
+            'beforeinsert',\r
 \r
             /**\r
             * @event beforeload\r
             * Fires before a node is loaded, return false to cancel\r
             * @param {Node} node The node being loaded\r
             */\r
 \r
             /**\r
             * @event beforeload\r
             * Fires before a node is loaded, return false to cancel\r
             * @param {Node} node The node being loaded\r
             */\r
-            "beforeload",\r
+            'beforeload',\r
             /**\r
             * @event load\r
             * Fires when a node is loaded\r
             * @param {Node} node The node that was loaded\r
             */\r
             /**\r
             * @event load\r
             * Fires when a node is loaded\r
             * @param {Node} node The node that was loaded\r
             */\r
-            "load",\r
+            'load',\r
             /**\r
             * @event textchange\r
             * Fires when the text for a node is changed\r
             /**\r
             * @event textchange\r
             * Fires when the text for a node is changed\r
@@ -257,7 +258,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {String} text The new text\r
             * @param {String} oldText The old text\r
             */\r
             * @param {String} text The new text\r
             * @param {String} oldText The old text\r
             */\r
-            "textchange",\r
+            'textchange',\r
             /**\r
             * @event beforeexpandnode\r
             * Fires before a node is expanded, return false to cancel.\r
             /**\r
             * @event beforeexpandnode\r
             * Fires before a node is expanded, return false to cancel.\r
@@ -265,7 +266,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Boolean} deep\r
             * @param {Boolean} anim\r
             */\r
             * @param {Boolean} deep\r
             * @param {Boolean} anim\r
             */\r
-            "beforeexpandnode",\r
+            'beforeexpandnode',\r
             /**\r
             * @event beforecollapsenode\r
             * Fires before a node is collapsed, return false to cancel.\r
             /**\r
             * @event beforecollapsenode\r
             * Fires before a node is collapsed, return false to cancel.\r
@@ -273,61 +274,75 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Boolean} deep\r
             * @param {Boolean} anim\r
             */\r
             * @param {Boolean} deep\r
             * @param {Boolean} anim\r
             */\r
-            "beforecollapsenode",\r
+            'beforecollapsenode',\r
             /**\r
             * @event expandnode\r
             * Fires when a node is expanded\r
             * @param {Node} node The node\r
             */\r
             /**\r
             * @event expandnode\r
             * Fires when a node is expanded\r
             * @param {Node} node The node\r
             */\r
-            "expandnode",\r
+            'expandnode',\r
             /**\r
             * @event disabledchange\r
             * Fires when the disabled status of a node changes\r
             * @param {Node} node The node\r
             * @param {Boolean} disabled\r
             */\r
             /**\r
             * @event disabledchange\r
             * Fires when the disabled status of a node changes\r
             * @param {Node} node The node\r
             * @param {Boolean} disabled\r
             */\r
-            "disabledchange",\r
+            'disabledchange',\r
             /**\r
             * @event collapsenode\r
             * Fires when a node is collapsed\r
             * @param {Node} node The node\r
             */\r
             /**\r
             * @event collapsenode\r
             * Fires when a node is collapsed\r
             * @param {Node} node The node\r
             */\r
-            "collapsenode",\r
+            'collapsenode',\r
             /**\r
             * @event beforeclick\r
             * Fires before click processing on a node. Return false to cancel the default action.\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
             /**\r
             * @event beforeclick\r
             * Fires before click processing on a node. Return false to cancel the default action.\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "beforeclick",\r
+            'beforeclick',\r
             /**\r
             * @event click\r
             * Fires when a node is clicked\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
             /**\r
             * @event click\r
             * Fires when a node is clicked\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "click",\r
+            'click',\r
+            /**\r
+            * @event containerclick\r
+            * Fires when the tree container is clicked\r
+            * @param {Tree} this\r
+            * @param {Ext.EventObject} e The event object\r
+            */\r
+            'containerclick',\r
             /**\r
             * @event checkchange\r
             * Fires when a node with a checkbox's checked property changes\r
             * @param {Node} this This node\r
             * @param {Boolean} checked\r
             */\r
             /**\r
             * @event checkchange\r
             * Fires when a node with a checkbox's checked property changes\r
             * @param {Node} this This node\r
             * @param {Boolean} checked\r
             */\r
-            "checkchange",\r
+            'checkchange',\r
             /**\r
             * @event beforedblclick\r
             * Fires before double click processing on a node. Return false to cancel the default action.\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
             /**\r
             * @event beforedblclick\r
             * Fires before double click processing on a node. Return false to cancel the default action.\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "beforedblclick",\r
+            'beforedblclick',\r
             /**\r
             * @event dblclick\r
             * Fires when a node is double clicked\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
             /**\r
             * @event dblclick\r
             * Fires when a node is double clicked\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "dblclick",\r
+            'dblclick',\r
+            /**\r
+            * @event containerdblclick\r
+            * Fires when the tree container is double clicked\r
+            * @param {Tree} this\r
+            * @param {Ext.EventObject} e The event object\r
+            */\r
+            'containerdblclick',\r
             /**\r
             * @event contextmenu\r
             * Fires when a node is right clicked. To display a context menu in response to this\r
             /**\r
             * @event contextmenu\r
             * Fires when a node is right clicked. To display a context menu in response to this\r
@@ -375,13 +390,20 @@ new Ext.tree.TreePanel({
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "contextmenu",\r
+            'contextmenu',\r
+            /**\r
+            * @event containercontextmenu\r
+            * Fires when the tree container is right clicked\r
+            * @param {Tree} this\r
+            * @param {Ext.EventObject} e The event object\r
+            */\r
+            'containercontextmenu',\r
             /**\r
             * @event beforechildrenrendered\r
             * Fires right before the child nodes for a node are rendered\r
             * @param {Node} node The node\r
             */\r
             /**\r
             * @event beforechildrenrendered\r
             * Fires right before the child nodes for a node are rendered\r
             * @param {Node} node The node\r
             */\r
-            "beforechildrenrendered",\r
+            'beforechildrenrendered',\r
            /**\r
              * @event startdrag\r
              * Fires when a node starts being dragged\r
            /**\r
              * @event startdrag\r
              * Fires when a node starts being dragged\r
@@ -389,7 +411,7 @@ new Ext.tree.TreePanel({
              * @param {Ext.tree.TreeNode} node\r
              * @param {event} e The raw browser event\r
              */\r
              * @param {Ext.tree.TreeNode} node\r
              * @param {event} e The raw browser event\r
              */\r
-            "startdrag",\r
+            'startdrag',\r
             /**\r
              * @event enddrag\r
              * Fires when a drag operation is complete\r
             /**\r
              * @event enddrag\r
              * Fires when a drag operation is complete\r
@@ -397,7 +419,7 @@ new Ext.tree.TreePanel({
              * @param {Ext.tree.TreeNode} node\r
              * @param {event} e The raw browser event\r
              */\r
              * @param {Ext.tree.TreeNode} node\r
              * @param {event} e The raw browser event\r
              */\r
-            "enddrag",\r
+            'enddrag',\r
             /**\r
              * @event dragdrop\r
              * Fires when a dragged node is dropped on a valid DD target\r
             /**\r
              * @event dragdrop\r
              * Fires when a dragged node is dropped on a valid DD target\r
@@ -406,7 +428,7 @@ new Ext.tree.TreePanel({
              * @param {DD} dd The dd it was dropped on\r
              * @param {event} e The raw browser event\r
              */\r
              * @param {DD} dd The dd it was dropped on\r
              * @param {event} e The raw browser event\r
              */\r
-            "dragdrop",\r
+            'dragdrop',\r
             /**\r
              * @event beforenodedrop\r
              * Fires when a DD object is dropped on a node in this tree for preprocessing. Return false to cancel the drop. The dropEvent\r
             /**\r
              * @event beforenodedrop\r
              * Fires when a DD object is dropped on a node in this tree for preprocessing. Return false to cancel the drop. The dropEvent\r
@@ -422,11 +444,11 @@ new Ext.tree.TreePanel({
              * to be inserted by setting them on this object.</li>\r
              * <li>cancel - Set this to true to cancel the drop.</li>\r
              * <li>dropStatus - If the default drop action is cancelled but the drop is valid, setting this to true\r
              * to be inserted by setting them on this object.</li>\r
              * <li>cancel - Set this to true to cancel the drop.</li>\r
              * <li>dropStatus - If the default drop action is cancelled but the drop is valid, setting this to true\r
-             * will prevent the animated "repair" from appearing.</li>\r
+             * will prevent the animated 'repair' from appearing.</li>\r
              * </ul>\r
              * @param {Object} dropEvent\r
              */\r
              * </ul>\r
              * @param {Object} dropEvent\r
              */\r
-            "beforenodedrop",\r
+            'beforenodedrop',\r
             /**\r
              * @event nodedrop\r
              * Fires after a DD object is dropped on a node in this tree. The dropEvent\r
             /**\r
              * @event nodedrop\r
              * Fires after a DD object is dropped on a node in this tree. The dropEvent\r
@@ -442,7 +464,7 @@ new Ext.tree.TreePanel({
              * </ul>\r
              * @param {Object} dropEvent\r
              */\r
              * </ul>\r
              * @param {Object} dropEvent\r
              */\r
-            "nodedrop",\r
+            'nodedrop',\r
              /**\r
              * @event nodedragover\r
              * Fires when a tree node is being targeted for a drag drop, return false to signal drop not allowed. The dragOverEvent\r
              /**\r
              * @event nodedragover\r
              * Fires when a tree node is being targeted for a drag drop, return false to signal drop not allowed. The dragOverEvent\r
@@ -459,10 +481,10 @@ new Ext.tree.TreePanel({
              * </ul>\r
              * @param {Object} dragOverEvent\r
              */\r
              * </ul>\r
              * @param {Object} dragOverEvent\r
              */\r
-            "nodedragover"\r
+            'nodedragover'\r
         );\r
         if(this.singleExpand){\r
         );\r
         if(this.singleExpand){\r
-            this.on("beforeexpandnode", this.restrictExpand, this);\r
+            this.on('beforeexpandnode', this.restrictExpand, this);\r
         }\r
     },\r
 \r
         }\r
     },\r
 \r
@@ -531,7 +553,7 @@ new Ext.tree.TreePanel({
 \r
     // private\r
     toString : function(){\r
 \r
     // private\r
     toString : function(){\r
-        return "[Tree"+(this.id?" "+this.id:"")+"]";\r
+        return '[Tree'+(this.id?' '+this.id:'')+']';\r
     },\r
 \r
     // private\r
     },\r
 \r
     // private\r
@@ -546,7 +568,7 @@ new Ext.tree.TreePanel({
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
-     * Retrieve an array of checked nodes, or an array of a specific attribute of checked nodes (e.g. "id")\r
+     * Retrieve an array of checked nodes, or an array of a specific attribute of checked nodes (e.g. 'id')\r
      * @param {String} attribute (optional) Defaults to null (return the actual nodes)\r
      * @param {TreeNode} startNode (optional) The node to start from, defaults to the root\r
      * @return {Array}\r
      * @param {String} attribute (optional) Defaults to null (return the actual nodes)\r
      * @param {TreeNode} startNode (optional) The node to start from, defaults to the root\r
      * @return {Array}\r
@@ -563,14 +585,6 @@ new Ext.tree.TreePanel({
         return r;\r
     },\r
 \r
         return r;\r
     },\r
 \r
-    /**\r
-     * Returns the container element for this TreePanel.\r
-     * @return {Element} The container element for this TreePanel.\r
-     */\r
-    getEl : function(){\r
-        return this.el;\r
-    },\r
-\r
     /**\r
      * Returns the default {@link Ext.tree.TreeLoader} for this TreePanel.\r
      * @return {Ext.tree.TreeLoader} The TreeLoader for this TreePanel.\r
     /**\r
      * Returns the default {@link Ext.tree.TreeLoader} for this TreePanel.\r
      * @return {Ext.tree.TreeLoader} The TreeLoader for this TreePanel.\r
@@ -612,7 +626,7 @@ new Ext.tree.TreePanel({
      * (bSuccess, oLastNode) where bSuccess is if the expand was successful and oLastNode is the last node that was expanded.\r
      */\r
     expandPath : function(path, attr, callback){\r
      * (bSuccess, oLastNode) where bSuccess is if the expand was successful and oLastNode is the last node that was expanded.\r
      */\r
     expandPath : function(path, attr, callback){\r
-        attr = attr || "id";\r
+        attr = attr || 'id';\r
         var keys = path.split(this.pathSeparator);\r
         var curNode = this.root;\r
         if(curNode.attributes[attr] != keys[1]){ // invalid root\r
         var keys = path.split(this.pathSeparator);\r
         var curNode = this.root;\r
         if(curNode.attributes[attr] != keys[1]){ // invalid root\r
@@ -650,7 +664,7 @@ new Ext.tree.TreePanel({
      * (bSuccess, oSelNode) where bSuccess is if the selection was successful and oSelNode is the selected node.\r
      */\r
     selectPath : function(path, attr, callback){\r
      * (bSuccess, oSelNode) where bSuccess is if the selection was successful and oSelNode is the selected node.\r
      */\r
     selectPath : function(path, attr, callback){\r
-        attr = attr || "id";\r
+        attr = attr || 'id';\r
         var keys = path.split(this.pathSeparator),\r
             v = keys.pop();\r
         if(keys.length > 1){\r
         var keys = path.split(this.pathSeparator),\r
             v = keys.pop();\r
         if(keys.length > 1){\r
@@ -692,9 +706,9 @@ new Ext.tree.TreePanel({
     onRender : function(ct, position){\r
         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);\r
         this.el.addClass('x-tree');\r
     onRender : function(ct, position){\r
         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);\r
         this.el.addClass('x-tree');\r
-        this.innerCt = this.body.createChild({tag:"ul",\r
-               cls:"x-tree-root-ct " +\r
-               (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});\r
+        this.innerCt = this.body.createChild({tag:'ul',\r
+               cls:'x-tree-root-ct ' +\r
+               (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});\r
     },\r
 \r
     // private\r
     },\r
 \r
     // private\r
@@ -711,7 +725,7 @@ new Ext.tree.TreePanel({
             * @type Ext.tree.TreeDropZone\r
             */\r
              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {\r
             * @type Ext.tree.TreeDropZone\r
             */\r
              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {\r
-               ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true\r
+               ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true\r
            });\r
         }\r
         if((this.enableDD || this.enableDrag) && !this.dragZone){\r
            });\r
         }\r
         if((this.enableDD || this.enableDrag) && !this.dragZone){\r
@@ -721,7 +735,7 @@ new Ext.tree.TreePanel({
             * @type Ext.tree.TreeDragZone\r
             */\r
             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {\r
             * @type Ext.tree.TreeDragZone\r
             */\r
             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {\r
-               ddGroup: this.ddGroup || "TreeDD",\r
+               ddGroup: this.ddGroup || 'TreeDD',\r
                scroll: this.ddScroll\r
            });\r
         }\r
                scroll: this.ddScroll\r
            });\r
         }\r
@@ -737,20 +751,14 @@ new Ext.tree.TreePanel({
         }\r
     },\r
 \r
         }\r
     },\r
 \r
-    onDestroy : function(){\r
+    beforeDestroy : function(){\r
         if(this.rendered){\r
         if(this.rendered){\r
-            this.body.removeAllListeners();\r
             Ext.dd.ScrollManager.unregister(this.body);\r
             Ext.dd.ScrollManager.unregister(this.body);\r
-            if(this.dropZone){\r
-                this.dropZone.unreg();\r
-            }\r
-            if(this.dragZone){\r
-               this.dragZone.unreg();\r
-            }\r
+            Ext.destroy(this.dropZone, this.dragZone);\r
         }\r
         }\r
-        this.root.destroy();\r
-        this.nodeHash = null;\r
-        Ext.tree.TreePanel.superclass.onDestroy.call(this);\r
+        Ext.destroy(this.root, this.loader);\r
+        this.nodeHash = this.root = this.loader = null;\r
+        Ext.tree.TreePanel.superclass.beforeDestroy.call(this);\r
     }\r
 \r
     /**\r
     }\r
 \r
     /**\r
@@ -1019,32 +1027,42 @@ Ext.tree.TreeEventModel.prototype = {
     },\r
 \r
     delegateClick : function(e, t){\r
     },\r
 \r
     delegateClick : function(e, t){\r
-        if(!this.beforeEvent(e)){\r
-            return;\r
-        }\r
-\r
-        if(e.getTarget('input[type=checkbox]', 1)){\r
-            this.onCheckboxClick(e, this.getNode(e));\r
-        }\r
-        else if(e.getTarget('.x-tree-ec-icon', 1)){\r
-            this.onIconClick(e, this.getNode(e));\r
-        }\r
-        else if(this.getNodeTarget(e)){\r
-            this.onNodeClick(e, this.getNode(e));\r
+        if(this.beforeEvent(e)){\r
+            if(e.getTarget('input[type=checkbox]', 1)){\r
+                this.onCheckboxClick(e, this.getNode(e));\r
+            }else if(e.getTarget('.x-tree-ec-icon', 1)){\r
+                this.onIconClick(e, this.getNode(e));\r
+            }else if(this.getNodeTarget(e)){\r
+                this.onNodeClick(e, this.getNode(e));\r
+            }else{\r
+                this.onContainerEvent(e, 'click');\r
+            }\r
         }\r
     },\r
 \r
     delegateDblClick : function(e, t){\r
         }\r
     },\r
 \r
     delegateDblClick : function(e, t){\r
-        if(this.beforeEvent(e) && this.getNodeTarget(e)){\r
-            this.onNodeDblClick(e, this.getNode(e));\r
+        if(this.beforeEvent(e)){\r
+            if(this.getNodeTarget(e)){\r
+                this.onNodeDblClick(e, this.getNode(e));\r
+            }else{\r
+                this.onContainerEvent(e, 'dblclick');    \r
+            }\r
         }\r
     },\r
 \r
     delegateContextMenu : function(e, t){\r
         }\r
     },\r
 \r
     delegateContextMenu : function(e, t){\r
-        if(this.beforeEvent(e) && this.getNodeTarget(e)){\r
-            this.onNodeContextMenu(e, this.getNode(e));\r
+        if(this.beforeEvent(e)){\r
+            if(this.getNodeTarget(e)){\r
+                this.onNodeContextMenu(e, this.getNode(e));\r
+            }else{\r
+                this.onContainerEvent(e, 'contextmenu');    \r
+            }\r
         }\r
     },\r
         }\r
     },\r
+    \r
+    onContainerEvent: function(e, type){\r
+        this.tree.fireEvent('container' + type, this.tree, e); \r
+    },\r
 \r
     onNodeClick : function(e, node){\r
         node.ui.onClick(e);\r
 \r
     onNodeClick : function(e, node){\r
         node.ui.onClick(e);\r
@@ -1113,7 +1131,7 @@ Ext.tree.DefaultSelectionModel = function(config){
         * @param {DefaultSelectionModel} this\r
         * @param {TreeNode} node the new selection\r
         */\r
         * @param {DefaultSelectionModel} this\r
         * @param {TreeNode} node the new selection\r
         */\r
-       "selectionchange",\r
+       'selectionchange',\r
 \r
        /**\r
         * @event beforeselect\r
 \r
        /**\r
         * @event beforeselect\r
@@ -1122,7 +1140,7 @@ Ext.tree.DefaultSelectionModel = function(config){
         * @param {TreeNode} node the new selection\r
         * @param {TreeNode} node the old selection\r
         */\r
         * @param {TreeNode} node the new selection\r
         * @param {TreeNode} node the old selection\r
         */\r
-       "beforeselect"\r
+       'beforeselect'\r
    );\r
 \r
     Ext.apply(this, config);\r
    );\r
 \r
     Ext.apply(this, config);\r
@@ -1133,7 +1151,7 @@ Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
     init : function(tree){\r
         this.tree = tree;\r
         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
     init : function(tree){\r
         this.tree = tree;\r
         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
-        tree.on("click", this.onNodeClick, this);\r
+        tree.on('click', this.onNodeClick, this);\r
     },\r
     \r
     onNodeClick : function(node, e){\r
     },\r
     \r
     onNodeClick : function(node, e){\r
@@ -1154,12 +1172,12 @@ Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
         if(node == last){\r
             node.ui.onSelectedChange(true);\r
         }else if(this.fireEvent('beforeselect', this, node, last) !== false){\r
         if(node == last){\r
             node.ui.onSelectedChange(true);\r
         }else if(this.fireEvent('beforeselect', this, node, last) !== false){\r
-            if(last){\r
+            if(last && last.ui){\r
                 last.ui.onSelectedChange(false);\r
             }\r
             this.selNode = node;\r
             node.ui.onSelectedChange(true);\r
                 last.ui.onSelectedChange(false);\r
             }\r
             this.selNode = node;\r
             node.ui.onSelectedChange(true);\r
-            this.fireEvent("selectionchange", this, node, last);\r
+            this.fireEvent('selectionchange', this, node, last);\r
         }\r
         return node;\r
     },\r
         }\r
         return node;\r
     },\r
@@ -1167,22 +1185,26 @@ Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
     /**\r
      * Deselect a node.\r
      * @param {TreeNode} node The node to unselect\r
     /**\r
      * Deselect a node.\r
      * @param {TreeNode} node The node to unselect\r
+     * @param {Boolean} silent True to stop the selectionchange event from firing.\r
      */\r
      */\r
-    unselect : function(node){\r
+    unselect : function(node, silent){\r
         if(this.selNode == node){\r
         if(this.selNode == node){\r
-            this.clearSelections();\r
+            this.clearSelections(silent);\r
         }    \r
     },\r
     \r
     /**\r
      * Clear all selections\r
         }    \r
     },\r
     \r
     /**\r
      * Clear all selections\r
+     * @param {Boolean} silent True to stop the selectionchange event from firing.\r
      */\r
      */\r
-    clearSelections : function(){\r
+    clearSelections : function(silent){\r
         var n = this.selNode;\r
         if(n){\r
             n.ui.onSelectedChange(false);\r
             this.selNode = null;\r
         var n = this.selNode;\r
         if(n){\r
             n.ui.onSelectedChange(false);\r
             this.selNode = null;\r
-            this.fireEvent("selectionchange", this, null);\r
+            if(silent !== true){\r
+                this.fireEvent('selectionchange', this, null);\r
+            }\r
         }\r
         return n;\r
     },\r
         }\r
         return n;\r
     },\r
@@ -1310,7 +1332,7 @@ Ext.tree.MultiSelectionModel = function(config){
         * @param {MultiSelectionModel} this\r
         * @param {Array} nodes Array of the selected nodes\r
         */\r
         * @param {MultiSelectionModel} this\r
         * @param {Array} nodes Array of the selected nodes\r
         */\r
-       "selectionchange"\r
+       'selectionchange'\r
    );\r
     Ext.apply(this, config);\r
     Ext.tree.MultiSelectionModel.superclass.constructor.call(this);\r
    );\r
     Ext.apply(this, config);\r
     Ext.tree.MultiSelectionModel.superclass.constructor.call(this);\r
@@ -1320,7 +1342,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
     init : function(tree){\r
         this.tree = tree;\r
         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
     init : function(tree){\r
         this.tree = tree;\r
         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
-        tree.on("click", this.onNodeClick, this);\r
+        tree.on('click', this.onNodeClick, this);\r
     },\r
     \r
     onNodeClick : function(node, e){\r
     },\r
     \r
     onNodeClick : function(node, e){\r
@@ -1350,7 +1372,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
         this.selMap[node.id] = node;\r
         this.lastSelNode = node;\r
         node.ui.onSelectedChange(true);\r
         this.selMap[node.id] = node;\r
         this.lastSelNode = node;\r
         node.ui.onSelectedChange(true);\r
-        this.fireEvent("selectionchange", this, this.selNodes);\r
+        this.fireEvent('selectionchange', this, this.selNodes);\r
         return node;\r
     },\r
     \r
         return node;\r
     },\r
     \r
@@ -1367,7 +1389,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
                 this.selNodes.splice(index, 1);\r
             }\r
             delete this.selMap[node.id];\r
                 this.selNodes.splice(index, 1);\r
             }\r
             delete this.selMap[node.id];\r
-            this.fireEvent("selectionchange", this, this.selNodes);\r
+            this.fireEvent('selectionchange', this, this.selNodes);\r
         }\r
     },\r
     \r
         }\r
     },\r
     \r
@@ -1383,7 +1405,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
             this.selNodes = [];\r
             this.selMap = {};\r
             if(suppressEvent !== true){\r
             this.selNodes = [];\r
             this.selMap = {};\r
             if(suppressEvent !== true){\r
-                this.fireEvent("selectionchange", this, this.selNodes);\r
+                this.fireEvent('selectionchange', this, this.selNodes);\r
             }\r
         }\r
     },\r
             }\r
         }\r
     },\r
@@ -1823,9 +1845,10 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     /**\r
      * Removes a child node from this node.\r
      * @param {Node} node The node to remove\r
     /**\r
      * Removes a child node from this node.\r
      * @param {Node} node The node to remove\r
+     * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.\r
      * @return {Node} The removed node\r
      */\r
      * @return {Node} The removed node\r
      */\r
-    removeChild : function(node){\r
+    removeChild : function(node, destroy){\r
         var index = this.childNodes.indexOf(node);\r
         if(index == -1){\r
             return false;\r
         var index = this.childNodes.indexOf(node);\r
         if(index == -1){\r
             return false;\r
@@ -1853,14 +1876,35 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
             this.setLastChild(node.previousSibling);\r
         }\r
 \r
             this.setLastChild(node.previousSibling);\r
         }\r
 \r
-        node.setOwnerTree(null);\r
-        // clear any references from the node\r
-        node.parentNode = null;\r
-        node.previousSibling = null;\r
-        node.nextSibling = null;\r
+        node.clear();\r
         this.fireEvent("remove", this.ownerTree, this, node);\r
         this.fireEvent("remove", this.ownerTree, this, node);\r
+        if(destroy){\r
+            node.destroy();\r
+        }\r
         return node;\r
     },\r
         return node;\r
     },\r
+    \r
+    // private\r
+    clear : function(destroy){\r
+        // clear any references from the node\r
+        this.setOwnerTree(null, destroy);\r
+        this.parentNode = this.previousSibling = this.nextSibling = null\r
+        if(destroy){\r
+            this.firstChild = this.lastChild = null; \r
+        }\r
+    },\r
+    \r
+    /**\r
+     * Destroys the node.\r
+     */\r
+    destroy : function(){\r
+        this.purgeListeners();\r
+        this.clear(true);  \r
+        Ext.each(this.childNodes, function(n){\r
+            n.destroy();\r
+        });\r
+        this.childNodes = null;\r
+    },\r
 \r
     /**\r
      * Inserts the first node before the second node in this nodes childNodes collection.\r
 \r
     /**\r
      * Inserts the first node before the second node in this nodes childNodes collection.\r
@@ -1920,10 +1964,11 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
 \r
     /**\r
      * Removes this node from its parent\r
 \r
     /**\r
      * Removes this node from its parent\r
+     * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.\r
      * @return {Node} this\r
      */\r
      * @return {Node} this\r
      */\r
-    remove : function(){\r
-        this.parentNode.removeChild(this);\r
+    remove : function(destroy){\r
+        this.parentNode.removeChild(this, destroy);\r
         return this;\r
     },\r
 \r
         return this;\r
     },\r
 \r
@@ -1992,16 +2037,18 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     // private\r
     },\r
 \r
     // private\r
-    setOwnerTree : function(tree){\r
+    setOwnerTree : function(tree, destroy){\r
         // if it is a move, we need to update everyone\r
         if(tree != this.ownerTree){\r
             if(this.ownerTree){\r
                 this.ownerTree.unregisterNode(this);\r
             }\r
             this.ownerTree = tree;\r
         // if it is a move, we need to update everyone\r
         if(tree != this.ownerTree){\r
             if(this.ownerTree){\r
                 this.ownerTree.unregisterNode(this);\r
             }\r
             this.ownerTree = tree;\r
-            var cs = this.childNodes;\r
-            for(var i = 0, len = cs.length; i < len; i++) {\r
-               cs[i].setOwnerTree(tree);\r
+            // If we're destroying, we don't need to recurse since it will be called on each child node\r
+            if(destroy !== true){\r
+                Ext.each(this.childNodes, function(n){\r
+                    n.setOwnerTree(tree);\r
+                });\r
             }\r
             if(tree){\r
                 tree.registerNode(this);\r
             }\r
             if(tree){\r
                 tree.registerNode(this);\r
@@ -2048,13 +2095,12 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
-     * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current node. The arguments to the function\r
+     * Bubbles up the tree from this node, calling the specified function with each node. The arguments to the function\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the bubble is stopped.\r
      * @param {Function} fn The function to call\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the bubble is stopped.\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
-     * @param {Array} args (optional) The args to call the function with (default to passing the current node)\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.\r
+     * @param {Array} args (optional) The args to call the function with (default to passing the current Node)\r
      */\r
     bubble : function(fn, scope, args){\r
         var p = this;\r
      */\r
     bubble : function(fn, scope, args){\r
         var p = this;\r
@@ -2067,13 +2113,12 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
-     * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current node. The arguments to the function\r
+     * Cascades down the tree from this node, calling the specified function with each node. The arguments to the function\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the cascade is stopped on that branch.\r
      * @param {Function} fn The function to call\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the cascade is stopped on that branch.\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
-     * @param {Array} args (optional) The args to call the function with (default to passing the current node)\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.\r
+     * @param {Array} args (optional) The args to call the function with (default to passing the current Node)\r
      */\r
     cascade : function(fn, scope, args){\r
         if(fn.apply(scope || this, args || [this]) !== false){\r
      */\r
     cascade : function(fn, scope, args){\r
         if(fn.apply(scope || this, args || [this]) !== false){\r
@@ -2085,13 +2130,12 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
-     * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current node. The arguments to the function\r
+     * Interates the child nodes of this node, calling the specified function with each node. The arguments to the function\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the iteration stops.\r
      * @param {Function} fn The function to call\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the iteration stops.\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
-     * @param {Array} args (optional) The args to call the function with (default to passing the current node)\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node in the iteration.\r
+     * @param {Array} args (optional) The args to call the function with (default to passing the current Node)\r
      */\r
     eachChild : function(fn, scope, args){\r
         var cs = this.childNodes;\r
      */\r
     eachChild : function(fn, scope, args){\r
         var cs = this.childNodes;\r
@@ -2119,10 +2163,9 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
-     * Finds the first child by a custom function. The child matches if the function passed\r
-     * returns true.\r
-     * @param {Function} fn\r
-     * @param {Object} scope (optional)\r
+     * Finds the first child by a custom function. The child matches if the function passed returns <code>true</code>.\r
+     * @param {Function} fn A function which must return <code>true</code> if the passed Node is the required Node.\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Node being tested.\r
      * @return {Node} The found child or null if none was found\r
      */\r
     findChildBy : function(fn, scope){\r
      * @return {Node} The found child or null if none was found\r
      */\r
     findChildBy : function(fn, scope){\r
@@ -2136,9 +2179,9 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
-     * Sorts this nodes children using the supplied sort function\r
-     * @param {Function} fn\r
-     * @param {Object} scope (optional)\r
+     * Sorts this nodes children using the supplied sort function.\r
+     * @param {Function} fn A function which, when passed two Nodes, returns -1, 0 or 1 depending upon required sort order.\r
+     * @param {Object} scope (optional)The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.\r
      */\r
     sort : function(fn, scope){\r
         var cs = this.childNodes;\r
      */\r
     sort : function(fn, scope){\r
         var cs = this.childNodes;\r
@@ -2213,13 +2256,13 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
  * @cfg {Boolean} draggable True to make this node draggable (defaults to false)\r
  * @cfg {Boolean} isTarget False to not allow this node to act as a drop target (defaults to true)\r
  * @cfg {Boolean} allowChildren False to not allow this node to have child nodes (defaults to true)\r
  * @cfg {Boolean} draggable True to make this node draggable (defaults to false)\r
  * @cfg {Boolean} isTarget False to not allow this node to act as a drop target (defaults to true)\r
  * @cfg {Boolean} allowChildren False to not allow this node to have child nodes (defaults to true)\r
- * @cfg {Boolean} editable False to not allow this node to be edited by an (@link Ext.tree.TreeEditor} (defaults to true)\r
+ * @cfg {Boolean} editable False to not allow this node to be edited by an {@link Ext.tree.TreeEditor} (defaults to true)\r
  * @constructor\r
  * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node\r
  */\r
 Ext.tree.TreeNode = function(attributes){\r
     attributes = attributes || {};\r
  * @constructor\r
  * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node\r
  */\r
 Ext.tree.TreeNode = function(attributes){\r
     attributes = attributes || {};\r
-    if(typeof attributes == 'string'){\r
+    if(Ext.isString(attributes)){\r
         attributes = {text: attributes};\r
     }\r
     this.childrenRendered = false;\r
         attributes = {text: attributes};\r
     }\r
     this.childrenRendered = false;\r
@@ -2370,7 +2413,7 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
 \r
     getLoader : function(){\r
         var owner;\r
 \r
     getLoader : function(){\r
         var owner;\r
-        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : new Ext.tree.TreeLoader());\r
+        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));\r
     },\r
 \r
     // private override\r
     },\r
 \r
     // private override\r
@@ -2412,11 +2455,11 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
     },\r
 \r
     // private override\r
     },\r
 \r
     // private override\r
-    removeChild : function(node){\r
+    removeChild : function(node, destroy){\r
         this.ownerTree.getSelectionModel().unselect(node);\r
         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);\r
         // if it's been rendered remove dom node\r
         this.ownerTree.getSelectionModel().unselect(node);\r
         Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);\r
         // if it's been rendered remove dom node\r
-        if(this.childrenRendered){\r
+        if(node.ui.rendered){\r
             node.ui.remove();\r
         }\r
         if(this.childNodes.length < 1){\r
             node.ui.remove();\r
         }\r
         if(this.childNodes.length < 1){\r
@@ -2449,8 +2492,7 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
      */\r
     setText : function(text){\r
         var oldText = this.text;\r
      */\r
     setText : function(text){\r
         var oldText = this.text;\r
-        this.text = text;\r
-        this.attributes.text = text;\r
+        this.text = this.attributes.text = text;\r
         if(this.rendered){ // event without subscribing\r
             this.ui.onTextChange(this, text, oldText);\r
         }\r
         if(this.rendered){ // event without subscribing\r
             this.ui.onTextChange(this, text, oldText);\r
         }\r
@@ -2461,14 +2503,21 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
      * Triggers selection of this node\r
      */\r
     select : function(){\r
      * Triggers selection of this node\r
      */\r
     select : function(){\r
-        this.getOwnerTree().getSelectionModel().select(this);\r
+        var t = this.getOwnerTree();\r
+        if(t){\r
+            t.getSelectionModel().select(this);\r
+        }\r
     },\r
 \r
     /**\r
      * Triggers deselection of this node\r
     },\r
 \r
     /**\r
      * Triggers deselection of this node\r
+     * @param {Boolean} silent (optional) True to stop selection change events from firing.\r
      */\r
      */\r
-    unselect : function(){\r
-        this.getOwnerTree().getSelectionModel().unselect(this);\r
+    unselect : function(silent){\r
+        var t = this.getOwnerTree();\r
+        if(t){\r
+            t.getSelectionModel().unselect(this, silent);\r
+        }\r
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
@@ -2476,7 +2525,8 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
      * @return {Boolean}\r
      */\r
     isSelected : function(){\r
      * @return {Boolean}\r
      */\r
     isSelected : function(){\r
-        return this.getOwnerTree().getSelectionModel().isSelected(this);\r
+        var t = this.getOwnerTree();\r
+        return t ? t.getSelectionModel().isSelected(this) : false;\r
     },\r
 \r
     /**\r
     },\r
 \r
     /**\r
@@ -2486,7 +2536,7 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
      * @param {Function} callback (optional) A callback to be called when\r
      * expanding this node completes (does not wait for deep expand to complete).\r
      * Called with 1 parameter, this node.\r
      * @param {Function} callback (optional) A callback to be called when\r
      * expanding this node completes (does not wait for deep expand to complete).\r
      * Called with 1 parameter, this node.\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this TreeNode.\r
      */\r
     expand : function(deep, anim, callback, scope){\r
         if(!this.expanded){\r
      */\r
     expand : function(deep, anim, callback, scope){\r
         if(!this.expanded){\r
@@ -2536,7 +2586,7 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
      * @param {Function} callback (optional) A callback to be called when\r
      * expanding this node completes (does not wait for deep expand to complete).\r
      * Called with 1 parameter, this node.\r
      * @param {Function} callback (optional) A callback to be called when\r
      * expanding this node completes (does not wait for deep expand to complete).\r
      * Called with 1 parameter, this node.\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this TreeNode.\r
      */\r
     collapse : function(deep, anim, callback, scope){\r
         if(this.expanded && !this.isHiddenRoot()){\r
      */\r
     collapse : function(deep, anim, callback, scope){\r
         if(this.expanded && !this.isHiddenRoot()){\r
@@ -2599,7 +2649,7 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
      * Ensures all parent nodes are expanded, and if necessary, scrolls\r
      * the node into view.\r
      * @param {Function} callback (optional) A function to call when the node has been made visible.\r
      * Ensures all parent nodes are expanded, and if necessary, scrolls\r
      * the node into view.\r
      * @param {Function} callback (optional) A function to call when the node has been made visible.\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this TreeNode.\r
      */\r
     ensureVisible : function(callback, scope){\r
         var tree = this.getOwnerTree();\r
      */\r
     ensureVisible : function(callback, scope){\r
         var tree = this.getOwnerTree();\r
@@ -2717,15 +2767,10 @@ Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
     },\r
 \r
     destroy : function(){\r
     },\r
 \r
     destroy : function(){\r
-        if(this.childNodes){\r
-            for(var i = 0,l = this.childNodes.length; i < l; i++){\r
-                this.childNodes[i].destroy();\r
-            }\r
-            this.childNodes = null;\r
-        }\r
-        if(this.ui.destroy){\r
-            this.ui.destroy();\r
-        }\r
+        this.unselect(true);\r
+        Ext.tree.TreeNode.superclass.destroy.call(this);\r
+        Ext.destroy(this.ui, this.loader);\r
+        this.ui = this.loader = null;\r
     },\r
 \r
     // private\r
     },\r
 \r
     // private\r
@@ -2825,7 +2870,7 @@ Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
     /**\r
      * Trigger a reload for this node\r
      * @param {Function} callback\r
     /**\r
      * Trigger a reload for this node\r
      * @param {Function} callback\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Node.\r
      */\r
     reload : function(callback, scope){\r
         this.collapse(false, false);\r
      */\r
     reload : function(callback, scope){\r
         this.collapse(false, false);\r
@@ -2891,9 +2936,9 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     onDisableChange : function(node, state){\r
         this.disabled = state;\r
     // private\r
     onDisableChange : function(node, state){\r
         this.disabled = state;\r
-               if (this.checkbox) {\r
-                       this.checkbox.disabled = state;\r
-               }        \r
+        if (this.checkbox) {\r
+            this.checkbox.disabled = state;\r
+        }        \r
         if(state){\r
             this.addClass("x-tree-node-disabled");\r
         }else{\r
         if(state){\r
             this.addClass("x-tree-node-disabled");\r
         }else{\r
@@ -3078,8 +3123,8 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     onCheckChange : function(){\r
         var checked = this.checkbox.checked;\r
     // private\r
     onCheckChange : function(){\r
         var checked = this.checkbox.checked;\r
-               // fix for IE6\r
-               this.checkbox.defaultChecked = checked;         \r
+        // fix for IE6\r
+        this.checkbox.defaultChecked = checked;        \r
         this.node.attributes.checked = checked;\r
         this.fireEvent('checkchange', this.node, checked);\r
     },\r
         this.node.attributes.checked = checked;\r
         this.fireEvent('checkchange', this.node, checked);\r
     },\r
@@ -3206,7 +3251,10 @@ Ext.tree.TreeNodeUI.prototype = {
         return this.ctNode;  \r
     },\r
 \r
         return this.ctNode;  \r
     },\r
 \r
-    // private\r
+/**\r
+ * Returns the element which encapsulates this node.\r
+ * @return {HtmlElement} The DOM element. The default implementation uses a <code>&lt;li></code>.\r
+ */\r
     getEl : function(){\r
         return this.wrap;  \r
     },\r
     getEl : function(){\r
         return this.wrap;  \r
     },\r
@@ -3269,10 +3317,10 @@ Ext.tree.TreeNodeUI.prototype = {
         // add some indent caching, this helps performance when rendering a large tree\r
         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';\r
 \r
         // add some indent caching, this helps performance when rendering a large tree\r
         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';\r
 \r
-        var cb = typeof a.checked == 'boolean';\r
-\r
-        var href = a.href ? a.href : Ext.isGecko ? "" : "#";\r
-        var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',\r
+        var cb = Ext.isBoolean(a.checked),\r
+            nel,\r
+            href = a.href ? a.href : Ext.isGecko ? "" : "#",\r
+            buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',\r
             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",\r
             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',\r
             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',\r
             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",\r
             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',\r
             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',\r
@@ -3282,7 +3330,6 @@ Ext.tree.TreeNodeUI.prototype = {
             '<ul class="x-tree-node-ct" style="display:none;"></ul>',\r
             "</li>"].join('');\r
 \r
             '<ul class="x-tree-node-ct" style="display:none;"></ul>',\r
             "</li>"].join('');\r
 \r
-        var nel;\r
         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){\r
             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);\r
         }else{\r
         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){\r
             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);\r
         }else{\r
@@ -3298,8 +3345,8 @@ Ext.tree.TreeNodeUI.prototype = {
         var index = 3;\r
         if(cb){\r
             this.checkbox = cs[3];\r
         var index = 3;\r
         if(cb){\r
             this.checkbox = cs[3];\r
-                       // fix for IE6\r
-                       this.checkbox.defaultChecked = this.checkbox.checked;                                           \r
+            // fix for IE6\r
+            this.checkbox.defaultChecked = this.checkbox.checked;\r
             index++;\r
         }\r
         this.anchor = cs[index];\r
             index++;\r
         }\r
         this.anchor = cs[index];\r
@@ -3342,9 +3389,11 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     updateExpandIcon : function(){\r
         if(this.rendered){\r
     // private\r
     updateExpandIcon : function(){\r
         if(this.rendered){\r
-            var n = this.node, c1, c2;\r
-            var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";\r
-            var hasChild = n.hasChildNodes();\r
+            var n = this.node, \r
+                c1, \r
+                c2,\r
+                cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",\r
+                hasChild = n.hasChildNodes();\r
             if(hasChild || n.attributes.expandable){\r
                 if(n.expanded){\r
                     cls += "-minus";\r
             if(hasChild || n.attributes.expandable){\r
                 if(n.expanded){\r
                     cls += "-minus";\r
@@ -3389,8 +3438,8 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     getChildIndent : function(){\r
         if(!this.childIndent){\r
     // private\r
     getChildIndent : function(){\r
         if(!this.childIndent){\r
-            var buf = [];\r
-            var p = this.node;\r
+            var buf = [],\r
+                p = this.node;\r
             while(p){\r
                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){\r
                     if(!p.isLast()) {\r
             while(p){\r
                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){\r
                     if(!p.isLast()) {\r
@@ -3409,8 +3458,8 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     renderIndent : function(){\r
         if(this.rendered){\r
     // private\r
     renderIndent : function(){\r
         if(this.rendered){\r
-            var indent = "";\r
-            var p = this.node.parentNode;\r
+            var indent = "",\r
+                p = this.node.parentNode;\r
             if(p){\r
                 indent = p.ui.getChildIndent();\r
             }\r
             if(p){\r
                 indent = p.ui.getChildIndent();\r
             }\r
@@ -3426,23 +3475,14 @@ Ext.tree.TreeNodeUI.prototype = {
         if(this.elNode){\r
             Ext.dd.Registry.unregister(this.elNode.id);\r
         }\r
         if(this.elNode){\r
             Ext.dd.Registry.unregister(this.elNode.id);\r
         }\r
-        delete this.elNode;\r
-        delete this.ctNode;\r
-        delete this.indentNode;\r
-        delete this.ecNode;\r
-        delete this.iconNode;\r
-        delete this.checkbox;\r
-        delete this.anchor;\r
-        delete this.textNode;\r
         \r
         \r
-        if (this.holder){\r
-             delete this.wrap;\r
-             Ext.removeNode(this.holder);\r
-             delete this.holder;\r
-        }else{\r
-            Ext.removeNode(this.wrap);\r
-            delete this.wrap;\r
-        }\r
+        Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){\r
+            if(this[el]){\r
+                Ext.fly(this[el]).remove();\r
+                delete this[el];\r
+            }\r
+        }, this);\r
+        delete this.node;\r
     }\r
 };\r
 \r
     }\r
 };\r
 \r
@@ -3536,7 +3576,7 @@ Ext.tree.TreeLoader = function(config){
         "loadexception"\r
     );\r
     Ext.tree.TreeLoader.superclass.constructor.call(this);\r
         "loadexception"\r
     );\r
     Ext.tree.TreeLoader.superclass.constructor.call(this);\r
-    if(typeof this.paramOrder == 'string'){\r
+    if(Ext.isString(this.paramOrder)){\r
         this.paramOrder = this.paramOrder.split(/[\s,|]/);\r
     }\r
 };\r
         this.paramOrder = this.paramOrder.split(/[\s,|]/);\r
     }\r
 };\r
@@ -3601,6 +3641,12 @@ paramOrder: 'param1|param2|param'
      * <tt>{@link #paramOrder}</tt> nullifies this configuration.\r
      */\r
     paramsAsHash: false,\r
      * <tt>{@link #paramOrder}</tt> nullifies this configuration.\r
      */\r
     paramsAsHash: false,\r
+    \r
+    /**\r
+     * @cfg {String} nodeParameter The name of the parameter sent to the server which contains\r
+     * the identifier of the node. Defaults to <tt>'node'</tt>.\r
+     */\r
+    nodeParameter: 'node',\r
 \r
     /**\r
      * @cfg {Function} directFn\r
 \r
     /**\r
      * @cfg {Function} directFn\r
@@ -3613,8 +3659,10 @@ paramOrder: 'param1|param2|param'
      * This is called automatically when a node is expanded, but may be used to reload\r
      * a node (or append new children if the {@link #clearOnLoad} option is false.)\r
      * @param {Ext.tree.TreeNode} node\r
      * This is called automatically when a node is expanded, but may be used to reload\r
      * a node (or append new children if the {@link #clearOnLoad} option is false.)\r
      * @param {Ext.tree.TreeNode} node\r
-     * @param {Function} callback\r
-     * @param (Object) scope\r
+     * @param {Function} callback Function to call after the node has been loaded. The \r
+     * function is passed the TreeNode which was requested to be loaded.\r
+     * @param (Object) scope The cope (<code>this</code> reference) in which the callback is executed.\r
+     * defaults to the loaded TreeNode.\r
      */\r
     load : function(node, callback, scope){\r
         if(this.clearOnLoad){\r
      */\r
     load : function(node, callback, scope){\r
         if(this.clearOnLoad){\r
@@ -3662,13 +3710,9 @@ paramOrder: 'param1|param2|param'
             }\r
             return buf;\r
         }else{\r
             }\r
             return buf;\r
         }else{\r
-            for(var key in bp){\r
-                if(!Ext.isFunction(bp[key])){\r
-                    buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");\r
-                }\r
-            }\r
-            buf.push("node=", encodeURIComponent(node.id));\r
-            return buf.join("");\r
+            var o = Ext.apply({}, bp);\r
+            o[this.nodeParameter] = node.id;\r
+            return o;\r
         }\r
     },\r
 \r
         }\r
     },\r
 \r
@@ -3758,7 +3802,7 @@ new Ext.tree.TreePanel({
         if(this.applyLoader !== false && !attr.loader){\r
             attr.loader = this;\r
         }\r
         if(this.applyLoader !== false && !attr.loader){\r
             attr.loader = this;\r
         }\r
-        if(typeof attr.uiProvider == 'string'){\r
+        if(Ext.isString(attr.uiProvider)){\r
            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);\r
         }\r
         if(attr.nodeType){\r
            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);\r
         }\r
         if(attr.nodeType){\r
@@ -3800,6 +3844,10 @@ new Ext.tree.TreePanel({
         var a = response.argument;\r
         this.fireEvent("loadexception", this, a.node, response);\r
         this.runCallback(a.callback, a.scope || a.node, [a.node]);\r
         var a = response.argument;\r
         this.fireEvent("loadexception", this, a.node, response);\r
         this.runCallback(a.callback, a.scope || a.node, [a.node]);\r
+    },\r
+    \r
+    destroy : function(){\r
+        this.purgeListeners();\r
     }\r
 });/**
  * @class Ext.tree.TreeFilter
     }\r
 });/**
  * @class Ext.tree.TreeFilter
@@ -3855,7 +3903,7 @@ Ext.tree.TreeFilter.prototype = {
      * node in the tree (or from the startNode). If the function returns true, the node is kept
      * otherwise it is filtered. If a node is filtered, its children are also filtered.
      * @param {Function} fn The filter function
      * node in the tree (or from the startNode). If the function returns true, the node is kept
      * otherwise it is filtered. If a node is filtered, its children are also filtered.
      * @param {Function} fn The filter function
-     * @param {Object} scope (optional) The scope of the function (defaults to the current node)
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.
      */
     filterBy : function(fn, scope, startNode){
         startNode = startNode || this.tree.root;
      */
     filterBy : function(fn, scope, startNode){
         startNode = startNode || this.tree.root;
@@ -3975,8 +4023,8 @@ Ext.tree.TreeSorter = function(tree, config){
                 return -1;\r
             }\r
         }\r
                 return -1;\r
             }\r
         }\r
-       var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());\r
-       var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());\r
+       var v1 = sortType ? sortType(n1.attributes[p]) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());\r
+       var v2 = sortType ? sortType(n2.attributes[p]) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());\r
        if(v1 < v2){\r
                        return dsc ? +1 : -1;\r
                }else if(v1 > v2){\r
        if(v1 < v2){\r
                        return dsc ? +1 : -1;\r
                }else if(v1 > v2){\r
@@ -4462,12 +4510,18 @@ Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
     editDelay : 350,
 
     initEditor : function(tree){
     editDelay : 350,
 
     initEditor : function(tree){
-        tree.on('beforeclick', this.beforeNodeClick, this);
-        tree.on('dblclick', this.onNodeDblClick, this);
-        this.on('complete', this.updateNode, this);
-        this.on('beforestartedit', this.fitToTree, this);
+        tree.on({
+            scope: this,
+            beforeclick: this.beforeNodeClick,
+            dblclick: this.onNodeDblClick
+        });
+        this.on({
+            scope: this,
+            complete: this.updateNode,
+            beforestartedit: this.fitToTree,
+            specialkey: this.onSpecialKey
+        });
         this.on('startedit', this.bindScroll, this, {delay:10});
         this.on('startedit', this.bindScroll, this, {delay:10});
-        this.on('specialkey', this.onSpecialKey, this);
     },
 
     // private
     },
 
     // private
@@ -4549,5 +4603,13 @@ Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
             e.stopEvent();
             this.completeEdit();
         }
             e.stopEvent();
             this.completeEdit();
         }
+    },
+    
+    onDestroy : function(){
+        clearTimeout(this.autoEditTimer);
+        Ext.tree.TreeEditor.superclass.onDestroy.call(this);
+        var tree = this.tree;
+        tree.un('beforeclick', this.beforeNodeClick, this);
+        tree.un('dblclick', this.onNodeDblClick, this);
     }
 });
\ No newline at end of file
     }
 });
\ No newline at end of file