| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>  <style type="text/css">    .highlight { display: block; background-color: #ddd; }  </style>  <script type="text/javascript">    function highlight() {      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";    }  </script></head><body onload="prettyPrint(); highlight();">  <pre class="prettyprint lang-js"><span id='Ext-tree-Panel'>/**</span> * 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: * *     @example *     var store = Ext.create('Ext.data.TreeStore', { *         root: { *             expanded: true, *             children: [ *                 { text: "detention", leaf: true }, *                 { text: "homework", expanded: true, children: [ *                     { text: "book report", leaf: true }, *                     { text: "alegrbra", leaf: true} *                 ] }, *                 { text: "buy lottery tickets", leaf: true } *             ] *         } *     }); * *     Ext.create('Ext.tree.Panel', { *         title: 'Simple Tree', *         width: 200, *         height: 150, *         store: store, *         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',    alias: 'widget.treepanel',    alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],    requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column', 'Ext.data.TreeStore'],    viewType: 'treeview',    selType: 'treemodel',    treeCls: Ext.baseCSSPrefix + 'tree-panel',    deferRowRender: false,<span id='Ext-tree-Panel-cfg-rowLines'>    /**</span>     * @cfg {Boolean} rowLines     * False so that rows are not separated by lines.     */    rowLines: false,<span id='Ext-tree-Panel-cfg-lines'>    /**</span>     * @cfg {Boolean} lines     * False to disable tree lines.     */    lines: true,<span id='Ext-tree-Panel-cfg-useArrows'>    /**</span>     * @cfg {Boolean} useArrows     * True to use Vista-style arrows in the tree.     */    useArrows: false,<span id='Ext-tree-Panel-cfg-singleExpand'>    /**</span>     * @cfg {Boolean} singleExpand     * True if only 1 node per branch may be expanded.     */    singleExpand: false,    ddConfig: {        enableDrag: true,        enableDrop: true    },<span id='Ext-tree-Panel-cfg-animate'>    /**</span>     * @cfg {Boolean} animate     * True to enable animated expand/collapse. Defaults to the value of {@link Ext#enableFx}.     */<span id='Ext-tree-Panel-cfg-rootVisible'>    /**</span>     * @cfg {Boolean} rootVisible     * False to hide the root node.     */    rootVisible: true,<span id='Ext-tree-Panel-cfg-displayField'>    /**</span>     * @cfg {String} displayField     * The field inside the model that will be used as the node's text.     */    displayField: 'text',<span id='Ext-tree-Panel-cfg-root'>    /**</span>     * @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     * to that store. For example:     *     *     Ext.create('Ext.tree.Panel', {     *         title: 'Simple Tree',     *         root: {     *             text: "Root node",     *             expanded: true,     *             children: [     *                 { text: "Child 1", leaf: true },     *                 { text: "Child 2", leaf: true }     *             ]     *         },     *         renderTo: Ext.getBody()     *     });     */    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'],    lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],        isTree: true,<span id='Ext-tree-Panel-cfg-hideHeaders'>    /**</span>     * @cfg {Boolean} hideHeaders     * True to hide the headers.     */<span id='Ext-tree-Panel-cfg-folderSort'>    /**</span>     * @cfg {Boolean} folderSort     * True to automatically prepend a leaf sorter to the store.     */     <span id='Ext-tree-Panel-cfg-store'>    /**</span>     * @cfg {Ext.data.TreeStore} store (required)     * The {@link Ext.data.TreeStore Store} the tree should use as its data source.     */    constructor: function(config) {        config = config || {};        if (config.animate === undefined) {            config.animate = Ext.isDefined(this.animate) ? this.animate : Ext.enableFx;        }        this.enableAnimations = config.animate;        delete config.animate;        this.callParent([config]);    },    initComponent: function() {        var me = this,            cls = [me.treeCls],            view;        if (me.useArrows) {            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) {            me.store = new Ext.data.TreeStore(Ext.apply({}, me.store || {}, {                root: me.root,                fields: me.fields,                model: me.model,                folderSort: me.folderSort            }));        } else if (me.root) {            me.store = Ext.data.StoreManager.lookup(me.store);            me.store.setRootNode(me.root);            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.apply({}, me.viewConfig);        me.viewConfig = Ext.applyIf(me.viewConfig, {            rootVisible: me.rootVisible,            animate: me.enableAnimations,            singleExpand: me.singleExpand,            node: me.store.getRootNode(),            hideHeaders: me.hideHeaders        });        me.mon(me.store, {            scope: me,            rootchange: me.onRootChange,            clear: me.onClear        });        me.relayEvents(me.store, [<span id='Ext-tree-Panel-event-beforeload'>            /**</span>             * @event beforeload             * @inheritdoc Ext.data.TreeStore#beforeload             */            'beforeload',<span id='Ext-tree-Panel-event-load'>            /**</span>             * @event load             * @inheritdoc Ext.data.TreeStore#load             */            'load'        ]);        me.mon(me.store, {<span id='Ext-tree-Panel-event-itemappend'>            /**</span>             * @event itemappend             * @inheritdoc Ext.data.TreeStore#append             */            append: me.createRelayer('itemappend'),<span id='Ext-tree-Panel-event-itemremove'>            /**</span>             * @event itemremove             * @inheritdoc Ext.data.TreeStore#remove             */            remove: me.createRelayer('itemremove'),<span id='Ext-tree-Panel-event-itemmove'>            /**</span>             * @event itemmove             * @inheritdoc Ext.data.TreeStore#move             */            move: me.createRelayer('itemmove', [0, 4]),<span id='Ext-tree-Panel-event-iteminsert'>            /**</span>             * @event iteminsert             * @inheritdoc Ext.data.TreeStore#insert             */            insert: me.createRelayer('iteminsert'),<span id='Ext-tree-Panel-event-beforeitemappend'>            /**</span>             * @event beforeitemappend             * @inheritdoc Ext.data.TreeStore#beforeappend             */            beforeappend: me.createRelayer('beforeitemappend'),<span id='Ext-tree-Panel-event-beforeitemremove'>            /**</span>             * @event beforeitemremove             * @inheritdoc Ext.data.TreeStore#beforeremove             */            beforeremove: me.createRelayer('beforeitemremove'),<span id='Ext-tree-Panel-event-beforeitemmove'>            /**</span>             * @event beforeitemmove             * @inheritdoc Ext.data.TreeStore#beforemove             */            beforemove: me.createRelayer('beforeitemmove'),<span id='Ext-tree-Panel-event-beforeiteminsert'>            /**</span>             * @event beforeiteminsert             * @inheritdoc Ext.data.TreeStore#beforeinsert             */            beforeinsert: me.createRelayer('beforeiteminsert'),<span id='Ext-tree-Panel-event-itemexpand'>            /**</span>             * @event itemexpand             * @inheritdoc Ext.data.TreeStore#expand             */            expand: me.createRelayer('itemexpand', [0, 1]),<span id='Ext-tree-Panel-event-itemcollapse'>            /**</span>             * @event itemcollapse             * @inheritdoc Ext.data.TreeStore#collapse             */            collapse: me.createRelayer('itemcollapse', [0, 1]),<span id='Ext-tree-Panel-event-beforeitemexpand'>            /**</span>             * @event beforeitemexpand             * @inheritdoc Ext.data.TreeStore#beforeexpand             */            beforeexpand: me.createRelayer('beforeitemexpand', [0, 1]),<span id='Ext-tree-Panel-event-beforeitemcollapse'>            /**</span>             * @event beforeitemcollapse             * @inheritdoc Ext.data.TreeStore#beforecollapse             */            beforecollapse: me.createRelayer('beforeitemcollapse', [0, 1])        });        // If the user specifies the headers collection manually then dont inject our own        if (!me.columns) {            if (me.initialConfig.hideHeaders === undefined) {                me.hideHeaders = true;            }            me.addCls(Ext.baseCSSPrefix + 'autowidth-table');            me.columns = [{                xtype    : 'treecolumn',                text     : 'Name',                width    : Ext.isIE6 ? null : 10000,                dataIndex: me.displayField                     }];        }        if (me.cls) {            cls.push(me.cls);        }        me.cls = cls.join(' ');        me.callParent();                view = me.getView();        me.relayEvents(view, [<span id='Ext-tree-Panel-event-checkchange'>            /**</span>             * @event checkchange             * Fires when a node with a checkbox's checked property changes             * @param {Ext.data.NodeInterface} node The node who's checked property was changed             * @param {Boolean} checked The node's new checked state             */            'checkchange',<span id='Ext-tree-Panel-event-afteritemexpand'>            /**</span>             * @event afteritemexpand             * @inheritdoc Ext.tree.View#afteritemexpand             */            'afteritemexpand',<span id='Ext-tree-Panel-event-afteritemcollapse'>            /**</span>             * @event afteritemcollapse             * @inheritdoc Ext.tree.View#afteritemcollapse             */            'afteritemcollapse'        ]);        // If the root is not visible and there is no rootnode defined, then just lets load the store        if (!view.rootVisible && !me.getRootNode()) {            me.setRootNode({                expanded: true            });        }    },        onClear: function(){        this.view.onClear();    },<span id='Ext-tree-Panel-method-setRootNode'>    /**</span>     * 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);    },<span id='Ext-tree-Panel-method-getRootNode'>    /**</span>     * Returns the root node for this tree.     * @return {Ext.data.NodeInterface}     */    getRootNode: function() {        return this.store.getRootNode();    },    onRootChange: function(root) {        this.view.setRootNode(root);    },<span id='Ext-tree-Panel-method-getChecked'>    /**</span>     * Retrieve an array of checked records.     * @return {Ext.data.NodeInterface[]} An array containing the checked records     */    getChecked: function() {        return this.getView().getChecked();    },    isItemChecked: function(rec) {        return rec.get('checked');    },    <span id='Ext-tree-Panel-method-expandNode'>    /**</span>     * Expands a record that is loaded in the tree.     * @param {Ext.data.Model} record The record to expand     * @param {Boolean} [deep] True to expand nodes all the way down the tree hierarchy.     * @param {Function} [callback] The function to run after the expand is completed     * @param {Object} [scope] The scope of the callback function.     */    expandNode: function(record, deep, callback, scope) {        return this.getView().expand(record, deep, callback, scope || this);    },<span id='Ext-tree-Panel-method-collapseNode'>    /**</span>     * Collapses a record that is loaded in the tree.     * @param {Ext.data.Model} record The record to collapse     * @param {Boolean} [deep] True to collapse nodes all the way up the tree hierarchy.     * @param {Function} [callback] The function to run after the collapse is completed     * @param {Object} [scope] The scope of the callback function.     */    collapseNode: function(record, deep, callback, scope) {        return this.getView().collapse(record, deep, callback, scope || this);    },<span id='Ext-tree-Panel-method-expandAll'>    /**</span>     * Expand all nodes     * @param {Function} [callback] A function to execute when the expand finishes.     * @param {Object} [scope] The scope of the callback function     */    expandAll : function(callback, scope) {        var me = this,            root = me.getRootNode(),            animate = me.enableAnimations,            view = me.getView();        if (root) {            if (!animate) {                view.beginBulkUpdate();            }            root.expand(true, callback, scope || me);            if (!animate) {                view.endBulkUpdate();            }        }    },<span id='Ext-tree-Panel-method-collapseAll'>    /**</span>     * Collapse all nodes     * @param {Function} [callback] A function to execute when the collapse finishes.     * @param {Object} [scope] The scope of the callback function     */    collapseAll : function(callback, scope) {        var me = this,            root = me.getRootNode(),            animate = me.enableAnimations,            view = me.getView();        if (root) {            if (!animate) {                view.beginBulkUpdate();            }            scope = scope || me;            if (view.rootVisible) {                root.collapse(true, callback, scope);            } else {                root.collapseChildren(true, callback, scope);            }            if (!animate) {                view.endBulkUpdate();            }        }    },<span id='Ext-tree-Panel-method-expandPath'>    /**</span>     * Expand the tree to the path of a particular node.     * @param {String} path The path to expand. The path should include a leading separator.     * @param {String} [field] The field to get the data from. Defaults to the model idProperty.     * @param {String} [separator='/'] A separator to use.     * @param {Function} [callback] A function to execute when the expand finishes. The callback will be called with     * (success, lastNode) where success is if the expand was successful and lastNode is the last node that was expanded.     * @param {Object} [scope] The scope of the callback function     */    expandPath: function(path, field, separator, callback, scope) {        var me = this,            current = me.getRootNode(),            index = 1,            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]);                return;            }            var node = current.findChild(field, keys[index]);            if (!node) {                Ext.callback(callback, scope || me, [false, current]);                return;            }            current = node;            current.expand(false, expander);        };        current.expand(false, expander);    },<span id='Ext-tree-Panel-method-selectPath'>    /**</span>     * 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] The field to get the data from. Defaults to the model idProperty.     * @param {String} [separator='/'] A separator to use.     * @param {Function} [callback] A function to execute when the select finishes. The callback will be called with     * (bSuccess, oLastNode) where bSuccess is if the select was successful and oLastNode is the last node that was expanded.     * @param {Object} [scope] The scope of the callback function     */    selectPath: function(path, field, separator, callback, scope) {        var me = this,            root,            keys,            last;        field = field || me.getRootNode().idProperty;        separator = separator || '/';        keys = path.split(separator);        last = keys.pop();        if (keys.length > 1) {            me.expandPath(keys.join(separator), field, separator, function(success, node){                var lastNode = node;                if (success && node) {                    node = node.findChild(field, last);                    if (node) {                        me.getSelectionModel().select(node);                        Ext.callback(callback, scope || me, [true, node]);                        return;                    }                }                Ext.callback(callback, scope || me, [false, lastNode]);            }, me);        } else {            root = me.getRootNode();            if (root.getId() === last) {                me.getSelectionModel().select(root);                Ext.callback(callback, scope || me, [true, root]);            } else {                Ext.callback(callback, scope || me, [false, null]);            }        }    }});</pre></body></html>
 |