Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / docs / source / GridFilters.html
1 <html>
2 <head>
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
4   <title>The source code</title>
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 </head>
8 <body  onload="prettyPrint();">
9     <pre class="prettyprint lang-js">/*!
10  * Ext JS Library 3.3.1
11  * Copyright(c) 2006-2010 Sencha Inc.
12  * licensing@sencha.com
13  * http://www.sencha.com/license
14  */
15 Ext.namespace('Ext.ux.grid');
16
17 <div id="cls-Ext.ux.grid.GridFilters"></div>/**
18  * @class Ext.ux.grid.GridFilters
19  * @extends Ext.util.Observable
20  * <p>GridFilter is a plugin (<code>ptype='gridfilters'</code>) for grids that
21  * allow for a slightly more robust representation of filtering than what is
22  * provided by the default store.</p>
23  * <p>Filtering is adjusted by the user using the grid's column header menu
24  * (this menu can be disabled through configuration). Through this menu users
25  * can configure, enable, and disable filters for each column.</p>
26  * <p><b><u>Features:</u></b></p>
27  * <div class="mdetail-params"><ul>
28  * <li><b>Filtering implementations</b> :
29  * <div class="sub-desc">
30  * Default filtering for Strings, Numeric Ranges, Date Ranges, Lists (which can
31  * be backed by a Ext.data.Store), and Boolean. Additional custom filter types
32  * and menus are easily created by extending Ext.ux.grid.filter.Filter.
33  * </div></li>
34  * <li><b>Graphical indicators</b> :
35  * <div class="sub-desc">
36  * Columns that are filtered have {@link #filterCls a configurable css class}
37  * applied to the column headers.
38  * </div></li>
39  * <li><b>Paging</b> :
40  * <div class="sub-desc">
41  * If specified as a plugin to the grid's configured PagingToolbar, the current page
42  * will be reset to page 1 whenever you update the filters.
43  * </div></li>
44  * <li><b>Automatic Reconfiguration</b> :
45  * <div class="sub-desc">
46  * Filters automatically reconfigure when the grid 'reconfigure' event fires.
47  * </div></li>
48  * <li><b>Stateful</b> :
49  * Filter information will be persisted across page loads by specifying a
50  * <code>stateId</code> in the Grid configuration.
51  * <div class="sub-desc">
52  * The filter collection binds to the
53  * <code>{@link Ext.grid.GridPanel#beforestaterestore beforestaterestore}</code>
54  * and <code>{@link Ext.grid.GridPanel#beforestatesave beforestatesave}</code>
55  * events in order to be stateful.
56  * </div></li>
57  * <li><b>Grid Changes</b> :
58  * <div class="sub-desc"><ul>
59  * <li>A <code>filters</code> <i>property</i> is added to the grid pointing to
60  * this plugin.</li>
61  * <li>A <code>filterupdate</code> <i>event</i> is added to the grid and is
62  * fired upon onStateChange completion.</li>
63  * </ul></div></li>
64  * <li><b>Server side code examples</b> :
65  * <div class="sub-desc"><ul>
66  * <li><a href="http://www.vinylfox.com/extjs/grid-filter-php-backend-code.php">PHP</a> - (Thanks VinylFox)</li>
67  * <li><a href="http://extjs.com/forum/showthread.php?p=77326#post77326">Ruby on Rails</a> - (Thanks Zyclops)</li>
68  * <li><a href="http://extjs.com/forum/showthread.php?p=176596#post176596">Ruby on Rails</a> - (Thanks Rotomaul)</li>
69  * <li><a href="http://www.debatablybeta.com/posts/using-extjss-grid-filtering-with-django/">Python</a> - (Thanks Matt)</li>
70  * <li><a href="http://mcantrell.wordpress.com/2008/08/22/extjs-grids-and-grails/">Grails</a> - (Thanks Mike)</li>
71  * </ul></div></li>
72  * </ul></div>
73  * <p><b><u>Example usage:</u></b></p>
74  * <pre><code>
75 var store = new Ext.data.GroupingStore({
76     ...
77 });
78
79 var filters = new Ext.ux.grid.GridFilters({
80     autoReload: false, //don&#39;t reload automatically
81     local: true, //only filter locally
82     // filters may be configured through the plugin,
83     // or in the column definition within the column model configuration
84     filters: [{
85         type: 'numeric',
86         dataIndex: 'id'
87     }, {
88         type: 'string',
89         dataIndex: 'name'
90     }, {
91         type: 'numeric',
92         dataIndex: 'price'
93     }, {
94         type: 'date',
95         dataIndex: 'dateAdded'
96     }, {
97         type: 'list',
98         dataIndex: 'size',
99         options: ['extra small', 'small', 'medium', 'large', 'extra large'],
100         phpMode: true
101     }, {
102         type: 'boolean',
103         dataIndex: 'visible'
104     }]
105 });
106 var cm = new Ext.grid.ColumnModel([{
107     ...
108 }]);
109
110 var grid = new Ext.grid.GridPanel({
111      ds: store,
112      cm: cm,
113      view: new Ext.grid.GroupingView(),
114      plugins: [filters],
115      height: 400,
116      width: 700,
117      bbar: new Ext.PagingToolbar({
118          store: store,
119          pageSize: 15,
120          plugins: [filters] //reset page to page 1 if filters change
121      })
122  });
123
124 store.load({params: {start: 0, limit: 15}});
125
126 // a filters property is added to the grid
127 grid.filters
128  * </code></pre>
129  */
130 Ext.ux.grid.GridFilters = Ext.extend(Ext.util.Observable, {
131     <div id="cfg-Ext.ux.grid.GridFilters-autoReload"></div>/**
132      * @cfg {Boolean} autoReload
133      * Defaults to true, reloading the datasource when a filter change happens.
134      * Set this to false to prevent the datastore from being reloaded if there
135      * are changes to the filters.  See <code>{@link updateBuffer}</code>.
136      */
137     autoReload : true,
138     <div id="cfg-Ext.ux.grid.GridFilters-encode"></div>/**
139      * @cfg {Boolean} encode
140      * Specify true for {@link #buildQuery} to use Ext.util.JSON.encode to
141      * encode the filter query parameter sent with a remote request.
142      * Defaults to false.
143      */
144     <div id="cfg-Ext.ux.grid.GridFilters-filters"></div>/**
145      * @cfg {Array} filters
146      * An Array of filters config objects. Refer to each filter type class for
147      * configuration details specific to each filter type. Filters for Strings,
148      * Numeric Ranges, Date Ranges, Lists, and Boolean are the standard filters
149      * available.
150      */
151     <div id="cfg-Ext.ux.grid.GridFilters-filterCls"></div>/**
152      * @cfg {String} filterCls
153      * The css class to be applied to column headers with active filters.
154      * Defaults to <tt>'ux-filterd-column'</tt>.
155      */
156     filterCls : 'ux-filtered-column',
157     <div id="cfg-Ext.ux.grid.GridFilters-local"></div>/**
158      * @cfg {Boolean} local
159      * <tt>true</tt> to use Ext.data.Store filter functions (local filtering)
160      * instead of the default (<tt>false</tt>) server side filtering.
161      */
162     local : false,
163     <div id="cfg-Ext.ux.grid.GridFilters-menuFilterText"></div>/**
164      * @cfg {String} menuFilterText
165      * defaults to <tt>'Filters'</tt>.
166      */
167     menuFilterText : 'Filters',
168     <div id="cfg-Ext.ux.grid.GridFilters-paramPrefix"></div>/**
169      * @cfg {String} paramPrefix
170      * The url parameter prefix for the filters.
171      * Defaults to <tt>'filter'</tt>.
172      */
173     paramPrefix : 'filter',
174     <div id="cfg-Ext.ux.grid.GridFilters-showMenu"></div>/**
175      * @cfg {Boolean} showMenu
176      * Defaults to true, including a filter submenu in the default header menu.
177      */
178     showMenu : true,
179     <div id="cfg-Ext.ux.grid.GridFilters-stateId"></div>/**
180      * @cfg {String} stateId
181      * Name of the value to be used to store state information.
182      */
183     stateId : undefined,
184     <div id="cfg-Ext.ux.grid.GridFilters-updateBuffer"></div>/**
185      * @cfg {Integer} updateBuffer
186      * Number of milliseconds to defer store updates since the last filter change.
187      */
188     updateBuffer : 500,
189
190     /** @private */
191     constructor : function (config) {
192         config = config || {};
193         this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);
194         this.filters = new Ext.util.MixedCollection();
195         this.filters.getKey = function (o) {
196             return o ? o.dataIndex : null;
197         };
198         this.addFilters(config.filters);
199         delete config.filters;
200         Ext.apply(this, config);
201     },
202
203     /** @private */
204     init : function (grid) {
205         if (grid instanceof Ext.grid.GridPanel) {
206             this.grid = grid;
207
208             this.bindStore(this.grid.getStore(), true);
209             // assumes no filters were passed in the constructor, so try and use ones from the colModel
210             if(this.filters.getCount() == 0){
211                 this.addFilters(this.grid.getColumnModel());
212             }
213
214             this.grid.filters = this;
215
216             this.grid.addEvents({'filterupdate': true});
217
218             grid.on({
219                 scope: this,
220                 beforestaterestore: this.applyState,
221                 beforestatesave: this.saveState,
222                 beforedestroy: this.destroy,
223                 reconfigure: this.onReconfigure
224             });
225
226             if (grid.rendered){
227                 this.onRender();
228             } else {
229                 grid.on({
230                     scope: this,
231                     single: true,
232                     render: this.onRender
233                 });
234             }
235
236         } else if (grid instanceof Ext.PagingToolbar) {
237             this.toolbar = grid;
238         }
239     },
240
241     /**
242      * @private
243      * Handler for the grid's beforestaterestore event (fires before the state of the
244      * grid is restored).
245      * @param {Object} grid The grid object
246      * @param {Object} state The hash of state values returned from the StateProvider.
247      */
248     applyState : function (grid, state) {
249         var key, filter;
250         this.applyingState = true;
251         this.clearFilters();
252         if (state.filters) {
253             for (key in state.filters) {
254                 filter = this.filters.get(key);
255                 if (filter) {
256                     filter.setValue(state.filters[key]);
257                     filter.setActive(true);
258                 }
259             }
260         }
261         this.deferredUpdate.cancel();
262         if (this.local) {
263             this.reload();
264         }
265         delete this.applyingState;
266         delete state.filters;
267     },
268
269     <div id="method-Ext.ux.grid.GridFilters-saveState"></div>/**
270      * Saves the state of all active filters
271      * @param {Object} grid
272      * @param {Object} state
273      * @return {Boolean}
274      */
275     saveState : function (grid, state) {
276         var filters = {};
277         this.filters.each(function (filter) {
278             if (filter.active) {
279                 filters[filter.dataIndex] = filter.getValue();
280             }
281         });
282         return (state.filters = filters);
283     },
284
285     /**
286      * @private
287      * Handler called when the grid is rendered
288      */
289     onRender : function () {
290         this.grid.getView().on('refresh', this.onRefresh, this);
291         this.createMenu();
292     },
293
294     /**
295      * @private
296      * Handler called by the grid 'beforedestroy' event
297      */
298     destroy : function () {
299         this.removeAll();
300         this.purgeListeners();
301
302         if(this.filterMenu){
303             Ext.menu.MenuMgr.unregister(this.filterMenu);
304             this.filterMenu.destroy();
305              this.filterMenu = this.menu.menu = null;
306         }
307     },
308
309     <div id="method-Ext.ux.grid.GridFilters-removeAll"></div>/**
310      * Remove all filters, permanently destroying them.
311      */
312     removeAll : function () {
313         if(this.filters){
314             Ext.destroy.apply(Ext, this.filters.items);
315             // remove all items from the collection
316             this.filters.clear();
317         }
318     },
319
320
321     <div id="method-Ext.ux.grid.GridFilters-bindStore"></div>/**
322      * Changes the data store bound to this view and refreshes it.
323      * @param {Store} store The store to bind to this view
324      */
325     bindStore : function(store, initial){
326         if(!initial && this.store){
327             if (this.local) {
328                 store.un('load', this.onLoad, this);
329             } else {
330                 store.un('beforeload', this.onBeforeLoad, this);
331             }
332         }
333         if(store){
334             if (this.local) {
335                 store.on('load', this.onLoad, this);
336             } else {
337                 store.on('beforeload', this.onBeforeLoad, this);
338             }
339         }
340         this.store = store;
341     },
342
343     /**
344      * @private
345      * Handler called when the grid reconfigure event fires
346      */
347     onReconfigure : function () {
348         this.bindStore(this.grid.getStore());
349         this.store.clearFilter();
350         this.removeAll();
351         this.addFilters(this.grid.getColumnModel());
352         this.updateColumnHeadings();
353     },
354
355     createMenu : function () {
356         var view = this.grid.getView(),
357             hmenu = view.hmenu;
358
359         if (this.showMenu && hmenu) {
360
361             this.sep  = hmenu.addSeparator();
362             this.filterMenu = new Ext.menu.Menu({
363                 id: this.grid.id + '-filters-menu'
364             });
365             this.menu = hmenu.add({
366                 checked: false,
367                 itemId: 'filters',
368                 text: this.menuFilterText,
369                 menu: this.filterMenu
370             });
371
372             this.menu.on({
373                 scope: this,
374                 checkchange: this.onCheckChange,
375                 beforecheckchange: this.onBeforeCheck
376             });
377             hmenu.on('beforeshow', this.onMenu, this);
378         }
379         this.updateColumnHeadings();
380     },
381
382     /**
383      * @private
384      * Get the filter menu from the filters MixedCollection based on the clicked header
385      */
386     getMenuFilter : function () {
387         var view = this.grid.getView();
388         if (!view || view.hdCtxIndex === undefined) {
389             return null;
390         }
391         return this.filters.get(
392             view.cm.config[view.hdCtxIndex].dataIndex
393         );
394     },
395
396     /**
397      * @private
398      * Handler called by the grid's hmenu beforeshow event
399      */
400     onMenu : function (filterMenu) {
401         var filter = this.getMenuFilter();
402
403         if (filter) {
404 /*
405 TODO: lazy rendering
406             if (!filter.menu) {
407                 filter.menu = filter.createMenu();
408             }
409 */
410             this.menu.menu = filter.menu;
411             this.menu.setChecked(filter.active, false);
412             // disable the menu if filter.disabled explicitly set to true
413             this.menu.setDisabled(filter.disabled === true);
414         }
415
416         this.menu.setVisible(filter !== undefined);
417         this.sep.setVisible(filter !== undefined);
418     },
419
420     /** @private */
421     onCheckChange : function (item, value) {
422         this.getMenuFilter().setActive(value);
423     },
424
425     /** @private */
426     onBeforeCheck : function (check, value) {
427         return !value || this.getMenuFilter().isActivatable();
428     },
429
430     /**
431      * @private
432      * Handler for all events on filters.
433      * @param {String} event Event name
434      * @param {Object} filter Standard signature of the event before the event is fired
435      */
436     onStateChange : function (event, filter) {
437         if (event === 'serialize') {
438             return;
439         }
440
441         if (filter == this.getMenuFilter()) {
442             this.menu.setChecked(filter.active, false);
443         }
444
445         if ((this.autoReload || this.local) && !this.applyingState) {
446             this.deferredUpdate.delay(this.updateBuffer);
447         }
448         this.updateColumnHeadings();
449
450         if (!this.applyingState) {
451             this.grid.saveState();
452         }
453         this.grid.fireEvent('filterupdate', this, filter);
454     },
455
456     /**
457      * @private
458      * Handler for store's beforeload event when configured for remote filtering
459      * @param {Object} store
460      * @param {Object} options
461      */
462     onBeforeLoad : function (store, options) {
463         options.params = options.params || {};
464         this.cleanParams(options.params);
465         var params = this.buildQuery(this.getFilterData());
466         Ext.apply(options.params, params);
467     },
468
469     /**
470      * @private
471      * Handler for store's load event when configured for local filtering
472      * @param {Object} store
473      * @param {Object} options
474      */
475     onLoad : function (store, options) {
476         store.filterBy(this.getRecordFilter());
477     },
478
479     /**
480      * @private
481      * Handler called when the grid's view is refreshed
482      */
483     onRefresh : function () {
484         this.updateColumnHeadings();
485     },
486
487     <div id="method-Ext.ux.grid.GridFilters-updateColumnHeadings"></div>/**
488      * Update the styles for the header row based on the active filters
489      */
490     updateColumnHeadings : function () {
491         var view = this.grid.getView(),
492             i, len, filter;
493         if (view.mainHd) {
494             for (i = 0, len = view.cm.config.length; i < len; i++) {
495                 filter = this.getFilter(view.cm.config[i].dataIndex);
496                 Ext.fly(view.getHeaderCell(i))[filter && filter.active ? 'addClass' : 'removeClass'](this.filterCls);
497             }
498         }
499     },
500
501     /** @private */
502     reload : function () {
503         if (this.local) {
504             this.grid.store.clearFilter(true);
505             this.grid.store.filterBy(this.getRecordFilter());
506         } else {
507             var start,
508                 store = this.grid.store;
509             this.deferredUpdate.cancel();
510             if (this.toolbar) {
511                 start = store.paramNames.start;
512                 if (store.lastOptions && store.lastOptions.params && store.lastOptions.params[start]) {
513                     store.lastOptions.params[start] = 0;
514                 }
515             }
516             store.reload();
517         }
518     },
519
520     /**
521      * Method factory that generates a record validator for the filters active at the time
522      * of invokation.
523      * @private
524      */
525     getRecordFilter : function () {
526         var f = [], len, i;
527         this.filters.each(function (filter) {
528             if (filter.active) {
529                 f.push(filter);
530             }
531         });
532
533         len = f.length;
534         return function (record) {
535             for (i = 0; i < len; i++) {
536                 if (!f[i].validateRecord(record)) {
537                     return false;
538                 }
539             }
540             return true;
541         };
542     },
543
544     <div id="method-Ext.ux.grid.GridFilters-addFilter"></div>/**
545      * Adds a filter to the collection and observes it for state change.
546      * @param {Object/Ext.ux.grid.filter.Filter} config A filter configuration or a filter object.
547      * @return {Ext.ux.grid.filter.Filter} The existing or newly created filter object.
548      */
549     addFilter : function (config) {
550         var Cls = this.getFilterClass(config.type),
551             filter = config.menu ? config : (new Cls(config));
552         this.filters.add(filter);
553
554         Ext.util.Observable.capture(filter, this.onStateChange, this);
555         return filter;
556     },
557
558     <div id="method-Ext.ux.grid.GridFilters-addFilters"></div>/**
559      * Adds filters to the collection.
560      * @param {Array/Ext.grid.ColumnModel} filters Either an Array of
561      * filter configuration objects or an Ext.grid.ColumnModel.  The columns
562      * of a passed Ext.grid.ColumnModel will be examined for a <code>filter</code>
563      * property and, if present, will be used as the filter configuration object.
564      */
565     addFilters : function (filters) {
566         if (filters) {
567             var i, len, filter, cm = false, dI;
568             if (filters instanceof Ext.grid.ColumnModel) {
569                 filters = filters.config;
570                 cm = true;
571             }
572             for (i = 0, len = filters.length; i < len; i++) {
573                 filter = false;
574                 if (cm) {
575                     dI = filters[i].dataIndex;
576                     filter = filters[i].filter || filters[i].filterable;
577                     if (filter){
578                         filter = (filter === true) ? {} : filter;
579                         Ext.apply(filter, {dataIndex:dI});
580                         // filter type is specified in order of preference:
581                         //     filter type specified in config
582                         //     type specified in store's field's type config
583                         filter.type = filter.type || this.store.fields.get(dI).type.type;
584                     }
585                 } else {
586                     filter = filters[i];
587                 }
588                 // if filter config found add filter for the column
589                 if (filter) {
590                     this.addFilter(filter);
591                 }
592             }
593         }
594     },
595
596     <div id="method-Ext.ux.grid.GridFilters-getFilter"></div>/**
597      * Returns a filter for the given dataIndex, if one exists.
598      * @param {String} dataIndex The dataIndex of the desired filter object.
599      * @return {Ext.ux.grid.filter.Filter}
600      */
601     getFilter : function (dataIndex) {
602         return this.filters.get(dataIndex);
603     },
604
605     <div id="method-Ext.ux.grid.GridFilters-clearFilters"></div>/**
606      * Turns all filters off. This does not clear the configuration information
607      * (see {@link #removeAll}).
608      */
609     clearFilters : function () {
610         this.filters.each(function (filter) {
611             filter.setActive(false);
612         });
613     },
614
615     <div id="method-Ext.ux.grid.GridFilters-getFilterData"></div>/**
616      * Returns an Array of the currently active filters.
617      * @return {Array} filters Array of the currently active filters.
618      */
619     getFilterData : function () {
620         var filters = [], i, len;
621
622         this.filters.each(function (f) {
623             if (f.active) {
624                 var d = [].concat(f.serialize());
625                 for (i = 0, len = d.length; i < len; i++) {
626                     filters.push({
627                         field: f.dataIndex,
628                         data: d[i]
629                     });
630                 }
631             }
632         });
633         return filters;
634     },
635
636     <div id="method-Ext.ux.grid.GridFilters-buildQuery"></div>/**
637      * Function to take the active filters data and build it into a query.
638      * The format of the query depends on the <code>{@link #encode}</code>
639      * configuration:
640      * <div class="mdetail-params"><ul>
641      *
642      * <li><b><tt>false</tt></b> : <i>Default</i>
643      * <div class="sub-desc">
644      * Flatten into query string of the form (assuming <code>{@link #paramPrefix}='filters'</code>:
645      * <pre><code>
646 filters[0][field]="someDataIndex"&
647 filters[0][data][comparison]="someValue1"&
648 filters[0][data][type]="someValue2"&
649 filters[0][data][value]="someValue3"&
650      * </code></pre>
651      * </div></li>
652      * <li><b><tt>true</tt></b> :
653      * <div class="sub-desc">
654      * JSON encode the filter data
655      * <pre><code>
656 filters[0][field]="someDataIndex"&
657 filters[0][data][comparison]="someValue1"&
658 filters[0][data][type]="someValue2"&
659 filters[0][data][value]="someValue3"&
660      * </code></pre>
661      * </div></li>
662      * </ul></div>
663      * Override this method to customize the format of the filter query for remote requests.
664      * @param {Array} filters A collection of objects representing active filters and their configuration.
665      *    Each element will take the form of {field: dataIndex, data: filterConf}. dataIndex is not assured
666      *    to be unique as any one filter may be a composite of more basic filters for the same dataIndex.
667      * @return {Object} Query keys and values
668      */
669     buildQuery : function (filters) {
670         var p = {}, i, f, root, dataPrefix, key, tmp,
671             len = filters.length;
672
673         if (!this.encode){
674             for (i = 0; i < len; i++) {
675                 f = filters[i];
676                 root = [this.paramPrefix, '[', i, ']'].join('');
677                 p[root + '[field]'] = f.field;
678
679                 dataPrefix = root + '[data]';
680                 for (key in f.data) {
681                     p[[dataPrefix, '[', key, ']'].join('')] = f.data[key];
682                 }
683             }
684         } else {
685             tmp = [];
686             for (i = 0; i < len; i++) {
687                 f = filters[i];
688                 tmp.push(Ext.apply(
689                     {},
690                     {field: f.field},
691                     f.data
692                 ));
693             }
694             // only build if there is active filter
695             if (tmp.length > 0){
696                 p[this.paramPrefix] = Ext.util.JSON.encode(tmp);
697             }
698         }
699         return p;
700     },
701
702     <div id="method-Ext.ux.grid.GridFilters-cleanParams"></div>/**
703      * Removes filter related query parameters from the provided object.
704      * @param {Object} p Query parameters that may contain filter related fields.
705      */
706     cleanParams : function (p) {
707         // if encoding just delete the property
708         if (this.encode) {
709             delete p[this.paramPrefix];
710         // otherwise scrub the object of filter data
711         } else {
712             var regex, key;
713             regex = new RegExp('^' + this.paramPrefix + '\[[0-9]+\]');
714             for (key in p) {
715                 if (regex.test(key)) {
716                     delete p[key];
717                 }
718             }
719         }
720     },
721
722     <div id="method-Ext.ux.grid.GridFilters-getFilterClass"></div>/**
723      * Function for locating filter classes, overwrite this with your favorite
724      * loader to provide dynamic filter loading.
725      * @param {String} type The type of filter to load ('Filter' is automatically
726      * appended to the passed type; eg, 'string' becomes 'StringFilter').
727      * @return {Class} The Ext.ux.grid.filter.Class
728      */
729     getFilterClass : function (type) {
730         // map the supported Ext.data.Field type values into a supported filter
731         switch(type) {
732             case 'auto':
733               type = 'string';
734               break;
735             case 'int':
736             case 'float':
737               type = 'numeric';
738               break;
739             case 'bool':
740               type = 'boolean';
741               break;
742         }
743         return Ext.ux.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];
744     }
745 });
746
747 // register ptype
748 Ext.preg('gridfilters', Ext.ux.grid.GridFilters);
749 </pre>    
750 </body>
751 </html>