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