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