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> * The TreePanel provides tree-structured UI representation of tree-structured data.
20 * A TreePanel must be bound to a {@link Ext.data.TreeStore}. TreePanel's support
21 * multiple columns through the {@link #columns} configuration.
23 * Simple TreePanel using inline data.
25 * {@img Ext.tree.Panel/Ext.tree.Panel1.png Ext.tree.Panel component}
29 * var store = Ext.create('Ext.data.TreeStore', {
33 * { text: "detention", leaf: true },
34 * { text: "homework", expanded: true, children: [
35 * { text: "book report", leaf: true },
36 * { text: "alegrbra", leaf: true}
38 * { text: "buy lottery tickets", leaf: true }
43 * Ext.create('Ext.tree.Panel', {
44 * title: 'Simple Tree',
49 * renderTo: Ext.getBody()
52 Ext.define('Ext.tree.Panel', {
53 extend: 'Ext.panel.Table',
54 alias: 'widget.treepanel',
55 alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
56 requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'],
60 treeCls: Ext.baseCSSPrefix + 'tree-panel',
62 deferRowRender: false,
64 <span id='Ext-tree-Panel-cfg-lines'> /**
65 </span> * @cfg {Boolean} lines False to disable tree lines. Defaults to true.
69 <span id='Ext-tree-Panel-cfg-useArrows'> /**
70 </span> * @cfg {Boolean} useArrows True to use Vista-style arrows in the tree. Defaults to false.
74 <span id='Ext-tree-Panel-cfg-singleExpand'> /**
75 </span> * @cfg {Boolean} singleExpand True if only 1 node per branch may be expanded. Defaults to false.
84 <span id='Ext-tree-Panel-cfg-animate'> /**
85 </span> * @cfg {Boolean} animate True to enable animated expand/collapse. Defaults to the value of {@link Ext#enableFx}.
88 <span id='Ext-tree-Panel-cfg-rootVisible'> /**
89 </span> * @cfg {Boolean} rootVisible False to hide the root node. Defaults to true.
93 <span id='Ext-tree-Panel-cfg-displayField'> /**
94 </span> * @cfg {Boolean} displayField The field inside the model that will be used as the node's text. Defaults to 'text'.
98 <span id='Ext-tree-Panel-cfg-root'> /**
99 </span> * @cfg {Ext.data.Model/Ext.data.NodeInterface/Object} root
100 * Allows you to not specify a store on this TreePanel. This is useful for creating a simple tree with preloaded
101 * data without having to specify a TreeStore and Model. A store and model will be created and root will be passed
102 * to that store. For example:
104 * Ext.create('Ext.tree.Panel', {
105 * title: 'Simple Tree',
107 * text: "Root node",
110 * { text: "Child 1", leaf: true },
111 * { text: "Child 2", leaf: true }
114 * renderTo: Ext.getBody()
119 // Required for the Lockable Mixin. These are the configurations which will be copied to the
120 // normal and locked sub tablepanels
121 normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'],
122 lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],
124 <span id='Ext-tree-Panel-cfg-hideHeaders'> /**
125 </span> * @cfg {Boolean} hideHeaders True to hide the headers. Defaults to `undefined`.
128 <span id='Ext-tree-Panel-cfg-folderSort'> /**
129 </span> * @cfg {Boolean} folderSort True to automatically prepend a leaf sorter to the store. Defaults to `undefined`.
132 constructor: function(config) {
133 config = config || {};
134 if (config.animate === undefined) {
135 config.animate = Ext.enableFx;
137 this.enableAnimations = config.animate;
138 delete config.animate;
140 this.callParent([config]);
143 initComponent: function() {
148 cls.push(Ext.baseCSSPrefix + 'tree-arrows');
153 cls.push(Ext.baseCSSPrefix + 'tree-lines');
154 } else if (!me.useArrows) {
155 cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
158 if (Ext.isString(me.store)) {
159 me.store = Ext.StoreMgr.lookup(me.store);
160 } else if (!me.store || Ext.isObject(me.store) && !me.store.isStore) {
161 me.store = Ext.create('Ext.data.TreeStore', Ext.apply({}, me.store || {}, {
165 folderSort: me.folderSort
167 } else if (me.root) {
168 me.store = Ext.data.StoreManager.lookup(me.store);
169 me.store.setRootNode(me.root);
170 if (me.folderSort !== undefined) {
171 me.store.folderSort = me.folderSort;
176 // I'm not sure if we want to this. It might be confusing
177 // if (me.initialConfig.rootVisible === undefined && !me.getRootNode()) {
178 // me.rootVisible = false;
181 me.viewConfig = Ext.applyIf(me.viewConfig || {}, {
182 rootVisible: me.rootVisible,
183 animate: me.enableAnimations,
184 singleExpand: me.singleExpand,
185 node: me.store.getRootNode(),
186 hideHeaders: me.hideHeaders
191 rootchange: me.onRootChange,
195 me.relayEvents(me.store, [
196 <span id='Ext-tree-Panel-event-beforeload'> /**
197 </span> * @event beforeload
199 * @param {Ext.data.Store} store This Store
200 * @param {Ext.data.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to load the Store
204 <span id='Ext-tree-Panel-event-load'> /**
205 </span> * @event load
206 * Fires whenever the store reads data from a remote data source.
207 * @param {Ext.data.store} this
208 * @param {Array} records An array of records
209 * @param {Boolean} successful True if the operation was successful.
215 <span id='Ext-tree-Panel-event-itemappend'> /**
216 </span> * @event itemappend
217 * Fires when a new child node is appended to a node in the tree.
218 * @param {Tree} tree The owner tree
219 * @param {Node} parent The parent node
220 * @param {Node} node The newly appended node
221 * @param {Number} index The index of the newly appended node
223 append: me.createRelayer('itemappend'),
225 <span id='Ext-tree-Panel-event-itemremove'> /**
226 </span> * @event itemremove
227 * Fires when a child node is removed from a node in the tree
228 * @param {Tree} tree The owner tree
229 * @param {Node} parent The parent node
230 * @param {Node} node The child node removed
232 remove: me.createRelayer('itemremove'),
234 <span id='Ext-tree-Panel-event-itemmove'> /**
235 </span> * @event itemmove
236 * Fires when a node is moved to a new location in the tree
237 * @param {Tree} tree The owner tree
238 * @param {Node} node The node moved
239 * @param {Node} oldParent The old parent of this node
240 * @param {Node} newParent The new parent of this node
241 * @param {Number} index The index it was moved to
243 move: me.createRelayer('itemmove'),
245 <span id='Ext-tree-Panel-event-iteminsert'> /**
246 </span> * @event iteminsert
247 * Fires when a new child node is inserted in a node in tree
248 * @param {Tree} tree The owner tree
249 * @param {Node} parent The parent node
250 * @param {Node} node The child node inserted
251 * @param {Node} refNode The child node the node was inserted before
253 insert: me.createRelayer('iteminsert'),
255 <span id='Ext-tree-Panel-event-beforeitemappend'> /**
256 </span> * @event beforeitemappend
257 * Fires before a new child is appended to a node in this tree, return false to cancel the append.
258 * @param {Tree} tree The owner tree
259 * @param {Node} parent The parent node
260 * @param {Node} node The child node to be appended
262 beforeappend: me.createRelayer('beforeitemappend'),
264 <span id='Ext-tree-Panel-event-beforeitemremove'> /**
265 </span> * @event beforeitemremove
266 * Fires before a child is removed from a node in this tree, return false to cancel the remove.
267 * @param {Tree} tree The owner tree
268 * @param {Node} parent The parent node
269 * @param {Node} node The child node to be removed
271 beforeremove: me.createRelayer('beforeitemremove'),
273 <span id='Ext-tree-Panel-event-beforeitemmove'> /**
274 </span> * @event beforeitemmove
275 * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
276 * @param {Tree} tree The owner tree
277 * @param {Node} node The node being moved
278 * @param {Node} oldParent The parent of the node
279 * @param {Node} newParent The new parent the node is moving to
280 * @param {Number} index The index it is being moved to
282 beforemove: me.createRelayer('beforeitemmove'),
284 <span id='Ext-tree-Panel-event-beforeiteminsert'> /**
285 </span> * @event beforeiteminsert
286 * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
287 * @param {Tree} tree The owner tree
288 * @param {Node} parent The parent node
289 * @param {Node} node The child node to be inserted
290 * @param {Node} refNode The child node the node is being inserted before
292 beforeinsert: me.createRelayer('beforeiteminsert'),
294 <span id='Ext-tree-Panel-event-itemexpand'> /**
295 </span> * @event itemexpand
296 * Fires when a node is expanded.
297 * @param {Node} this The expanding node
299 expand: me.createRelayer('itemexpand'),
301 <span id='Ext-tree-Panel-event-itemcollapse'> /**
302 </span> * @event itemcollapse
303 * Fires when a node is collapsed.
304 * @param {Node} this The collapsing node
306 collapse: me.createRelayer('itemcollapse'),
308 <span id='Ext-tree-Panel-event-beforeitemexpand'> /**
309 </span> * @event beforeitemexpand
310 * Fires before a node is expanded.
311 * @param {Node} this The expanding node
313 beforeexpand: me.createRelayer('beforeitemexpand'),
315 <span id='Ext-tree-Panel-event-beforeitemcollapse'> /**
316 </span> * @event beforeitemcollapse
317 * Fires before a node is collapsed.
318 * @param {Node} this The collapsing node
320 beforecollapse: me.createRelayer('beforeitemcollapse')
323 // If the user specifies the headers collection manually then dont inject our own
325 if (me.initialConfig.hideHeaders === undefined) {
326 me.hideHeaders = true;
329 xtype : 'treecolumn',
332 dataIndex: me.displayField
339 me.cls = cls.join(' ');
342 me.relayEvents(me.getView(), [
343 <span id='Ext-tree-Panel-event-checkchange'> /**
344 </span> * @event checkchange
345 * Fires when a node with a checkbox's checked property changes
346 * @param {Ext.data.Model} node The node who's checked property was changed
347 * @param {Boolean} checked The node's new checked state
352 // If the root is not visible and there is no rootnode defined, then just lets load the store
353 if (!me.getView().rootVisible && !me.getRootNode()) {
364 setRootNode: function() {
365 return this.store.setRootNode.apply(this.store, arguments);
368 getRootNode: function() {
369 return this.store.getRootNode();
372 onRootChange: function(root) {
373 this.view.setRootNode(root);
376 <span id='Ext-tree-Panel-method-getChecked'> /**
377 </span> * Retrieve an array of checked records.
378 * @return {Array} An array containing the checked records
380 getChecked: function() {
381 return this.getView().getChecked();
384 isItemChecked: function(rec) {
385 return rec.get('checked');
388 <span id='Ext-tree-Panel-method-expandAll'> /**
389 </span> * Expand all nodes
390 * @param {Function} callback (optional) A function to execute when the expand finishes.
391 * @param {Object} scope (optional) The scope of the callback function
393 expandAll : function(callback, scope) {
394 var root = this.getRootNode();
396 root.expand(true, callback, scope);
400 <span id='Ext-tree-Panel-method-collapseAll'> /**
401 </span> * Collapse all nodes
402 * @param {Function} callback (optional) A function to execute when the collapse finishes.
403 * @param {Object} scope (optional) The scope of the callback function
405 collapseAll : function(callback, scope) {
406 var root = this.getRootNode();
408 if (this.getView().rootVisible) {
409 root.collapse(true, callback, scope);
412 root.collapseChildren(true, callback, scope);
417 <span id='Ext-tree-Panel-method-expandPath'> /**
418 </span> * Expand the tree to the path of a particular node.
419 * @param {String} path The path to expand. The path should include a leading separator.
420 * @param {String} field (optional) The field to get the data from. Defaults to the model idProperty.
421 * @param {String} separator (optional) A separator to use. Defaults to `'/'`.
422 * @param {Function} callback (optional) A function to execute when the expand finishes. The callback will be called with
423 * (success, lastNode) where success is if the expand was successful and lastNode is the last node that was expanded.
424 * @param {Object} scope (optional) The scope of the callback function
426 expandPath: function(path, field, separator, callback, scope) {
428 current = me.getRootNode(),
434 field = field || me.getRootNode().idProperty;
435 separator = separator || '/';
437 if (Ext.isEmpty(path)) {
438 Ext.callback(callback, scope || me, [false, null]);
442 keys = path.split(separator);
443 if (current.get(field) != keys[1]) {
445 Ext.callback(callback, scope || me, [false, current]);
449 expander = function(){
450 if (++index === keys.length) {
451 Ext.callback(callback, scope || me, [true, current]);
454 var node = current.findChild(field, keys[index]);
456 Ext.callback(callback, scope || me, [false, current]);
460 current.expand(false, expander);
462 current.expand(false, expander);
465 <span id='Ext-tree-Panel-method-selectPath'> /**
466 </span> * Expand the tree to the path of a particular node, then selecti t.
467 * @param {String} path The path to select. The path should include a leading separator.
468 * @param {String} field (optional) The field to get the data from. Defaults to the model idProperty.
469 * @param {String} separator (optional) A separator to use. Defaults to `'/'`.
470 * @param {Function} callback (optional) A function to execute when the select finishes. The callback will be called with
471 * (bSuccess, oLastNode) where bSuccess is if the select was successful and oLastNode is the last node that was expanded.
472 * @param {Object} scope (optional) The scope of the callback function
474 selectPath: function(path, field, separator, callback, scope) {
479 field = field || me.getRootNode().idProperty;
480 separator = separator || '/';
482 keys = path.split(separator);
485 me.expandPath(keys.join(separator), field, separator, function(success, node){
486 var doSuccess = false;
487 if (success && node) {
488 node = node.findChild(field, last);
490 me.getSelectionModel().select(node);
491 Ext.callback(callback, scope || me, [true, node]);
494 } else if (node === me.getRootNode()) {
497 Ext.callback(callback, scope || me, [doSuccess, node]);