GridFilters.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:24k
源码类别:

JavaScript

开发平台:

JavaScript

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