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