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