source: trunk/web/addons/job_monarch/lib/extjs/examples/grid-filtering/grid/GridFilters.js @ 619

Last change on this file since 619 was 619, checked in by ramonb, 15 years ago

lib/:

  • added new AJAX dependancies: ExtJS, pChart, Lightbox2
File size: 9.5 KB
Line 
1/*
2 * Ext JS Library 2.2.1
3 * Copyright(c) 2006-2009, Ext JS, LLC.
4 * licensing@extjs.com
5 *
6 * http://extjs.com/license
7 */
8
9Ext.grid.GridFilters = function(config){               
10        this.filters = new Ext.util.MixedCollection();
11        this.filters.getKey = function(o) {return o ? o.dataIndex : null};
12       
13        for(var i=0, len=config.filters.length; i<len; i++) {
14                this.addFilter(config.filters[i]);
15  }
16 
17        this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);
18       
19        delete config.filters;
20        Ext.apply(this, config);
21};
22Ext.extend(Ext.grid.GridFilters, Ext.util.Observable, {
23        /**
24         * @cfg {Integer} updateBuffer
25         * Number of milisecond to defer store updates since the last filter change.
26         */
27        updateBuffer: 500,
28        /**
29         * @cfg {String} paramPrefix
30         * The url parameter prefix for the filters.
31         */
32        paramPrefix: 'filter',
33        /**
34         * @cfg {String} fitlerCls
35         * The css class to be applied to column headers that active filters. Defaults to 'ux-filterd-column'
36         */
37        filterCls: 'ux-filtered-column',
38        /**
39         * @cfg {Boolean} local
40         * True to use Ext.data.Store filter functions instead of server side filtering.
41         */
42        local: false,
43        /**
44         * @cfg {Boolean} autoReload
45         * True to automagicly reload the datasource when a filter change happens.
46         */
47        autoReload: true,
48        /**
49         * @cfg {String} stateId
50         * Name of the Ext.data.Store value to be used to store state information.
51         */
52        stateId: undefined,
53        /**
54         * @cfg {Boolean} showMenu
55         * True to show the filter menus
56         */
57        showMenu: true,
58    /**
59     * @cfg {String} filtersText
60     * The text displayed for the "Filters" menu item
61     */
62    filtersText: 'Filters',
63
64        init: function(grid){
65    if(grid instanceof Ext.grid.GridPanel){
66      this.grid  = grid;
67     
68      this.store = this.grid.getStore();
69      if(this.local){
70        this.store.on('load', function(store) {
71          store.filterBy(this.getRecordFilter());
72        }, this);
73      } else {
74        this.store.on('beforeload', this.onBeforeLoad, this);
75      }
76     
77      this.grid.filters = this;
78     
79      this.grid.addEvents('filterupdate');
80     
81      grid.on("render", this.onRender, this);
82      grid.on("beforestaterestore", this.applyState, this);
83      grid.on("beforestatesave", this.saveState, this);
84     
85    } else if(grid instanceof Ext.PagingToolbar) {
86      this.toolbar = grid;
87    }
88        },
89               
90        /** private **/
91        applyState: function(grid, state) {
92                this.suspendStateStore = true;
93                this.clearFilters();
94                if(state.filters) {
95                        for(var key in state.filters) {
96                                var filter = this.filters.get(key);
97                                if(filter) {
98                                        filter.setValue(state.filters[key]);
99                                        filter.setActive(true);
100                                }
101                        }
102    }
103   
104                this.deferredUpdate.cancel();
105                if(this.local) {
106                        this.reload();
107    }
108   
109                this.suspendStateStore = false;
110        },
111       
112        /** private **/
113        saveState: function(grid, state){
114                var filters = {};
115                this.filters.each(function(filter) {
116                        if(filter.active) {
117                                filters[filter.dataIndex] = filter.getValue();
118      }
119                });
120                return state.filters = filters;
121        },
122       
123        /** private **/
124        onRender: function(){
125                var hmenu;
126               
127                if(this.showMenu) {
128                        hmenu = this.grid.getView().hmenu;
129                       
130                        this.sep  = hmenu.addSeparator();
131                        this.menu = hmenu.add(new Ext.menu.CheckItem({
132                                        text: this.filtersText,
133                                        menu: new Ext.menu.Menu()
134                                }));
135                        this.menu.on('checkchange', this.onCheckChange, this);
136                        this.menu.on('beforecheckchange', this.onBeforeCheck, this);
137                               
138                        hmenu.on('beforeshow', this.onMenu, this);
139                }
140               
141                this.grid.getView().on("refresh", this.onRefresh, this);
142                this.updateColumnHeadings(this.grid.getView());
143        },
144       
145        /** private **/
146        onMenu: function(filterMenu) {
147                var filter = this.getMenuFilter();
148                if(filter) {
149                        this.menu.menu = filter.menu;
150                        this.menu.setChecked(filter.active, false);
151                }
152               
153                this.menu.setVisible(filter !== undefined);
154                this.sep.setVisible(filter !== undefined);
155        },
156       
157        /** private **/
158        onCheckChange: function(item, value) {
159                this.getMenuFilter().setActive(value);
160        },
161       
162        /** private **/
163        onBeforeCheck: function(check, value) {
164                return !value || this.getMenuFilter().isActivatable();
165        },
166       
167        /** private **/
168        onStateChange: function(event, filter) {
169    if(event == "serialize") {
170      return;
171    }
172   
173                if(filter == this.getMenuFilter()) {
174                        this.menu.setChecked(filter.active, false);
175    }
176                       
177                if(this.autoReload || this.local) {
178                        this.deferredUpdate.delay(this.updateBuffer);
179    }
180               
181                var view = this.grid.getView();
182                this.updateColumnHeadings(view);
183                       
184                this.grid.saveState();
185                       
186                this.grid.fireEvent('filterupdate', this, filter);
187        },
188       
189        /** private **/
190        onBeforeLoad: function(store, options) {
191    options.params = options.params || {};
192                this.cleanParams(options.params);               
193                var params = this.buildQuery(this.getFilterData());
194                Ext.apply(options.params, params);
195        },
196       
197        /** private **/
198        onRefresh: function(view) {
199                this.updateColumnHeadings(view);
200        },
201       
202        /** private **/
203        getMenuFilter: function() {
204                var view = this.grid.getView();
205                if(!view || view.hdCtxIndex === undefined) {
206                        return null;
207    }
208               
209                return this.filters.get(view.cm.config[view.hdCtxIndex].dataIndex);
210        },
211       
212        /** private **/
213        updateColumnHeadings: function(view) {
214                if(!view || !view.mainHd) {
215      return;
216    }
217               
218                var hds = view.mainHd.select('td').removeClass(this.filterCls);
219                for(var i=0, len=view.cm.config.length; i<len; i++) {
220                        var filter = this.getFilter(view.cm.config[i].dataIndex);
221                        if(filter && filter.active) {
222                                hds.item(i).addClass(this.filterCls);
223      }
224                }
225        },
226       
227        /** private **/
228        reload: function() {
229                if(this.local){
230                        this.grid.store.clearFilter(true);
231                        this.grid.store.filterBy(this.getRecordFilter());
232                } else {
233                        this.deferredUpdate.cancel();
234                        var store = this.grid.store;
235                        if(this.toolbar) {
236                                var start = this.toolbar.paramNames.start;
237                                if(store.lastOptions && store.lastOptions.params && store.lastOptions.params[start]) {
238                                        store.lastOptions.params[start] = 0;
239        }
240                        }
241                        store.reload();
242                }
243        },
244       
245        /**
246         * Method factory that generates a record validator for the filters active at the time
247         * of invokation.
248         *
249         * @private
250         */
251        getRecordFilter: function() {
252                var f = [];
253                this.filters.each(function(filter) {
254                        if(filter.active) {
255        f.push(filter);
256      }
257                });
258               
259                var len = f.length;
260                return function(record) {
261                        for(var i=0; i<len; i++) {
262                                if(!f[i].validateRecord(record)) {
263                                        return false;
264        }
265      }
266                        return true;
267                };
268        },
269       
270        /**
271         * Adds a filter to the collection.
272         *
273         * @param {Object/Ext.grid.filter.Filter} config A filter configuration or a filter object.
274         *
275         * @return {Ext.grid.filter.Filter} The existing or newly created filter object.
276         */
277        addFilter: function(config) {
278                var filter = config.menu ? config : new (this.getFilterClass(config.type))(config);
279                this.filters.add(filter);
280               
281                Ext.util.Observable.capture(filter, this.onStateChange, this);
282                return filter;
283        },
284       
285        /**
286         * Returns a filter for the given dataIndex, if on exists.
287         *
288         * @param {String} dataIndex The dataIndex of the desired filter object.
289         *
290         * @return {Ext.grid.filter.Filter}
291         */
292        getFilter: function(dataIndex){
293                return this.filters.get(dataIndex);
294        },
295
296        /**
297         * Turns all filters off. This does not clear the configuration information.
298         */
299        clearFilters: function() {
300                this.filters.each(function(filter) {
301                        filter.setActive(false);
302                });
303        },
304
305        /** private **/
306        getFilterData: function() {
307                var filters = [];
308               
309                this.filters.each(function(f) {
310                        if(f.active) {
311                                var d = [].concat(f.serialize());
312                                for(var i=0, len=d.length; i<len; i++) {
313                                        filters.push({field: f.dataIndex, data: d[i]});
314        }
315                        }
316                });
317               
318                return filters;
319        },
320       
321        /**
322         * Function to take structured filter data and 'flatten' it into query parameteres. The default function
323         * will produce a query string of the form:
324         *              filters[0][field]=dataIndex&filters[0][data][param1]=param&filters[0][data][param2]=param...
325         *
326         * @param {Array} filters A collection of objects representing active filters and their configuration.
327         *        Each element will take the form of {field: dataIndex, data: filterConf}. dataIndex is not assured
328         *    to be unique as any one filter may be a composite of more basic filters for the same dataIndex.
329         *
330         * @return {Object} Query keys and values
331         */
332        buildQuery: function(filters) {
333                var p = {};
334                for(var i=0, len=filters.length; i<len; i++) {
335                        var f = filters[i];
336                        var root = [this.paramPrefix, '[', i, ']'].join('');
337                        p[root + '[field]'] = f.field;
338                       
339                        var dataPrefix = root + '[data]';
340                        for(var key in f.data) {
341                                p[[dataPrefix, '[', key, ']'].join('')] = f.data[key];
342      }
343                }
344               
345                return p;
346        },
347       
348        /**
349         * Removes filter related query parameters from the provided object.
350         *
351         * @param {Object} p Query parameters that may contain filter related fields.
352         */
353        cleanParams: function(p) {
354                var regex = new RegExp("^" + this.paramPrefix + "\[[0-9]+\]");
355                for(var key in p) {
356                        if(regex.test(key)) {
357                                delete p[key];
358      }
359    }
360        },
361       
362        /**
363         * Function for locating filter classes, overwrite this with your favorite
364         * loader to provide dynamic filter loading.
365         *
366         * @param {String} type The type of filter to load.
367         *
368         * @return {Class}
369         */
370        getFilterClass: function(type){
371                return Ext.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];
372        }
373});
Note: See TracBrowser for help on using the repository browser.