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