* @class Ext.ux.grid.menu.ListMenu * @extends Ext.menu.Menu * This is a supporting class for {@link Ext.ux.grid.filter.ListFilter}. * Although not listed as configuration options for this class, this class * also accepts all configuration options from {@link Ext.ux.grid.filter.ListFilter}. */ Ext.define('Ext.ux.grid.menu.ListMenu', { extend: 'Ext.menu.Menu', * @cfg {String} labelField * Defaults to 'text'. */ labelField : 'text', * @cfg {String} paramPrefix * Defaults to 'Loading...'. */ loadingText : 'Loading...', * @cfg {Boolean} loadOnShow * Defaults to true. */ loadOnShow : true, * @cfg {Boolean} single * Specify true to group all items in this list into a single-select * radio button group. Defaults to false. */ single : false, constructor : function (cfg) { this.selected = []; this.addEvents( * @event checkchange * Fires when there is a change in checked items from this list * @param {Object} item Ext.menu.CheckItem * @param {Object} checked The checked value that was set */ 'checkchange' ); this.callParent([cfg = cfg || {}]); if(!cfg.store && cfg.options){ var options = []; for(var i=0, len=cfg.options.length; i<len; i++){ var value = cfg.options[i]; switch(Ext.type(value)){ case 'array': options.push(value); break; case 'object': options.push([value.id, value[this.labelField]]); break; case 'string': options.push([value, value]); break; } } this.store = Ext.create('Ext.data.ArrayStore', { fields: ['id', this.labelField], data: options, listeners: { 'load': this.onLoad, scope: this } }); this.loaded = true; } else { this.add({text: this.loadingText, iconCls: 'loading-indicator'}); this.store.on('load', this.onLoad, this); } }, destroy : function () { if (this.store) { this.store.destroyStore(); } this.callParent(); }, * Lists will initially show a 'loading' item while the data is retrieved from the store. * In some cases the loaded data will result in a list that goes off the screen to the * right (as placement calculations were done with the loading item). This adapter will * allow show to be called with no arguments to show with the previous arguments and * thus recalculate the width and potentially hang the menu from the left. */ show : function () { var lastArgs = null; return function(){ if(arguments.length === 0){ this.callParent(lastArgs); } else { lastArgs = arguments; if (this.loadOnShow && !this.loaded) { this.store.load(); } this.callParent(arguments); } }; }(), onLoad : function (store, records) { var me = this, visible = me.isVisible(), gid, item, itemValue, i, len; me.hide(false); me.removeAll(true); gid = me.single ? Ext.id() : null; for (i = 0, len = records.length; i < len; i++) { itemValue = records[i].get('id'); item = Ext.create('Ext.menu.CheckItem', { text: records[i].get(me.labelField), group: gid, checked: Ext.Array.contains(me.selected, itemValue), hideOnClick: false, value: itemValue }); item.on('checkchange', me.checkChange, me); me.add(item); } me.loaded = true; if (visible) { me.show(); } me.fireEvent('load', me, records); }, * Get the selected items. * @return {Array} selected */ getSelected : function () { return this.selected; }, setSelected : function (value) { value = this.selected = [].concat(value); if (this.loaded) { this.items.each(function(item){ item.setChecked(false, true); for (var i = 0, len = value.length; i < len; i++) { if (item.value == value[i]) { item.setChecked(true, true); } } }, this); } }, * Handler for the 'checkchange' event from an check item in this menu * @param {Object} item Ext.menu.CheckItem * @param {Object} checked The checked value that was set */ checkChange : function (item, checked) { var value = []; this.items.each(function(item){ if (item.checked) { value.push(item.value); } },this); this.selected = value; this.fireEvent('checkchange', item, checked); } });