X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..HEAD:/src/tree/Panel.js diff --git a/src/tree/Panel.js b/src/tree/Panel.js index 9d6361f4..5d5c934c 100644 --- a/src/tree/Panel.js +++ b/src/tree/Panel.js @@ -15,17 +15,14 @@ If you are unsure which license is appropriate for your use, please contact the /** * The TreePanel provides tree-structured UI representation of tree-structured data. * A TreePanel must be bound to a {@link Ext.data.TreeStore}. TreePanel's support - * multiple columns through the {@link #columns} configuration. - * - * Simple TreePanel using inline data. + * multiple columns through the {@link #columns} configuration. * - * {@img Ext.tree.Panel/Ext.tree.Panel1.png Ext.tree.Panel component} - * - * Code: + * Simple TreePanel using inline data: * + * @example * var store = Ext.create('Ext.data.TreeStore', { * root: { - * expanded: true, + * expanded: true, * children: [ * { text: "detention", leaf: true }, * { text: "homework", expanded: true, children: [ @@ -35,16 +32,19 @@ If you are unsure which license is appropriate for your use, please contact the * { text: "buy lottery tickets", leaf: true } * ] * } - * }); + * }); * * Ext.create('Ext.tree.Panel', { * title: 'Simple Tree', * width: 200, * height: 150, * store: store, - * rootVisible: false, + * rootVisible: false, * renderTo: Ext.getBody() * }); + * + * For the tree node config options (like `text`, `leaf`, `expanded`), see the documentation of + * {@link Ext.data.NodeInterface NodeInterface} config options. */ Ext.define('Ext.tree.Panel', { extend: 'Ext.panel.Table', @@ -53,46 +53,46 @@ Ext.define('Ext.tree.Panel', { requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'], viewType: 'treeview', selType: 'treemodel', - + treeCls: Ext.baseCSSPrefix + 'tree-panel', deferRowRender: false, /** - * @cfg {Boolean} lines False to disable tree lines. Defaults to true. + * @cfg {Boolean} lines False to disable tree lines. */ lines: true, - + /** - * @cfg {Boolean} useArrows True to use Vista-style arrows in the tree. Defaults to false. + * @cfg {Boolean} useArrows True to use Vista-style arrows in the tree. */ useArrows: false, - + /** - * @cfg {Boolean} singleExpand True if only 1 node per branch may be expanded. Defaults to false. + * @cfg {Boolean} singleExpand True if only 1 node per branch may be expanded. */ singleExpand: false, - + ddConfig: { enableDrag: true, enableDrop: true }, - - /** + + /** * @cfg {Boolean} animate True to enable animated expand/collapse. Defaults to the value of {@link Ext#enableFx}. */ - - /** - * @cfg {Boolean} rootVisible False to hide the root node. Defaults to true. + + /** + * @cfg {Boolean} rootVisible False to hide the root node. */ rootVisible: true, - - /** - * @cfg {Boolean} displayField The field inside the model that will be used as the node's text. Defaults to 'text'. - */ + + /** + * @cfg {Boolean} displayField The field inside the model that will be used as the node's text. + */ displayField: 'text', - /** + /** * @cfg {Ext.data.Model/Ext.data.NodeInterface/Object} root * Allows you to not specify a store on this TreePanel. This is useful for creating a simple tree with preloaded * data without having to specify a TreeStore and Model. A store and model will be created and root will be passed @@ -112,7 +112,7 @@ Ext.define('Ext.tree.Panel', { * }); */ root: null, - + // Required for the Lockable Mixin. These are the configurations which will be copied to the // normal and locked sub tablepanels normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'], @@ -121,11 +121,11 @@ Ext.define('Ext.tree.Panel', { /** * @cfg {Boolean} hideHeaders True to hide the headers. Defaults to `undefined`. */ - + /** * @cfg {Boolean} folderSort True to automatically prepend a leaf sorter to the store. Defaults to `undefined`. - */ - + */ + constructor: function(config) { config = config || {}; if (config.animate === undefined) { @@ -133,10 +133,10 @@ Ext.define('Ext.tree.Panel', { } this.enableAnimations = config.animate; delete config.animate; - + this.callParent([config]); }, - + initComponent: function() { var me = this, cls = [me.treeCls]; @@ -145,13 +145,13 @@ Ext.define('Ext.tree.Panel', { cls.push(Ext.baseCSSPrefix + 'tree-arrows'); me.lines = false; } - + if (me.lines) { cls.push(Ext.baseCSSPrefix + 'tree-lines'); } else if (!me.useArrows) { cls.push(Ext.baseCSSPrefix + 'tree-no-lines'); } - + if (Ext.isString(me.store)) { me.store = Ext.StoreMgr.lookup(me.store); } else if (!me.store || Ext.isObject(me.store) && !me.store.isStore) { @@ -167,14 +167,14 @@ Ext.define('Ext.tree.Panel', { if (me.folderSort !== undefined) { me.store.folderSort = me.folderSort; me.store.sort(); - } + } } - + // I'm not sure if we want to this. It might be confusing // if (me.initialConfig.rootVisible === undefined && !me.getRootNode()) { // me.rootVisible = false; // } - + me.viewConfig = Ext.applyIf(me.viewConfig || {}, { rootVisible: me.rootVisible, animate: me.enableAnimations, @@ -182,141 +182,101 @@ Ext.define('Ext.tree.Panel', { node: me.store.getRootNode(), hideHeaders: me.hideHeaders }); - + me.mon(me.store, { scope: me, rootchange: me.onRootChange, clear: me.onClear }); - + me.relayEvents(me.store, [ /** * @event beforeload - * Event description - * @param {Ext.data.Store} store This Store - * @param {Ext.data.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to load the Store + * @alias Ext.data.Store#beforeload */ 'beforeload', /** * @event load - * Fires whenever the store reads data from a remote data source. - * @param {Ext.data.store} this - * @param {Array} records An array of records - * @param {Boolean} successful True if the operation was successful. + * @alias Ext.data.Store#load */ - 'load' + 'load' ]); - + me.store.on({ /** * @event itemappend - * Fires when a new child node is appended to a node in the tree. - * @param {Tree} tree The owner tree - * @param {Node} parent The parent node - * @param {Node} node The newly appended node - * @param {Number} index The index of the newly appended node + * @alias Ext.data.TreeStore#append */ append: me.createRelayer('itemappend'), - + /** * @event itemremove - * Fires when a child node is removed from a node in the tree - * @param {Tree} tree The owner tree - * @param {Node} parent The parent node - * @param {Node} node The child node removed + * @alias Ext.data.TreeStore#remove */ remove: me.createRelayer('itemremove'), - + /** * @event itemmove - * Fires when a node is moved to a new location in the tree - * @param {Tree} tree The owner tree - * @param {Node} node The node moved - * @param {Node} oldParent The old parent of this node - * @param {Node} newParent The new parent of this node - * @param {Number} index The index it was moved to + * @alias Ext.data.TreeStore#move */ move: me.createRelayer('itemmove'), - + /** * @event iteminsert - * Fires when a new child node is inserted in a node in tree - * @param {Tree} tree The owner tree - * @param {Node} parent The parent node - * @param {Node} node The child node inserted - * @param {Node} refNode The child node the node was inserted before + * @alias Ext.data.TreeStore#insert */ insert: me.createRelayer('iteminsert'), - + /** * @event beforeitemappend - * Fires before a new child is appended to a node in this tree, return false to cancel the append. - * @param {Tree} tree The owner tree - * @param {Node} parent The parent node - * @param {Node} node The child node to be appended + * @alias Ext.data.TreeStore#beforeappend */ beforeappend: me.createRelayer('beforeitemappend'), - + /** * @event beforeitemremove - * Fires before a child is removed from a node in this tree, return false to cancel the remove. - * @param {Tree} tree The owner tree - * @param {Node} parent The parent node - * @param {Node} node The child node to be removed + * @alias Ext.data.TreeStore#beforeremove */ beforeremove: me.createRelayer('beforeitemremove'), - + /** * @event beforeitemmove - * Fires before a node is moved to a new location in the tree. Return false to cancel the move. - * @param {Tree} tree The owner tree - * @param {Node} node The node being moved - * @param {Node} oldParent The parent of the node - * @param {Node} newParent The new parent the node is moving to - * @param {Number} index The index it is being moved to + * @alias Ext.data.TreeStore#beforemove */ beforemove: me.createRelayer('beforeitemmove'), - + /** * @event beforeiteminsert - * Fires before a new child is inserted in a node in this tree, return false to cancel the insert. - * @param {Tree} tree The owner tree - * @param {Node} parent The parent node - * @param {Node} node The child node to be inserted - * @param {Node} refNode The child node the node is being inserted before + * @alias Ext.data.TreeStore#beforeinsert */ beforeinsert: me.createRelayer('beforeiteminsert'), - + /** * @event itemexpand - * Fires when a node is expanded. - * @param {Node} this The expanding node + * @alias Ext.data.TreeStore#expand */ expand: me.createRelayer('itemexpand'), - + /** * @event itemcollapse - * Fires when a node is collapsed. - * @param {Node} this The collapsing node + * @alias Ext.data.TreeStore#collapse */ collapse: me.createRelayer('itemcollapse'), - + /** * @event beforeitemexpand - * Fires before a node is expanded. - * @param {Node} this The expanding node + * @alias Ext.data.TreeStore#beforeexpand */ beforeexpand: me.createRelayer('beforeitemexpand'), - + /** * @event beforeitemcollapse - * Fires before a node is collapsed. - * @param {Node} this The collapsing node + * @alias Ext.data.TreeStore#beforecollapse */ beforecollapse: me.createRelayer('beforeitemcollapse') }); - + // If the user specifies the headers collection manually then dont inject our own if (!me.columns) { if (me.initialConfig.hideHeaders === undefined) { @@ -326,16 +286,16 @@ Ext.define('Ext.tree.Panel', { xtype : 'treecolumn', text : 'Name', flex : 1, - dataIndex: me.displayField + dataIndex: me.displayField }]; } - + if (me.cls) { cls.push(me.cls); } me.cls = cls.join(' '); me.callParent(); - + me.relayEvents(me.getView(), [ /** * @event checkchange @@ -345,7 +305,7 @@ Ext.define('Ext.tree.Panel', { */ 'checkchange' ]); - + // If the root is not visible and there is no rootnode defined, then just lets load the store if (!me.getView().rootVisible && !me.getRootNode()) { me.setRootNode({ @@ -353,44 +313,61 @@ Ext.define('Ext.tree.Panel', { }); } }, - + onClear: function(){ this.view.onClear(); }, - + + /** + * Sets root node of this tree. + * @param {Ext.data.Model/Ext.data.NodeInterface/Object} root + * @return {Ext.data.NodeInterface} The new root + */ setRootNode: function() { return this.store.setRootNode.apply(this.store, arguments); }, - + + /** + * Returns the root node for this tree. + * @return {Ext.data.NodeInterface} + */ getRootNode: function() { return this.store.getRootNode(); }, - + onRootChange: function(root) { this.view.setRootNode(root); }, /** * Retrieve an array of checked records. - * @return {Array} An array containing the checked records + * @return {Ext.data.Model[]} An array containing the checked records */ getChecked: function() { return this.getView().getChecked(); }, - + isItemChecked: function(rec) { return rec.get('checked'); }, - + /** * Expand all nodes * @param {Function} callback (optional) A function to execute when the expand finishes. * @param {Object} scope (optional) The scope of the callback function */ expandAll : function(callback, scope) { - var root = this.getRootNode(); + var root = this.getRootNode(), + animate = this.enableAnimations, + view = this.getView(); if (root) { + if (!animate) { + view.beginBulkUpdate(); + } root.expand(true, callback, scope); + if (!animate) { + view.endBulkUpdate(); + } } }, @@ -400,14 +377,22 @@ Ext.define('Ext.tree.Panel', { * @param {Object} scope (optional) The scope of the callback function */ collapseAll : function(callback, scope) { - var root = this.getRootNode(); + var root = this.getRootNode(), + animate = this.enableAnimations, + view = this.getView(); + if (root) { - if (this.getView().rootVisible) { - root.collapse(true, callback, scope); + if (!animate) { + view.beginBulkUpdate(); } - else { + if (view.rootVisible) { + root.collapse(true, callback, scope); + } else { root.collapseChildren(true, callback, scope); } + if (!animate) { + view.endBulkUpdate(); + } } }, @@ -427,22 +412,22 @@ Ext.define('Ext.tree.Panel', { view = me.getView(), keys, expander; - + field = field || me.getRootNode().idProperty; separator = separator || '/'; - + if (Ext.isEmpty(path)) { Ext.callback(callback, scope || me, [false, null]); return; } - + keys = path.split(separator); if (current.get(field) != keys[1]) { // invalid root Ext.callback(callback, scope || me, [false, current]); return; } - + expander = function(){ if (++index === keys.length) { Ext.callback(callback, scope || me, [true, current]); @@ -458,9 +443,9 @@ Ext.define('Ext.tree.Panel', { }; current.expand(false, expander); }, - + /** - * Expand the tree to the path of a particular node, then selecti t. + * Expand the tree to the path of a particular node, then select it. * @param {String} path The path to select. The path should include a leading separator. * @param {String} field (optional) The field to get the data from. Defaults to the model idProperty. * @param {String} separator (optional) A separator to use. Defaults to `'/'`. @@ -472,13 +457,13 @@ Ext.define('Ext.tree.Panel', { var me = this, keys, last; - + field = field || me.getRootNode().idProperty; separator = separator || '/'; - + keys = path.split(separator); last = keys.pop(); - + me.expandPath(keys.join(separator), field, separator, function(success, node){ var doSuccess = false; if (success && node) {