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