Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / examples / ux / grid / menu / RangeMenu.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.RangeMenu
17  * @extends Ext.menu.Menu
18  * Custom implementation of {@link Ext.menu.Menu} that has preconfigured items for entering numeric
19  * range comparison values: less-than, greater-than, and equal-to. This is used internally
20  * by {@link Ext.ux.grid.filter.NumericFilter} to create its menu.
21  */
22 Ext.define('Ext.ux.grid.menu.RangeMenu', {
23     extend: 'Ext.menu.Menu',
24
25     /**
26      * @cfg {String} fieldCls
27      * The Class to use to construct each field item within this menu
28      * Defaults to:<pre>
29      * fieldCls : Ext.form.field.Number
30      * </pre>
31      */
32     fieldCls : 'Ext.form.field.Number',
33
34     /**
35      * @cfg {Object} fieldCfg
36      * The default configuration options for any field item unless superseded
37      * by the <code>{@link #fields}</code> configuration.
38      * Defaults to:<pre>
39      * fieldCfg : {}
40      * </pre>
41      * Example usage:
42      * <pre><code>
43 fieldCfg : {
44     width: 150,
45 },
46      * </code></pre>
47      */
48
49     /**
50      * @cfg {Object} fields
51      * The field items may be configured individually
52      * Defaults to <tt>undefined</tt>.
53      * Example usage:
54      * <pre><code>
55 fields : {
56     gt: { // override fieldCfg options
57         width: 200,
58         fieldCls: Ext.ux.form.CustomNumberField // to override default {@link #fieldCls}
59     }
60 },
61      * </code></pre>
62      */
63
64     /**
65      * @cfg {Object} iconCls
66      * The iconCls to be applied to each comparator field item.
67      * Defaults to:<pre>
68 iconCls : {
69     gt : 'ux-rangemenu-gt',
70     lt : 'ux-rangemenu-lt',
71     eq : 'ux-rangemenu-eq'
72 }
73      * </pre>
74      */
75     iconCls : {
76         gt : 'ux-rangemenu-gt',
77         lt : 'ux-rangemenu-lt',
78         eq : 'ux-rangemenu-eq'
79     },
80
81     /**
82      * @cfg {Object} fieldLabels
83      * Accessible label text for each comparator field item. Can be overridden by localization
84      * files. Defaults to:<pre>
85 fieldLabels : {
86      gt: 'Greater Than',
87      lt: 'Less Than',
88      eq: 'Equal To'
89 }</pre>
90      */
91     fieldLabels: {
92         gt: 'Greater Than',
93         lt: 'Less Than',
94         eq: 'Equal To'
95     },
96
97     /**
98      * @cfg {Object} menuItemCfgs
99      * Default configuration options for each menu item
100      * Defaults to:<pre>
101 menuItemCfgs : {
102     emptyText: 'Enter Filter Text...',
103     selectOnFocus: true,
104     width: 125
105 }
106      * </pre>
107      */
108     menuItemCfgs : {
109         emptyText: 'Enter Number...',
110         selectOnFocus: false,
111         width: 155
112     },
113
114     /**
115      * @cfg {Array} menuItems
116      * The items to be shown in this menu.  Items are added to the menu
117      * according to their position within this array. Defaults to:<pre>
118      * menuItems : ['lt','gt','-','eq']
119      * </pre>
120      */
121     menuItems : ['lt', 'gt', '-', 'eq'],
122
123
124     constructor : function (config) {
125         var me = this,
126             fields, fieldCfg, i, len, item, cfg, Cls;
127
128         me.callParent(arguments);
129
130         fields = me.fields = me.fields || {};
131         fieldCfg = me.fieldCfg = me.fieldCfg || {};
132         
133         me.addEvents(
134             /**
135              * @event update
136              * Fires when a filter configuration has changed
137              * @param {Ext.ux.grid.filter.Filter} this The filter object.
138              */
139             'update'
140         );
141       
142         me.updateTask = Ext.create('Ext.util.DelayedTask', me.fireUpdate, me);
143     
144         for (i = 0, len = me.menuItems.length; i < len; i++) {
145             item = me.menuItems[i];
146             if (item !== '-') {
147                 // defaults
148                 cfg = {
149                     itemId: 'range-' + item,
150                     enableKeyEvents: true,
151                     hideLabel: false,
152                     fieldLabel: me.iconTpl.apply({
153                         cls: me.iconCls[item] || 'no-icon',
154                         text: me.fieldLabels[item] || '',
155                         src: Ext.BLANK_IMAGE_URL
156                     }),
157                     labelSeparator: '',
158                     labelWidth: 29,
159                     listeners: {
160                         scope: me,
161                         change: me.onInputChange,
162                         keyup: me.onInputKeyUp,
163                         el: {
164                             click: function(e) {
165                                 e.stopPropagation();
166                             }
167                         }
168                     },
169                     activate: Ext.emptyFn,
170                     deactivate: Ext.emptyFn
171                 };
172                 Ext.apply(
173                     cfg,
174                     // custom configs
175                     Ext.applyIf(fields[item] || {}, fieldCfg[item]),
176                     // configurable defaults
177                     me.menuItemCfgs
178                 );
179                 Cls = cfg.fieldCls || me.fieldCls;
180                 item = fields[item] = Ext.create(Cls, cfg);
181             }
182             me.add(item);
183         }
184     },
185
186     /**
187      * @private
188      * called by this.updateTask
189      */
190     fireUpdate : function () {
191         this.fireEvent('update', this);
192     },
193     
194     /**
195      * Get and return the value of the filter.
196      * @return {String} The value of this filter
197      */
198     getValue : function () {
199         var result = {}, key, field;
200         for (key in this.fields) {
201             field = this.fields[key];
202             if (field.isValid() && field.getValue() !== null) {
203                 result[key] = field.getValue();
204             }
205         }
206         return result;
207     },
208   
209     /**
210      * Set the value of this menu and fires the 'update' event.
211      * @param {Object} data The data to assign to this menu
212      */ 
213     setValue : function (data) {
214         var key;
215         for (key in this.fields) {
216             this.fields[key].setValue(key in data ? data[key] : '');
217         }
218         this.fireEvent('update', this);
219     },
220
221     /**  
222      * @private
223      * Handler method called when there is a keyup event on an input
224      * item of this menu.
225      */
226     onInputKeyUp: function(field, e) {
227         if (e.getKey() === e.RETURN && field.isValid()) {
228             e.stopEvent();
229             this.hide();
230         }
231     },
232
233     /**
234      * @private
235      * Handler method called when the user changes the value of one of the input
236      * items in this menu.
237      */
238     onInputChange: function(field) {
239         var me = this,
240             fields = me.fields,
241             eq = fields.eq,
242             gt = fields.gt,
243             lt = fields.lt;
244
245         if (field == eq) {
246             if (gt) {
247                 gt.setValue(null);
248             }
249             if (lt) {
250                 lt.setValue(null);
251             }
252         }
253         else {
254             eq.setValue(null);
255         }
256
257         // restart the timer
258         this.updateTask.delay(this.updateBuffer);
259     }
260 }, function() {
261
262     /**
263      * @cfg {Ext.XTemplate} iconTpl
264      * A template for generating the label for each field in the menu
265      */
266     this.prototype.iconTpl = Ext.create('Ext.XTemplate',
267         '<img src="{src}" alt="{text}" class="' + Ext.baseCSSPrefix + 'menu-item-icon ux-rangemenu-icon {cls}" />'
268     );
269
270 });
271