Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / examples / ux / gridfilters / filter / DateFilter.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 /** \r
8  * @class Ext.ux.grid.filter.DateFilter\r
9  * @extends Ext.ux.grid.filter.Filter\r
10  * Filter by a configurable Ext.menu.DateMenu\r
11  * <p><b><u>Example Usage:</u></b></p>\r
12  * <pre><code>    \r
13 var filters = new Ext.ux.grid.GridFilters({\r
14     ...\r
15     filters: [{\r
16         // required configs\r
17         type: 'date',\r
18         dataIndex: 'dateAdded',\r
19         \r
20         // optional configs\r
21         dateFormat: 'm/d/Y',  // default\r
22         beforeText: 'Before', // default\r
23         afterText: 'After',   // default\r
24         onText: 'On',         // default\r
25         pickerOpts: {\r
26             // any DateMenu configs\r
27         },\r
28 \r
29         active: true // default is false\r
30     }]\r
31 });\r
32  * </code></pre>\r
33  */\r
34 Ext.ux.grid.filter.DateFilter = Ext.extend(Ext.ux.grid.filter.Filter, {\r
35     /**\r
36      * @cfg {String} afterText\r
37      * Defaults to 'After'.\r
38      */\r
39     afterText : 'After',\r
40     /**\r
41      * @cfg {String} beforeText\r
42      * Defaults to 'Before'.\r
43      */\r
44     beforeText : 'Before',\r
45     /**\r
46      * @cfg {Object} compareMap\r
47      * Map for assigning the comparison values used in serialization.\r
48      */\r
49     compareMap : {\r
50         before: 'lt',\r
51         after:  'gt',\r
52         on:     'eq'\r
53     },\r
54     /**\r
55      * @cfg {String} dateFormat\r
56      * The date format to return when using getValue.\r
57      * Defaults to 'm/d/Y'.\r
58      */\r
59     dateFormat : 'm/d/Y',\r
60 \r
61     /**\r
62      * @cfg {Date} maxDate\r
63      * Allowable date as passed to the Ext.DatePicker\r
64      * Defaults to undefined.\r
65      */\r
66     /**\r
67      * @cfg {Date} minDate\r
68      * Allowable date as passed to the Ext.DatePicker\r
69      * Defaults to undefined.\r
70      */\r
71     /**\r
72      * @cfg {Array} menuItems\r
73      * The items to be shown in this menu\r
74      * Defaults to:<pre>\r
75      * menuItems : ['before', 'after', '-', 'on'],\r
76      * </pre>\r
77      */\r
78     menuItems : ['before', 'after', '-', 'on'],\r
79 \r
80     /**\r
81      * @cfg {Object} menuItemCfgs\r
82      * Default configuration options for each menu item\r
83      */\r
84     menuItemCfgs : {\r
85         selectOnFocus: true,\r
86         width: 125\r
87     },\r
88 \r
89     /**\r
90      * @cfg {String} onText\r
91      * Defaults to 'On'.\r
92      */\r
93     onText : 'On',\r
94     \r
95     /**\r
96      * @cfg {Object} pickerOpts\r
97      * Configuration options for the date picker associated with each field.\r
98      */\r
99     pickerOpts : {},\r
100 \r
101     /**  \r
102      * @private\r
103      * Template method that is to initialize the filter and install required menu items.\r
104      */\r
105     init : function (config) {\r
106         var menuCfg, i, len, item, cfg, Cls;\r
107 \r
108         menuCfg = Ext.apply(this.pickerOpts, {\r
109             minDate: this.minDate, \r
110             maxDate: this.maxDate, \r
111             format:  this.dateFormat,\r
112             listeners: {\r
113                 scope: this,\r
114                 select: this.onMenuSelect\r
115             }\r
116         });\r
117 \r
118         this.fields = {};\r
119         for (i = 0, len = this.menuItems.length; i < len; i++) {\r
120             item = this.menuItems[i];\r
121             if (item !== '-') {\r
122                 cfg = {\r
123                     itemId: 'range-' + item,\r
124                     text: this[item + 'Text'],\r
125                     menu: new Ext.menu.DateMenu(\r
126                         Ext.apply(menuCfg, {\r
127                             itemId: item\r
128                         })\r
129                     ),\r
130                     listeners: {\r
131                         scope: this,\r
132                         checkchange: this.onCheckChange\r
133                     }\r
134                 };\r
135                 Cls = Ext.menu.CheckItem;\r
136                 item = this.fields[item] = new Cls(cfg);\r
137             }\r
138             //this.add(item);\r
139             this.menu.add(item);\r
140         }\r
141     },\r
142 \r
143     onCheckChange : function () {\r
144         this.setActive(this.isActivatable());\r
145         this.fireEvent('update', this);\r
146     },\r
147 \r
148     /**  \r
149      * @private\r
150      * Handler method called when there is a keyup event on an input\r
151      * item of this menu.\r
152      */\r
153     onInputKeyUp : function (field, e) {\r
154         var k = e.getKey();\r
155         if (k == e.RETURN && field.isValid()) {\r
156             e.stopEvent();\r
157             this.menu.hide(true);\r
158             return;\r
159         }\r
160     },\r
161 \r
162     /**\r
163      * Handler for when the menu for a field fires the 'select' event\r
164      * @param {Object} date\r
165      * @param {Object} menuItem\r
166      * @param {Object} value\r
167      * @param {Object} picker\r
168      */\r
169     onMenuSelect : function (menuItem, value, picker) {\r
170         var fields = this.fields,\r
171             field = this.fields[menuItem.itemId];\r
172         \r
173         field.setChecked(true);\r
174         \r
175         if (field == fields.on) {\r
176             fields.before.setChecked(false, true);\r
177             fields.after.setChecked(false, true);\r
178         } else {\r
179             fields.on.setChecked(false, true);\r
180             if (field == fields.after && fields.before.menu.picker.value < value) {\r
181                 fields.before.setChecked(false, true);\r
182             } else if (field == fields.before && fields.after.menu.picker.value > value) {\r
183                 fields.after.setChecked(false, true);\r
184             }\r
185         }\r
186         this.fireEvent('update', this);\r
187     },\r
188 \r
189     /**\r
190      * @private\r
191      * Template method that is to get and return the value of the filter.\r
192      * @return {String} The value of this filter\r
193      */\r
194     getValue : function () {\r
195         var key, result = {};\r
196         for (key in this.fields) {\r
197             if (this.fields[key].checked) {\r
198                 result[key] = this.fields[key].menu.picker.getValue();\r
199             }\r
200         }\r
201         return result;\r
202     },\r
203 \r
204     /**\r
205      * @private\r
206      * Template method that is to set the value of the filter.\r
207      * @param {Object} value The value to set the filter\r
208      * @param {Boolean} preserve true to preserve the checked status\r
209      * of the other fields.  Defaults to false, unchecking the\r
210      * other fields\r
211      */ \r
212     setValue : function (value, preserve) {\r
213         var key;\r
214         for (key in this.fields) {\r
215             if(value[key]){\r
216                 this.fields[key].menu.picker.setValue(value[key]);\r
217                 this.fields[key].setChecked(true);\r
218             } else if (!preserve) {\r
219                 this.fields[key].setChecked(false);\r
220             }\r
221         }\r
222         this.fireEvent('update', this);\r
223     },\r
224 \r
225     /**\r
226      * @private\r
227      * Template method that is to return <tt>true</tt> if the filter\r
228      * has enough configuration information to be activated.\r
229      * @return {Boolean}\r
230      */\r
231     isActivatable : function () {\r
232         var key;\r
233         for (key in this.fields) {\r
234             if (this.fields[key].checked) {\r
235                 return true;\r
236             }\r
237         }\r
238         return false;\r
239     },\r
240 \r
241     /**\r
242      * @private\r
243      * Template method that is to get and return serialized filter data for\r
244      * transmission to the server.\r
245      * @return {Object/Array} An object or collection of objects containing\r
246      * key value pairs representing the current configuration of the filter.\r
247      */\r
248     getSerialArgs : function () {\r
249         var args = [];\r
250         for (var key in this.fields) {\r
251             if(this.fields[key].checked){\r
252                 args.push({\r
253                     type: 'date',\r
254                     comparison: this.compareMap[key],\r
255                     value: this.getFieldValue(key).format(this.dateFormat)\r
256                 });\r
257             }\r
258         }\r
259         return args;\r
260     },\r
261 \r
262     /**\r
263      * Get and return the date menu picker value\r
264      * @param {String} item The field identifier ('before', 'after', 'on')\r
265      * @return {Date} Gets the current selected value of the date field\r
266      */\r
267     getFieldValue : function(item){\r
268         return this.fields[item].menu.picker.getValue();\r
269     },\r
270     \r
271     /**\r
272      * Gets the menu picker associated with the passed field\r
273      * @param {String} item The field identifier ('before', 'after', 'on')\r
274      * @return {Object} The menu picker\r
275      */\r
276     getPicker : function(item){\r
277         return this.fields[item].menu.picker;\r
278     },\r
279 \r
280     /**\r
281      * Template method that is to validate the provided Ext.data.Record\r
282      * against the filters configuration.\r
283      * @param {Ext.data.Record} record The record to validate\r
284      * @return {Boolean} true if the record is valid within the bounds\r
285      * of the filter, false otherwise.\r
286      */\r
287     validateRecord : function (record) {\r
288         var key,\r
289             pickerValue,\r
290             val = record.get(this.dataIndex);\r
291             \r
292         if(!Ext.isDate(val)){\r
293             return false;\r
294         }\r
295         val = val.clearTime(true).getTime();\r
296         \r
297         for (key in this.fields) {\r
298             if (this.fields[key].checked) {\r
299                 pickerValue = this.getFieldValue(key).clearTime(true).getTime();\r
300                 if (key == 'before' && pickerValue <= val) {\r
301                     return false;\r
302                 }\r
303                 if (key == 'after' && pickerValue >= val) {\r
304                     return false;\r
305                 }\r
306                 if (key == 'on' && pickerValue != val) {\r
307                     return false;\r
308                 }\r
309             }\r
310         }\r
311         return true;\r
312     }\r
313 });