Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / ux / grid / menu / ListMenu.js
1 /**
2  * @class Ext.ux.grid.menu.ListMenu
3  * @extends Ext.menu.Menu
4  * This is a supporting class for {@link Ext.ux.grid.filter.ListFilter}.
5  * Although not listed as configuration options for this class, this class
6  * also accepts all configuration options from {@link Ext.ux.grid.filter.ListFilter}.
7  */
8 Ext.define('Ext.ux.grid.menu.ListMenu', {
9     extend: 'Ext.menu.Menu',
10
11     /**
12      * @cfg {String} labelField
13      * Defaults to 'text'.
14      */
15     labelField :  'text',
16     /**
17      * @cfg {String} paramPrefix
18      * Defaults to 'Loading...'.
19      */
20     loadingText : 'Loading...',
21     /**
22      * @cfg {Boolean} loadOnShow
23      * Defaults to true.
24      */
25     loadOnShow : true,
26     /**
27      * @cfg {Boolean} single
28      * Specify true to group all items in this list into a single-select
29      * radio button group. Defaults to false.
30      */
31     single : false,
32
33     constructor : function (cfg) {
34         this.selected = [];
35         this.addEvents(
36             /**
37              * @event checkchange
38              * Fires when there is a change in checked items from this list
39              * @param {Object} item Ext.menu.CheckItem
40              * @param {Object} checked The checked value that was set
41              */
42             'checkchange'
43         );
44
45         this.callParent([cfg = cfg || {}]);
46
47         if(!cfg.store && cfg.options){
48             var options = [];
49             for(var i=0, len=cfg.options.length; i<len; i++){
50                 var value = cfg.options[i];
51                 switch(Ext.type(value)){
52                     case 'array':  options.push(value); break;
53                     case 'object': options.push([value.id, value[this.labelField]]); break;
54                     case 'string': options.push([value, value]); break;
55                 }
56             }
57
58             this.store = Ext.create('Ext.data.ArrayStore', {
59                 fields: ['id', this.labelField],
60                 data:   options,
61                 listeners: {
62                     'load': this.onLoad,
63                     scope:  this
64                 }
65             });
66             this.loaded = true;
67         } else {
68             this.add({text: this.loadingText, iconCls: 'loading-indicator'});
69             this.store.on('load', this.onLoad, this);
70         }
71     },
72
73     destroy : function () {
74         if (this.store) {
75             this.store.destroy();
76         }
77         this.callParent();
78     },
79
80     /**
81      * Lists will initially show a 'loading' item while the data is retrieved from the store.
82      * In some cases the loaded data will result in a list that goes off the screen to the
83      * right (as placement calculations were done with the loading item). This adapter will
84      * allow show to be called with no arguments to show with the previous arguments and
85      * thus recalculate the width and potentially hang the menu from the left.
86      */
87     show : function () {
88         var lastArgs = null;
89         return function(){
90             if(arguments.length === 0){
91                 this.callParent(lastArgs);
92             } else {
93                 lastArgs = arguments;
94                 if (this.loadOnShow && !this.loaded) {
95                     this.store.load();
96                 }
97                 this.callParent(arguments);
98             }
99         };
100     }(),
101
102     /** @private */
103     onLoad : function (store, records) {
104         var me = this,
105             visible = me.isVisible(),
106             gid, item, itemValue, i, len;
107
108         me.hide(false);
109
110         me.removeAll(true);
111
112         gid = me.single ? Ext.id() : null;
113         for (i = 0, len = records.length; i < len; i++) {
114             itemValue = records[i].get('id');
115             item = Ext.create('Ext.menu.CheckItem', {
116                 text: records[i].get(me.labelField),
117                 group: gid,
118                 checked: Ext.Array.contains(me.selected, itemValue),
119                 hideOnClick: false,
120                 value: itemValue
121             });
122
123             item.on('checkchange', me.checkChange, me);
124
125             me.add(item);
126         }
127
128         me.loaded = true;
129
130         if (visible) {
131             me.show();
132         }
133         me.fireEvent('load', me, records);
134     },
135
136     /**
137      * Get the selected items.
138      * @return {Array} selected
139      */
140     getSelected : function () {
141         return this.selected;
142     },
143
144     /** @private */
145     setSelected : function (value) {
146         value = this.selected = [].concat(value);
147
148         if (this.loaded) {
149             this.items.each(function(item){
150                 item.setChecked(false, true);
151                 for (var i = 0, len = value.length; i < len; i++) {
152                     if (item.value == value[i]) {
153                         item.setChecked(true, true);
154                     }
155                 }
156             }, this);
157         }
158     },
159
160     /**
161      * Handler for the 'checkchange' event from an check item in this menu
162      * @param {Object} item Ext.menu.CheckItem
163      * @param {Object} checked The checked value that was set
164      */
165     checkChange : function (item, checked) {
166         var value = [];
167         this.items.each(function(item){
168             if (item.checked) {
169                 value.push(item.value);
170             }
171         },this);
172         this.selected = value;
173
174         this.fireEvent('checkchange', item, checked);
175     }
176 });