| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 | <!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">/* * Note that this control will most likely remain as an example, and not as a core Ext form * control.  However, the API will be changing in a future release and so should not yet be * treated as a final, stable API at this time. */<span id='Ext-ux-form-ItemSelector'>/**</span> * A control that allows selection of between two Ext.ux.form.MultiSelect controls. */Ext.define('Ext.ux.form.ItemSelector', {    extend: 'Ext.ux.form.MultiSelect',    alias: ['widget.itemselectorfield', 'widget.itemselector'],    alternateClassName: ['Ext.ux.ItemSelector'],    requires: [        'Ext.button.Button',        'Ext.ux.form.MultiSelect'    ],<span id='Ext-ux-form-ItemSelector-cfg-hideNavIcons'>    /**</span>     * @cfg {Boolean} [hideNavIcons=false] True to hide the navigation icons     */    hideNavIcons:false,<span id='Ext-ux-form-ItemSelector-cfg-buttons'>    /**</span>     * @cfg {Array} buttons Defines the set of buttons that should be displayed in between the ItemSelector     * fields. Defaults to <tt>['top', 'up', 'add', 'remove', 'down', 'bottom']</tt>. These names are used     * to build the button CSS class names, and to look up the button text labels in {@link #buttonsText}.     * This can be overridden with a custom Array to change which buttons are displayed or their order.     */    buttons: ['top', 'up', 'add', 'remove', 'down', 'bottom'],<span id='Ext-ux-form-ItemSelector-cfg-buttonsText'>    /**</span>     * @cfg {Object} buttonsText The tooltips for the {@link #buttons}.     * Labels for buttons.     */    buttonsText: {        top: "Move to Top",        up: "Move Up",        add: "Add to Selected",        remove: "Remove from Selected",        down: "Move Down",        bottom: "Move to Bottom"    },    initComponent: function() {        var me = this;        me.ddGroup = me.id + '-dd';        me.callParent();        // bindStore must be called after the fromField has been created because        // it copies records from our configured Store into the fromField's Store        me.bindStore(me.store);    },    createList: function(title){        var me = this;        return Ext.create('Ext.ux.form.MultiSelect', {            submitValue: false,            flex: 1,            dragGroup: me.ddGroup,            dropGroup: me.ddGroup,            title: title,            store: {                model: me.store.model,                data: []            },            displayField: me.displayField,            disabled: me.disabled,            listeners: {                boundList: {                    scope: me,                    itemdblclick: me.onItemDblClick,                    drop: me.syncValue                }            }        });    },    setupItems: function() {        var me = this;        me.fromField = me.createList(me.fromTitle);        me.toField = me.createList(me.toTitle);        return {            border: false,            layout: {                type: 'hbox',                align: 'stretch'            },            items: [                me.fromField,                {                    xtype: 'container',                    margins: '0 4',                    width: 22,                    layout: {                        type: 'vbox',                        pack: 'center'                    },                    items: me.createButtons()                },                me.toField            ]        };    },    createButtons: function(){        var me = this,            buttons = [];        if (!me.hideNavIcons) {            Ext.Array.forEach(me.buttons, function(name) {                buttons.push({                    xtype: 'button',                    tooltip: me.buttonsText[name],                    handler: me['on' + Ext.String.capitalize(name) + 'BtnClick'],                    cls: Ext.baseCSSPrefix + 'form-itemselector-btn',                    iconCls: Ext.baseCSSPrefix + 'form-itemselector-' + name,                    navBtn: true,                    scope: me,                    margin: '4 0 0 0'                });            });        }        return buttons;    },<span id='Ext-ux-form-ItemSelector-method-getSelections'>    /**</span>     * Get the selected records from the specified list.     *      * Records will be returned *in store order*, not in order of selection.     * @param {Ext.view.BoundList} list The list to read selections from.     * @return {Ext.data.Model[]} The selected records in store order.     *      */    getSelections: function(list) {        var store = list.getStore();        return Ext.Array.sort(list.getSelectionModel().getSelection(), function(a, b) {            a = store.indexOf(a);            b = store.indexOf(b);            if (a < b) {                return -1;            } else if (a > b) {                return 1;            }            return 0;        });    },    onTopBtnClick : function() {        var list = this.toField.boundList,            store = list.getStore(),            selected = this.getSelections(list);        store.suspendEvents();        store.remove(selected, true);        store.insert(0, selected);        store.resumeEvents();        list.refresh();        this.syncValue();         list.getSelectionModel().select(selected);    },    onBottomBtnClick : function() {        var list = this.toField.boundList,            store = list.getStore(),            selected = this.getSelections(list);        store.suspendEvents();        store.remove(selected, true);        store.add(selected);        store.resumeEvents();        list.refresh();        this.syncValue();        list.getSelectionModel().select(selected);    },    onUpBtnClick : function() {        var list = this.toField.boundList,            store = list.getStore(),            selected = this.getSelections(list),            rec,            i = 0,            len = selected.length,            index = 0;        // Move each selection up by one place if possible        store.suspendEvents();        for (; i < len; ++i, index++) {            rec = selected[i];            index = Math.max(index, store.indexOf(rec) - 1);            store.remove(rec, true);            store.insert(index, rec);        }        store.resumeEvents();        list.refresh();        this.syncValue();        list.getSelectionModel().select(selected);    },    onDownBtnClick : function() {        var list = this.toField.boundList,            store = list.getStore(),            selected = this.getSelections(list),            rec,            i = selected.length - 1,            index = store.getCount() - 1;        // Move each selection down by one place if possible        store.suspendEvents();        for (; i > -1; --i, index--) {            rec = selected[i];            index = Math.min(index, store.indexOf(rec) + 1);            store.remove(rec, true);            store.insert(index, rec);        }        store.resumeEvents();        list.refresh();        this.syncValue();        list.getSelectionModel().select(selected);    },    onAddBtnClick : function() {        var me = this,            selected = me.getSelections(me.fromField.boundList);        me.moveRec(true, selected);        me.toField.boundList.getSelectionModel().select(selected);    },    onRemoveBtnClick : function() {        var me = this,            selected = me.getSelections(me.toField.boundList);        me.moveRec(false, selected);        me.fromField.boundList.getSelectionModel().select(selected);    },    moveRec: function(add, recs) {        var me = this,            fromField = me.fromField,            toField   = me.toField,            fromStore = add ? fromField.store : toField.store,            toStore   = add ? toField.store   : fromField.store;        fromStore.suspendEvents();        toStore.suspendEvents();        fromStore.remove(recs);        toStore.add(recs);        fromStore.resumeEvents();        toStore.resumeEvents();        fromField.boundList.refresh();        toField.boundList.refresh();        me.syncValue();    },    // Synchronizes the submit value with the current state of the toStore    syncValue: function() {        var me = this;         me.mixins.field.setValue.call(me, me.setupValue(me.toField.store.getRange()));    },    onItemDblClick: function(view, rec) {        this.moveRec(view === this.fromField.boundList, rec);    },    setValue: function(value) {        var me = this,            fromField = me.fromField,            toField = me.toField,            fromStore = fromField.store,            toStore = toField.store,            selected;        // Wait for from store to be loaded        if (!me.fromStorePopulated) {            me.fromField.store.on({                load: Ext.Function.bind(me.setValue, me, [value]),                single: true            });            return;        }        value = me.setupValue(value);        me.mixins.field.setValue.call(me, value);        selected = me.getRecordsForValue(value);        // Clear both left and right Stores.        // Both stores must not fire events during this process.        fromStore.suspendEvents();        toStore.suspendEvents();        fromStore.removeAll();        toStore.removeAll();        // Reset fromStore        me.populateFromStore(me.store);        // Copy selection across to toStore        Ext.Array.forEach(selected, function(rec){            // In the from store, move it over            if (fromStore.indexOf(rec) > -1) {                fromStore.remove(rec);            }            toStore.add(rec);        });        // Stores may now fire events        fromStore.resumeEvents();        toStore.resumeEvents();        // Refresh both sides and then update the app layout        Ext.suspendLayouts();        fromField.boundList.refresh();        toField.boundList.refresh();        Ext.resumeLayouts(true);            },    onBindStore: function(store, initial) {        var me = this;        if (me.fromField) {            me.fromField.store.removeAll()            me.toField.store.removeAll();            // Add everything to the from field as soon as the Store is loaded            if (store.getCount()) {                me.populateFromStore(store);            } else {                me.store.on('load', me.populateFromStore, me);            }        }    },    populateFromStore: function(store) {        var fromStore = this.fromField.store;        // Flag set when the fromStore has been loaded        this.fromStorePopulated = true;        fromStore.add(store.getRange());        // setValue waits for the from Store to be loaded        fromStore.fireEvent('load', fromStore);    },    onEnable: function(){        var me = this;        me.callParent();        me.fromField.enable();        me.toField.enable();        Ext.Array.forEach(me.query('[navBtn]'), function(btn){            btn.enable();        });    },    onDisable: function(){        var me = this;        me.callParent();        me.fromField.disable();        me.toField.disable();        Ext.Array.forEach(me.query('[navBtn]'), function(btn){            btn.disable();        });    },    onDestroy: function(){        this.bindStore(null);        this.callParent();    }});</pre></body></html>
 |