TreePanel.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:30k
源码类别:

中间件编程

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.0.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.tree.TreePanel
  3.  * @extends Ext.Panel
  4.  * <p>The TreePanel provides tree-structured UI representation of tree-structured data.</p>
  5.  * <p>{@link Ext.tree.TreeNode TreeNode}s added to the TreePanel may each contain metadata
  6.  * used by your application in their {@link Ext.tree.TreeNode#attributes attributes} property.</p>
  7.  * <p><b>A TreePanel must have a {@link #root} node before it is rendered.</b> This may either be
  8.  * specified using the {@link #root} config option, or using the {@link #setRootNode} method.
  9.  * <p>An example of tree rendered to an existing div:</p><pre><code>
  10. var tree = new Ext.tree.TreePanel({
  11.     renderTo: 'tree-div',
  12.     useArrows: true,
  13.     autoScroll: true,
  14.     animate: true,
  15.     enableDD: true,
  16.     containerScroll: true,
  17.     border: false,
  18.     // auto create TreeLoader
  19.     dataUrl: 'get-nodes.php',
  20.     root: {
  21.         nodeType: 'async',
  22.         text: 'Ext JS',
  23.         draggable: false,
  24.         id: 'source'
  25.     }
  26. });
  27. tree.getRootNode().expand();
  28.  * </code></pre>
  29.  * <p>The example above would work with a data packet similar to this:</p><pre><code>
  30. [{
  31.     "text": "adapter",
  32.     "id": "source/adapter",
  33.     "cls": "folder"
  34. }, {
  35.     "text": "dd",
  36.     "id": "source/dd",
  37.     "cls": "folder"
  38. }, {
  39.     "text": "debug.js",
  40.     "id": "source/debug.js",
  41.     "leaf": true,
  42.     "cls": "file"
  43. }]
  44.  * </code></pre>
  45.  * <p>An example of tree within a Viewport:</p><pre><code>
  46. new Ext.Viewport({
  47.     layout: 'border',
  48.     items: [{
  49.         region: 'west',
  50.         collapsible: true,
  51.         title: 'Navigation',
  52.         xtype: 'treepanel',
  53.         width: 200,
  54.         autoScroll: true,
  55.         split: true,
  56.         loader: new Ext.tree.TreeLoader(),
  57.         root: new Ext.tree.AsyncTreeNode({
  58.             expanded: true,
  59.             children: [{
  60.                 text: 'Menu Option 1',
  61.                 leaf: true
  62.             }, {
  63.                 text: 'Menu Option 2',
  64.                 leaf: true
  65.             }, {
  66.                 text: 'Menu Option 3',
  67.                 leaf: true
  68.             }]
  69.         }),
  70.         rootVisible: false,
  71.         listeners: {
  72.             click: function(n) {
  73.                 Ext.Msg.alert('Navigation Tree Click', 'You clicked: "' + n.attributes.text + '"');
  74.             }
  75.         }
  76.     }, {
  77.         region: 'center',
  78.         xtype: 'tabpanel',
  79.         // remaining code not shown ...
  80.     }]
  81. });
  82. </code></pre>
  83.  *
  84.  * @cfg {Ext.tree.TreeNode} root The root node for the tree.
  85.  * @cfg {Boolean} rootVisible <tt>false</tt> to hide the root node (defaults to <tt>true</tt>)
  86.  * @cfg {Boolean} lines <tt>false</tt> to disable tree lines (defaults to <tt>true</tt>)
  87.  * @cfg {Boolean} enableDD <tt>true</tt> to enable drag and drop
  88.  * @cfg {Boolean} enableDrag <tt>true</tt> to enable just drag
  89.  * @cfg {Boolean} enableDrop <tt>true</tt> to enable just drop
  90.  * @cfg {Object} dragConfig Custom config to pass to the {@link Ext.tree.TreeDragZone} instance
  91.  * @cfg {Object} dropConfig Custom config to pass to the {@link Ext.tree.TreeDropZone} instance
  92.  * @cfg {String} ddGroup The DD group this TreePanel belongs to
  93.  * @cfg {Boolean} ddAppendOnly <tt>true</tt> if the tree should only allow append drops (use for trees which are sorted)
  94.  * @cfg {Boolean} ddScroll <tt>true</tt> to enable body scrolling
  95.  * @cfg {Boolean} containerScroll <tt>true</tt> to register this container with ScrollManager
  96.  * @cfg {Boolean} hlDrop <tt>false</tt> to disable node highlight on drop (defaults to the value of {@link Ext#enableFx})
  97.  * @cfg {String} hlColor The color of the node highlight (defaults to <tt>'C3DAF9'</tt>)
  98.  * @cfg {Boolean} animate <tt>true</tt> to enable animated expand/collapse (defaults to the value of {@link Ext#enableFx})
  99.  * @cfg {Boolean} singleExpand <tt>true</tt> if only 1 node per branch may be expanded
  100.  * @cfg {Object} selModel A tree selection model to use with this TreePanel (defaults to an {@link Ext.tree.DefaultSelectionModel})
  101.  * @cfg {Boolean} trackMouseOver <tt>false</tt> to disable mouse over highlighting
  102.  * @cfg {Ext.tree.TreeLoader} loader A {@link Ext.tree.TreeLoader} for use with this TreePanel
  103.  * @cfg {String} pathSeparator The token used to separate sub-paths in path strings (defaults to <tt>'/'</tt>)
  104.  * @cfg {Boolean} useArrows <tt>true</tt> to use Vista-style arrows in the tree (defaults to <tt>false</tt>)
  105.  * @cfg {String} requestMethod The HTTP request method for loading data (defaults to the value of {@link Ext.Ajax#method}).
  106.  *
  107.  * @constructor
  108.  * @param {Object} config
  109.  * @xtype treepanel
  110.  */
  111. Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
  112.     rootVisible : true,
  113.     animate: Ext.enableFx,
  114.     lines : true,
  115.     enableDD : false,
  116.     hlDrop : Ext.enableFx,
  117.     pathSeparator: "/",
  118.     initComponent : function(){
  119.         Ext.tree.TreePanel.superclass.initComponent.call(this);
  120.         if(!this.eventModel){
  121.             this.eventModel = new Ext.tree.TreeEventModel(this);
  122.         }
  123.         // initialize the loader
  124.         var l = this.loader;
  125.         if(!l){
  126.             l = new Ext.tree.TreeLoader({
  127.                 dataUrl: this.dataUrl,
  128.                 requestMethod: this.requestMethod
  129.             });
  130.         }else if(typeof l == 'object' && !l.load){
  131.             l = new Ext.tree.TreeLoader(l);
  132.         }
  133.         this.loader = l;
  134.         this.nodeHash = {};
  135.         /**
  136.         * The root node of this tree.
  137.         * @type Ext.tree.TreeNode
  138.         * @property root
  139.         */
  140.         if(this.root){
  141.             var r = this.root;
  142.             delete this.root;
  143.             this.setRootNode(r);
  144.         }
  145.         this.addEvents(
  146.             /**
  147.             * @event append
  148.             * Fires when a new child node is appended to a node in this tree.
  149.             * @param {Tree} tree The owner tree
  150.             * @param {Node} parent The parent node
  151.             * @param {Node} node The newly appended node
  152.             * @param {Number} index The index of the newly appended node
  153.             */
  154.            "append",
  155.            /**
  156.             * @event remove
  157.             * Fires when a child node is removed from a node in this tree.
  158.             * @param {Tree} tree The owner tree
  159.             * @param {Node} parent The parent node
  160.             * @param {Node} node The child node removed
  161.             */
  162.            "remove",
  163.            /**
  164.             * @event movenode
  165.             * Fires when a node is moved to a new location in the tree
  166.             * @param {Tree} tree The owner tree
  167.             * @param {Node} node The node moved
  168.             * @param {Node} oldParent The old parent of this node
  169.             * @param {Node} newParent The new parent of this node
  170.             * @param {Number} index The index it was moved to
  171.             */
  172.            "movenode",
  173.            /**
  174.             * @event insert
  175.             * Fires when a new child node is inserted in a node in this tree.
  176.             * @param {Tree} tree The owner tree
  177.             * @param {Node} parent The parent node
  178.             * @param {Node} node The child node inserted
  179.             * @param {Node} refNode The child node the node was inserted before
  180.             */
  181.            "insert",
  182.            /**
  183.             * @event beforeappend
  184.             * Fires before a new child is appended to a node in this tree, return false to cancel the append.
  185.             * @param {Tree} tree The owner tree
  186.             * @param {Node} parent The parent node
  187.             * @param {Node} node The child node to be appended
  188.             */
  189.            "beforeappend",
  190.            /**
  191.             * @event beforeremove
  192.             * Fires before a child is removed from a node in this tree, return false to cancel the remove.
  193.             * @param {Tree} tree The owner tree
  194.             * @param {Node} parent The parent node
  195.             * @param {Node} node The child node to be removed
  196.             */
  197.            "beforeremove",
  198.            /**
  199.             * @event beforemovenode
  200.             * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
  201.             * @param {Tree} tree The owner tree
  202.             * @param {Node} node The node being moved
  203.             * @param {Node} oldParent The parent of the node
  204.             * @param {Node} newParent The new parent the node is moving to
  205.             * @param {Number} index The index it is being moved to
  206.             */
  207.            "beforemovenode",
  208.            /**
  209.             * @event beforeinsert
  210.             * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
  211.             * @param {Tree} tree The owner tree
  212.             * @param {Node} parent The parent node
  213.             * @param {Node} node The child node to be inserted
  214.             * @param {Node} refNode The child node the node is being inserted before
  215.             */
  216.             "beforeinsert",
  217.             /**
  218.             * @event beforeload
  219.             * Fires before a node is loaded, return false to cancel
  220.             * @param {Node} node The node being loaded
  221.             */
  222.             "beforeload",
  223.             /**
  224.             * @event load
  225.             * Fires when a node is loaded
  226.             * @param {Node} node The node that was loaded
  227.             */
  228.             "load",
  229.             /**
  230.             * @event textchange
  231.             * Fires when the text for a node is changed
  232.             * @param {Node} node The node
  233.             * @param {String} text The new text
  234.             * @param {String} oldText The old text
  235.             */
  236.             "textchange",
  237.             /**
  238.             * @event beforeexpandnode
  239.             * Fires before a node is expanded, return false to cancel.
  240.             * @param {Node} node The node
  241.             * @param {Boolean} deep
  242.             * @param {Boolean} anim
  243.             */
  244.             "beforeexpandnode",
  245.             /**
  246.             * @event beforecollapsenode
  247.             * Fires before a node is collapsed, return false to cancel.
  248.             * @param {Node} node The node
  249.             * @param {Boolean} deep
  250.             * @param {Boolean} anim
  251.             */
  252.             "beforecollapsenode",
  253.             /**
  254.             * @event expandnode
  255.             * Fires when a node is expanded
  256.             * @param {Node} node The node
  257.             */
  258.             "expandnode",
  259.             /**
  260.             * @event disabledchange
  261.             * Fires when the disabled status of a node changes
  262.             * @param {Node} node The node
  263.             * @param {Boolean} disabled
  264.             */
  265.             "disabledchange",
  266.             /**
  267.             * @event collapsenode
  268.             * Fires when a node is collapsed
  269.             * @param {Node} node The node
  270.             */
  271.             "collapsenode",
  272.             /**
  273.             * @event beforeclick
  274.             * Fires before click processing on a node. Return false to cancel the default action.
  275.             * @param {Node} node The node
  276.             * @param {Ext.EventObject} e The event object
  277.             */
  278.             "beforeclick",
  279.             /**
  280.             * @event click
  281.             * Fires when a node is clicked
  282.             * @param {Node} node The node
  283.             * @param {Ext.EventObject} e The event object
  284.             */
  285.             "click",
  286.             /**
  287.             * @event checkchange
  288.             * Fires when a node with a checkbox's checked property changes
  289.             * @param {Node} this This node
  290.             * @param {Boolean} checked
  291.             */
  292.             "checkchange",
  293.             /**
  294.             * @event dblclick
  295.             * Fires when a node is double clicked
  296.             * @param {Node} node The node
  297.             * @param {Ext.EventObject} e The event object
  298.             */
  299.             "dblclick",
  300.             /**
  301.             * @event contextmenu
  302.             * Fires when a node is right clicked. To display a context menu in response to this
  303.             * event, first create a Menu object (see {@link Ext.menu.Menu} for details), then add
  304.             * a handler for this event:<pre><code>
  305. new Ext.tree.TreePanel({
  306.     title: 'My TreePanel',
  307.     root: new Ext.tree.AsyncTreeNode({
  308.         text: 'The Root',
  309.         children: [
  310.             { text: 'Child node 1', leaf: true },
  311.             { text: 'Child node 2', leaf: true }
  312.         ]
  313.     }),
  314.     contextMenu: new Ext.menu.Menu({
  315.         items: [{
  316.             id: 'delete-node',
  317.             text: 'Delete Node'
  318.         }],
  319.         listeners: {
  320.             itemclick: function(item) {
  321.                 switch (item.id) {
  322.                     case 'delete-node':
  323.                         var n = item.parentMenu.contextNode;
  324.                         if (n.parentNode) {
  325.                             n.remove();
  326.                         }
  327.                         break;
  328.                 }
  329.             }
  330.         }
  331.     }),
  332.     listeners: {
  333.         contextmenu: function(node, e) {
  334. //          Register the context node with the menu so that a Menu Item's handler function can access
  335. //          it via its {@link Ext.menu.BaseItem#parentMenu parentMenu} property.
  336.             node.select();
  337.             var c = node.getOwnerTree().contextMenu;
  338.             c.contextNode = node;
  339.             c.showAt(e.getXY());
  340.         }
  341.     }
  342. });
  343. </code></pre>
  344.             * @param {Node} node The node
  345.             * @param {Ext.EventObject} e The event object
  346.             */
  347.             "contextmenu",
  348.             /**
  349.             * @event beforechildrenrendered
  350.             * Fires right before the child nodes for a node are rendered
  351.             * @param {Node} node The node
  352.             */
  353.             "beforechildrenrendered",
  354.            /**
  355.              * @event startdrag
  356.              * Fires when a node starts being dragged
  357.              * @param {Ext.tree.TreePanel} this
  358.              * @param {Ext.tree.TreeNode} node
  359.              * @param {event} e The raw browser event
  360.              */
  361.             "startdrag",
  362.             /**
  363.              * @event enddrag
  364.              * Fires when a drag operation is complete
  365.              * @param {Ext.tree.TreePanel} this
  366.              * @param {Ext.tree.TreeNode} node
  367.              * @param {event} e The raw browser event
  368.              */
  369.             "enddrag",
  370.             /**
  371.              * @event dragdrop
  372.              * Fires when a dragged node is dropped on a valid DD target
  373.              * @param {Ext.tree.TreePanel} this
  374.              * @param {Ext.tree.TreeNode} node
  375.              * @param {DD} dd The dd it was dropped on
  376.              * @param {event} e The raw browser event
  377.              */
  378.             "dragdrop",
  379.             /**
  380.              * @event beforenodedrop
  381.              * Fires when a DD object is dropped on a node in this tree for preprocessing. Return false to cancel the drop. The dropEvent
  382.              * passed to handlers has the following properties:<br />
  383.              * <ul style="padding:5px;padding-left:16px;">
  384.              * <li>tree - The TreePanel</li>
  385.              * <li>target - The node being targeted for the drop</li>
  386.              * <li>data - The drag data from the drag source</li>
  387.              * <li>point - The point of the drop - append, above or below</li>
  388.              * <li>source - The drag source</li>
  389.              * <li>rawEvent - Raw mouse event</li>
  390.              * <li>dropNode - Drop node(s) provided by the source <b>OR</b> you can supply node(s)
  391.              * to be inserted by setting them on this object.</li>
  392.              * <li>cancel - Set this to true to cancel the drop.</li>
  393.              * <li>dropStatus - If the default drop action is cancelled but the drop is valid, setting this to true
  394.              * will prevent the animated "repair" from appearing.</li>
  395.              * </ul>
  396.              * @param {Object} dropEvent
  397.              */
  398.             "beforenodedrop",
  399.             /**
  400.              * @event nodedrop
  401.              * Fires after a DD object is dropped on a node in this tree. The dropEvent
  402.              * passed to handlers has the following properties:<br />
  403.              * <ul style="padding:5px;padding-left:16px;">
  404.              * <li>tree - The TreePanel</li>
  405.              * <li>target - The node being targeted for the drop</li>
  406.              * <li>data - The drag data from the drag source</li>
  407.              * <li>point - The point of the drop - append, above or below</li>
  408.              * <li>source - The drag source</li>
  409.              * <li>rawEvent - Raw mouse event</li>
  410.              * <li>dropNode - Dropped node(s).</li>
  411.              * </ul>
  412.              * @param {Object} dropEvent
  413.              */
  414.             "nodedrop",
  415.              /**
  416.              * @event nodedragover
  417.              * Fires when a tree node is being targeted for a drag drop, return false to signal drop not allowed. The dragOverEvent
  418.              * passed to handlers has the following properties:<br />
  419.              * <ul style="padding:5px;padding-left:16px;">
  420.              * <li>tree - The TreePanel</li>
  421.              * <li>target - The node being targeted for the drop</li>
  422.              * <li>data - The drag data from the drag source</li>
  423.              * <li>point - The point of the drop - append, above or below</li>
  424.              * <li>source - The drag source</li>
  425.              * <li>rawEvent - Raw mouse event</li>
  426.              * <li>dropNode - Drop node(s) provided by the source.</li>
  427.              * <li>cancel - Set this to true to signal drop not allowed.</li>
  428.              * </ul>
  429.              * @param {Object} dragOverEvent
  430.              */
  431.             "nodedragover"
  432.         );
  433.         if(this.singleExpand){
  434.             this.on("beforeexpandnode", this.restrictExpand, this);
  435.         }
  436.     },
  437.     // private
  438.     proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
  439.         if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
  440.             ename = ename+'node';
  441.         }
  442.         // args inline for performance while bubbling events
  443.         return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
  444.     },
  445.     /**
  446.      * Returns this root node for this tree
  447.      * @return {Node}
  448.      */
  449.     getRootNode : function(){
  450.         return this.root;
  451.     },
  452.     /**
  453.      * Sets the root node for this tree. If the TreePanel has already rendered a root node, the
  454.      * previous root node (and all of its descendants) are destroyed before the new root node is rendered.
  455.      * @param {Node} node
  456.      * @return {Node}
  457.      */
  458.     setRootNode : function(node){
  459.         Ext.destroy(this.root);
  460.         if(!node.render){ // attributes passed
  461.             node = this.loader.createNode(node);
  462.         }
  463.         this.root = node;
  464.         node.ownerTree = this;
  465.         node.isRoot = true;
  466.         this.registerNode(node);
  467.         if(!this.rootVisible){
  468.             var uiP = node.attributes.uiProvider;
  469.             node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
  470.         }
  471.         if (this.innerCt) {
  472.             this.innerCt.update('');
  473.             this.afterRender();
  474.         }
  475.         return node;
  476.     },
  477.     /**
  478.      * Gets a node in this tree by its id
  479.      * @param {String} id
  480.      * @return {Node}
  481.      */
  482.     getNodeById : function(id){
  483.         return this.nodeHash[id];
  484.     },
  485.     // private
  486.     registerNode : function(node){
  487.         this.nodeHash[node.id] = node;
  488.     },
  489.     // private
  490.     unregisterNode : function(node){
  491.         delete this.nodeHash[node.id];
  492.     },
  493.     // private
  494.     toString : function(){
  495.         return "[Tree"+(this.id?" "+this.id:"")+"]";
  496.     },
  497.     // private
  498.     restrictExpand : function(node){
  499.         var p = node.parentNode;
  500.         if(p){
  501.             if(p.expandedChild && p.expandedChild.parentNode == p){
  502.                 p.expandedChild.collapse();
  503.             }
  504.             p.expandedChild = node;
  505.         }
  506.     },
  507.     /**
  508.      * Retrieve an array of checked nodes, or an array of a specific attribute of checked nodes (e.g. "id")
  509.      * @param {String} attribute (optional) Defaults to null (return the actual nodes)
  510.      * @param {TreeNode} startNode (optional) The node to start from, defaults to the root
  511.      * @return {Array}
  512.      */
  513.     getChecked : function(a, startNode){
  514.         startNode = startNode || this.root;
  515.         var r = [];
  516.         var f = function(){
  517.             if(this.attributes.checked){
  518.                 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
  519.             }
  520.         };
  521.         startNode.cascade(f);
  522.         return r;
  523.     },
  524.     /**
  525.      * Returns the container element for this TreePanel.
  526.      * @return {Element} The container element for this TreePanel.
  527.      */
  528.     getEl : function(){
  529.         return this.el;
  530.     },
  531.     /**
  532.      * Returns the default {@link Ext.tree.TreeLoader} for this TreePanel.
  533.      * @return {Ext.tree.TreeLoader} The TreeLoader for this TreePanel.
  534.      */
  535.     getLoader : function(){
  536.         return this.loader;
  537.     },
  538.     /**
  539.      * Expand all nodes
  540.      */
  541.     expandAll : function(){
  542.         this.root.expand(true);
  543.     },
  544.     /**
  545.      * Collapse all nodes
  546.      */
  547.     collapseAll : function(){
  548.         this.root.collapse(true);
  549.     },
  550.     /**
  551.      * Returns the selection model used by this TreePanel.
  552.      * @return {TreeSelectionModel} The selection model used by this TreePanel
  553.      */
  554.     getSelectionModel : function(){
  555.         if(!this.selModel){
  556.             this.selModel = new Ext.tree.DefaultSelectionModel();
  557.         }
  558.         return this.selModel;
  559.     },
  560.     /**
  561.      * Expands a specified path in this TreePanel. A path can be retrieved from a node with {@link Ext.data.Node#getPath}
  562.      * @param {String} path
  563.      * @param {String} attr (optional) The attribute used in the path (see {@link Ext.data.Node#getPath} for more info)
  564.      * @param {Function} callback (optional) The callback to call when the expand is complete. The callback will be called with
  565.      * (bSuccess, oLastNode) where bSuccess is if the expand was successful and oLastNode is the last node that was expanded.
  566.      */
  567.     expandPath : function(path, attr, callback){
  568.         attr = attr || "id";
  569.         var keys = path.split(this.pathSeparator);
  570.         var curNode = this.root;
  571.         if(curNode.attributes[attr] != keys[1]){ // invalid root
  572.             if(callback){
  573.                 callback(false, null);
  574.             }
  575.             return;
  576.         }
  577.         var index = 1;
  578.         var f = function(){
  579.             if(++index == keys.length){
  580.                 if(callback){
  581.                     callback(true, curNode);
  582.                 }
  583.                 return;
  584.             }
  585.             var c = curNode.findChild(attr, keys[index]);
  586.             if(!c){
  587.                 if(callback){
  588.                     callback(false, curNode);
  589.                 }
  590.                 return;
  591.             }
  592.             curNode = c;
  593.             c.expand(false, false, f);
  594.         };
  595.         curNode.expand(false, false, f);
  596.     },
  597.     /**
  598.      * Selects the node in this tree at the specified path. A path can be retrieved from a node with {@link Ext.data.Node#getPath}
  599.      * @param {String} path
  600.      * @param {String} attr (optional) The attribute used in the path (see {@link Ext.data.Node#getPath} for more info)
  601.      * @param {Function} callback (optional) The callback to call when the selection is complete. The callback will be called with
  602.      * (bSuccess, oSelNode) where bSuccess is if the selection was successful and oSelNode is the selected node.
  603.      */
  604.     selectPath : function(path, attr, callback){
  605.         attr = attr || "id";
  606.         var keys = path.split(this.pathSeparator);
  607.         var v = keys.pop();
  608.         if(keys.length > 0){
  609.             var f = function(success, node){
  610.                 if(success && node){
  611.                     var n = node.findChild(attr, v);
  612.                     if(n){
  613.                         n.select();
  614.                         if(callback){
  615.                             callback(true, n);
  616.                         }
  617.                     }else if(callback){
  618.                         callback(false, n);
  619.                     }
  620.                 }else{
  621.                     if(callback){
  622.                         callback(false, n);
  623.                     }
  624.                 }
  625.             };
  626.             this.expandPath(keys.join(this.pathSeparator), attr, f);
  627.         }else{
  628.             this.root.select();
  629.             if(callback){
  630.                 callback(true, this.root);
  631.             }
  632.         }
  633.     },
  634.     /**
  635.      * Returns the underlying Element for this tree
  636.      * @return {Ext.Element} The Element
  637.      */
  638.     getTreeEl : function(){
  639.         return this.body;
  640.     },
  641.     // private
  642.     onRender : function(ct, position){
  643.         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
  644.         this.el.addClass('x-tree');
  645.         this.innerCt = this.body.createChild({tag:"ul",
  646.                cls:"x-tree-root-ct " +
  647.                (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});
  648.     },
  649.     // private
  650.     initEvents : function(){
  651.         Ext.tree.TreePanel.superclass.initEvents.call(this);
  652.         if(this.containerScroll){
  653.             Ext.dd.ScrollManager.register(this.body);
  654.         }
  655.         if((this.enableDD || this.enableDrop) && !this.dropZone){
  656.            /**
  657.             * The dropZone used by this tree if drop is enabled (see {@link #enableDD} or {@link #enableDrop})
  658.             * @property dropZone
  659.             * @type Ext.tree.TreeDropZone
  660.             */
  661.              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
  662.                ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true
  663.            });
  664.         }
  665.         if((this.enableDD || this.enableDrag) && !this.dragZone){
  666.            /**
  667.             * The dragZone used by this tree if drag is enabled (see {@link #enableDD} or {@link #enableDrag})
  668.             * @property dragZone
  669.             * @type Ext.tree.TreeDragZone
  670.             */
  671.             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
  672.                ddGroup: this.ddGroup || "TreeDD",
  673.                scroll: this.ddScroll
  674.            });
  675.         }
  676.         this.getSelectionModel().init(this);
  677.     },
  678.     // private
  679.     afterRender : function(){
  680.         Ext.tree.TreePanel.superclass.afterRender.call(this);
  681.         this.root.render();
  682.         if(!this.rootVisible){
  683.             this.root.renderChildren();
  684.         }
  685.     },
  686.     onDestroy : function(){
  687.         if(this.rendered){
  688.             this.body.removeAllListeners();
  689.             Ext.dd.ScrollManager.unregister(this.body);
  690.             if(this.dropZone){
  691.                 this.dropZone.unreg();
  692.             }
  693.             if(this.dragZone){
  694.                this.dragZone.unreg();
  695.             }
  696.         }
  697.         this.root.destroy();
  698.         this.nodeHash = null;
  699.         Ext.tree.TreePanel.superclass.onDestroy.call(this);
  700.     }
  701.     /**
  702.      * @cfg {String/Number} activeItem
  703.      * @hide
  704.      */
  705.     /**
  706.      * @cfg {Boolean} autoDestroy
  707.      * @hide
  708.      */
  709.     /**
  710.      * @cfg {Object/String/Function} autoLoad
  711.      * @hide
  712.      */
  713.     /**
  714.      * @cfg {Boolean} autoWidth
  715.      * @hide
  716.      */
  717.     /**
  718.      * @cfg {Boolean/Number} bufferResize
  719.      * @hide
  720.      */
  721.     /**
  722.      * @cfg {String} defaultType
  723.      * @hide
  724.      */
  725.     /**
  726.      * @cfg {Object} defaults
  727.      * @hide
  728.      */
  729.     /**
  730.      * @cfg {Boolean} hideBorders
  731.      * @hide
  732.      */
  733.     /**
  734.      * @cfg {Mixed} items
  735.      * @hide
  736.      */
  737.     /**
  738.      * @cfg {String} layout
  739.      * @hide
  740.      */
  741.     /**
  742.      * @cfg {Object} layoutConfig
  743.      * @hide
  744.      */
  745.     /**
  746.      * @cfg {Boolean} monitorResize
  747.      * @hide
  748.      */
  749.     /**
  750.      * @property items
  751.      * @hide
  752.      */
  753.     /**
  754.      * @method cascade
  755.      * @hide
  756.      */
  757.     /**
  758.      * @method doLayout
  759.      * @hide
  760.      */
  761.     /**
  762.      * @method find
  763.      * @hide
  764.      */
  765.     /**
  766.      * @method findBy
  767.      * @hide
  768.      */
  769.     /**
  770.      * @method findById
  771.      * @hide
  772.      */
  773.     /**
  774.      * @method findByType
  775.      * @hide
  776.      */
  777.     /**
  778.      * @method getComponent
  779.      * @hide
  780.      */
  781.     /**
  782.      * @method getLayout
  783.      * @hide
  784.      */
  785.     /**
  786.      * @method getUpdater
  787.      * @hide
  788.      */
  789.     /**
  790.      * @method insert
  791.      * @hide
  792.      */
  793.     /**
  794.      * @method load
  795.      * @hide
  796.      */
  797.     /**
  798.      * @method remove
  799.      * @hide
  800.      */
  801.     /**
  802.      * @event add
  803.      * @hide
  804.      */
  805.     /**
  806.      * @method removeAll
  807.      * @hide
  808.      */
  809.     /**
  810.      * @event afterLayout
  811.      * @hide
  812.      */
  813.     /**
  814.      * @event beforeadd
  815.      * @hide
  816.      */
  817.     /**
  818.      * @event beforeremove
  819.      * @hide
  820.      */
  821.     /**
  822.      * @event remove
  823.      * @hide
  824.      */
  825.     /**
  826.      * @cfg {String} allowDomMove  @hide
  827.      */
  828.     /**
  829.      * @cfg {String} autoEl @hide
  830.      */
  831.     /**
  832.      * @cfg {String} applyTo  @hide
  833.      */
  834.     /**
  835.      * @cfg {String} contentEl  @hide
  836.      */
  837.     /**
  838.      * @cfg {String} disabledClass  @hide
  839.      */
  840.     /**
  841.      * @cfg {String} elements  @hide
  842.      */
  843.     /**
  844.      * @cfg {String} html  @hide
  845.      */
  846.     /**
  847.      * @cfg {Boolean} preventBodyReset
  848.      * @hide
  849.      */
  850.     /**
  851.      * @property disabled
  852.      * @hide
  853.      */
  854.     /**
  855.      * @method applyToMarkup
  856.      * @hide
  857.      */
  858.     /**
  859.      * @method enable
  860.      * @hide
  861.      */
  862.     /**
  863.      * @method disable
  864.      * @hide
  865.      */
  866.     /**
  867.      * @method setDisabled
  868.      * @hide
  869.      */
  870. });
  871. Ext.tree.TreePanel.nodeTypes = {};
  872. Ext.reg('treepanel', Ext.tree.TreePanel);