4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-tree-Panel'>/**
19 </span> * @class Ext.tree.Panel
20 * @extends Ext.panel.Table
22 * The TreePanel provides tree-structured UI representation of tree-structured data.
23 * A TreePanel must be bound to a {@link Ext.data.TreeStore}. TreePanel's support
24 * multiple columns through the {@link columns} configuration.
26 * Simple TreePanel using inline data.
28 * {@img Ext.tree.Panel/Ext.tree.Panel1.png Ext.tree.Panel component}
30 * ## Simple Tree Panel (no columns)
32 * var store = Ext.create('Ext.data.TreeStore', {
37 * status:"",
39 * { text:"detention", leaf: true },
40 * { text:"homework", expanded: true,
42 * { text:"book report", leaf: true },
43 * { text:"alegrbra", leaf: true}
46 * { text: "buy lottery tickets", leaf:true }
51 * Ext.create('Ext.tree.Panel', {
52 * title: 'Simple Tree',
57 * renderTo: Ext.getBody()
62 Ext.define('Ext.tree.Panel', {
63 extend: 'Ext.panel.Table',
64 alias: 'widget.treepanel',
65 alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
66 requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'],
70 treeCls: Ext.baseCSSPrefix + 'tree-panel',
72 <span id='Ext-tree-Panel-cfg-lines'> /**
73 </span> * @cfg {Boolean} lines false to disable tree lines (defaults to true)
77 <span id='Ext-tree-Panel-cfg-useArrows'> /**
78 </span> * @cfg {Boolean} useArrows true to use Vista-style arrows in the tree (defaults to false)
82 <span id='Ext-tree-Panel-cfg-singleExpand'> /**
83 </span> * @cfg {Boolean} singleExpand <tt>true</tt> if only 1 node per branch may be expanded
92 <span id='Ext-tree-Panel-cfg-animate'> /**
93 </span> * @cfg {Boolean} animate <tt>true</tt> to enable animated expand/collapse (defaults to the value of {@link Ext#enableFx Ext.enableFx})
96 <span id='Ext-tree-Panel-cfg-rootVisible'> /**
97 </span> * @cfg {Boolean} rootVisible <tt>false</tt> to hide the root node (defaults to <tt>true</tt>)
101 <span id='Ext-tree-Panel-cfg-displayField'> /**
102 </span> * @cfg {Boolean} displayField The field inside the model that will be used as the node's text. (defaults to <tt>text</tt>)
104 displayField: 'text',
106 <span id='Ext-tree-Panel-cfg-root'> /**
107 </span> * @cfg {Boolean} root Allows you to not specify a store on this TreePanel. This is useful for creating a simple
108 * tree with preloaded data without having to specify a TreeStore and Model. A store and model will be created and
109 * root will be passed to that store.
113 // Required for the Lockable Mixin. These are the configurations which will be copied to the
114 // normal and locked sub tablepanels
115 normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'],
116 lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],
118 <span id='Ext-tree-Panel-cfg-hideHeaders'> /**
119 </span> * @cfg {Boolean} hideHeaders
120 * Specify as <code>true</code> to hide the headers.
123 <span id='Ext-tree-Panel-cfg-folderSort'> /**
124 </span> * @cfg {Boolean} folderSort Set to true to automatically prepend a leaf sorter to the store (defaults to <tt>undefined</tt>)
127 constructor: function(config) {
128 config = config || {};
129 if (config.animate === undefined) {
130 config.animate = Ext.enableFx;
132 this.enableAnimations = config.animate;
133 delete config.animate;
135 this.callParent([config]);
138 initComponent: function() {
143 cls.push(Ext.baseCSSPrefix + 'tree-arrows');
148 cls.push(Ext.baseCSSPrefix + 'tree-lines');
149 } else if (!me.useArrows) {
150 cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
153 if (Ext.isString(me.store)) {
154 me.store = Ext.StoreMgr.lookup(me.store);
155 } else if (!me.store || Ext.isObject(me.store) && !me.store.isStore) {
156 me.store = Ext.create('Ext.data.TreeStore', Ext.apply({}, me.store || {}, {
160 folderSort: me.folderSort
162 } else if (me.root) {
163 me.store = Ext.data.StoreManager.lookup(me.store);
164 me.store.setRootNode(me.root);
165 if (me.folderSort !== undefined) {
166 me.store.folderSort = me.folderSort;
171 // I'm not sure if we want to this. It might be confusing
172 // if (me.initialConfig.rootVisible === undefined && !me.getRootNode()) {
173 // me.rootVisible = false;
176 me.viewConfig = Ext.applyIf(me.viewConfig || {}, {
177 rootVisible: me.rootVisible,
178 animate: me.enableAnimations,
179 singleExpand: me.singleExpand,
180 node: me.store.getRootNode(),
181 hideHeaders: me.hideHeaders
186 rootchange: me.onRootChange,
190 me.relayEvents(me.store, [
191 <span id='Ext-tree-Panel-event-beforeload'> /**
192 </span> * @event beforeload
194 * @param {Ext.data.Store} store This Store
195 * @param {Ext.data.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to load the Store
199 <span id='Ext-tree-Panel-event-load'> /**
200 </span> * @event load
201 * Fires whenever the store reads data from a remote data source.
202 * @param {Ext.data.store} this
203 * @param {Array} records An array of records
204 * @param {Boolean} successful True if the operation was successful.
210 <span id='Ext-tree-Panel-event-itemappend'> /**
211 </span> * @event itemappend
212 * Fires when a new child node is appended to a node in the tree.
213 * @param {Tree} tree The owner tree
214 * @param {Node} parent The parent node
215 * @param {Node} node The newly appended node
216 * @param {Number} index The index of the newly appended node
218 append: me.createRelayer('itemappend'),
220 <span id='Ext-tree-Panel-event-itemremove'> /**
221 </span> * @event itemremove
222 * Fires when a child node is removed from a node in the tree
223 * @param {Tree} tree The owner tree
224 * @param {Node} parent The parent node
225 * @param {Node} node The child node removed
227 remove: me.createRelayer('itemremove'),
229 <span id='Ext-tree-Panel-event-itemmove'> /**
230 </span> * @event itemmove
231 * Fires when a node is moved to a new location in the tree
232 * @param {Tree} tree The owner tree
233 * @param {Node} node The node moved
234 * @param {Node} oldParent The old parent of this node
235 * @param {Node} newParent The new parent of this node
236 * @param {Number} index The index it was moved to
238 move: me.createRelayer('itemmove'),
240 <span id='Ext-tree-Panel-event-iteminsert'> /**
241 </span> * @event iteminsert
242 * Fires when a new child node is inserted in a node in tree
243 * @param {Tree} tree The owner tree
244 * @param {Node} parent The parent node
245 * @param {Node} node The child node inserted
246 * @param {Node} refNode The child node the node was inserted before
248 insert: me.createRelayer('iteminsert'),
250 <span id='Ext-tree-Panel-event-beforeitemappend'> /**
251 </span> * @event beforeitemappend
252 * Fires before a new child is appended to a node in this tree, return false to cancel the append.
253 * @param {Tree} tree The owner tree
254 * @param {Node} parent The parent node
255 * @param {Node} node The child node to be appended
257 beforeappend: me.createRelayer('beforeitemappend'),
259 <span id='Ext-tree-Panel-event-beforeitemremove'> /**
260 </span> * @event beforeitemremove
261 * Fires before a child is removed from a node in this tree, return false to cancel the remove.
262 * @param {Tree} tree The owner tree
263 * @param {Node} parent The parent node
264 * @param {Node} node The child node to be removed
266 beforeremove: me.createRelayer('beforeitemremove'),
268 <span id='Ext-tree-Panel-event-beforeitemmove'> /**
269 </span> * @event beforeitemmove
270 * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
271 * @param {Tree} tree The owner tree
272 * @param {Node} node The node being moved
273 * @param {Node} oldParent The parent of the node
274 * @param {Node} newParent The new parent the node is moving to
275 * @param {Number} index The index it is being moved to
277 beforemove: me.createRelayer('beforeitemmove'),
279 <span id='Ext-tree-Panel-event-beforeiteminsert'> /**
280 </span> * @event beforeiteminsert
281 * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
282 * @param {Tree} tree The owner tree
283 * @param {Node} parent The parent node
284 * @param {Node} node The child node to be inserted
285 * @param {Node} refNode The child node the node is being inserted before
287 beforeinsert: me.createRelayer('beforeiteminsert'),
289 <span id='Ext-tree-Panel-event-itemexpand'> /**
290 </span> * @event itemexpand
291 * Fires when a node is expanded.
292 * @param {Node} this The expanding node
294 expand: me.createRelayer('itemexpand'),
296 <span id='Ext-tree-Panel-event-itemcollapse'> /**
297 </span> * @event itemcollapse
298 * Fires when a node is collapsed.
299 * @param {Node} this The collapsing node
301 collapse: me.createRelayer('itemcollapse'),
303 <span id='Ext-tree-Panel-event-beforeitemexpand'> /**
304 </span> * @event beforeitemexpand
305 * Fires before a node is expanded.
306 * @param {Node} this The expanding node
308 beforeexpand: me.createRelayer('beforeitemexpand'),
310 <span id='Ext-tree-Panel-event-beforeitemcollapse'> /**
311 </span> * @event beforeitemcollapse
312 * Fires before a node is collapsed.
313 * @param {Node} this The collapsing node
315 beforecollapse: me.createRelayer('beforeitemcollapse')
318 // If the user specifies the headers collection manually then dont inject our own
320 if (me.initialConfig.hideHeaders === undefined) {
321 me.hideHeaders = true;
324 xtype : 'treecolumn',
327 dataIndex: me.displayField
334 me.cls = cls.join(' ');
337 me.relayEvents(me.getView(), [
338 <span id='Ext-tree-Panel-event-checkchange'> /**
339 </span> * @event checkchange
340 * Fires when a node with a checkbox's checked property changes
341 * @param {Ext.data.Model} node The node who's checked property was changed
342 * @param {Boolean} checked The node's new checked state
347 // If the root is not visible and there is no rootnode defined, then just lets load the store
348 if (!me.getView().rootVisible && !me.getRootNode()) {
359 setRootNode: function() {
360 return this.store.setRootNode.apply(this.store, arguments);
363 getRootNode: function() {
364 return this.store.getRootNode();
367 onRootChange: function(root) {
368 this.view.setRootNode(root);
371 <span id='Ext-tree-Panel-method-getChecked'> /**
372 </span> * Retrieve an array of checked records.
373 * @return {Array} An array containing the checked records
375 getChecked: function() {
376 return this.getView().getChecked();
379 isItemChecked: function(rec) {
380 return rec.get('checked');
383 <span id='Ext-tree-Panel-method-expandAll'> /**
384 </span> * Expand all nodes
385 * @param {Function} callback (optional) A function to execute when the expand finishes.
386 * @param {Object} scope (optional) The scope of the callback function
388 expandAll : function(callback, scope) {
389 var root = this.getRootNode();
391 root.expand(true, callback, scope);
395 <span id='Ext-tree-Panel-method-collapseAll'> /**
396 </span> * Collapse all nodes
397 * @param {Function} callback (optional) A function to execute when the collapse finishes.
398 * @param {Object} scope (optional) The scope of the callback function
400 collapseAll : function(callback, scope) {
401 var root = this.getRootNode();
403 if (this.getView().rootVisible) {
404 root.collapse(true, callback, scope);
407 root.collapseChildren(true, callback, scope);
412 <span id='Ext-tree-Panel-method-expandPath'> /**
413 </span> * Expand the tree to the path of a particular node.
414 * @param {String} path The path to expand. The path should include a leading separator.
415 * @param {String} field (optional) The field to get the data from. Defaults to the model idProperty.
416 * @param {String} separator (optional) A separator to use. Defaults to <tt>'/'</tt>.
417 * @param {Function} callback (optional) A function to execute when the expand finishes. The callback will be called with
418 * (success, lastNode) where success is if the expand was successful and lastNode is the last node that was expanded.
419 * @param {Object} scope (optional) The scope of the callback function
421 expandPath: function(path, field, separator, callback, scope) {
423 current = me.getRootNode(),
429 field = field || me.getRootNode().idProperty;
430 separator = separator || '/';
432 if (Ext.isEmpty(path)) {
433 Ext.callback(callback, scope || me, [false, null]);
437 keys = path.split(separator);
438 if (current.get(field) != keys[1]) {
440 Ext.callback(callback, scope || me, [false, current]);
444 expander = function(){
445 if (++index === keys.length) {
446 Ext.callback(callback, scope || me, [true, current]);
449 var node = current.findChild(field, keys[index]);
451 Ext.callback(callback, scope || me, [false, current]);
455 current.expand(false, expander);
457 current.expand(false, expander);
460 <span id='Ext-tree-Panel-method-selectPath'> /**
461 </span> * Expand the tree to the path of a particular node, then selecti t.
462 * @param {String} path The path to select. The path should include a leading separator.
463 * @param {String} field (optional) The field to get the data from. Defaults to the model idProperty.
464 * @param {String} separator (optional) A separator to use. Defaults to <tt>'/'</tt>.
465 * @param {Function} callback (optional) A function to execute when the select finishes. The callback will be called with
466 * (bSuccess, oLastNode) where bSuccess is if the select was successful and oLastNode is the last node that was expanded.
467 * @param {Object} scope (optional) The scope of the callback function
469 selectPath: function(path, field, separator, callback, scope) {
474 field = field || me.getRootNode().idProperty;
475 separator = separator || '/';
477 keys = path.split(separator);
480 me.expandPath(keys.join('/'), field, separator, function(success, node){
481 var doSuccess = false;
482 if (success && node) {
483 node = node.findChild(field, last);
485 me.getSelectionModel().select(node);
486 Ext.callback(callback, scope || me, [true, node]);
489 } else if (node === me.getRootNode()) {
492 Ext.callback(callback, scope || me, [doSuccess, node]);