+++ /dev/null
-/*\r
- * Ext JS Library 2.2.1\r
- * Copyright(c) 2006-2009, Ext JS, LLC.\r
- * licensing@extjs.com\r
- * \r
- * http://extjs.com/license\r
- */\r
-\r
-Ext.grid.GridFilters = function(config){ \r
- this.filters = new Ext.util.MixedCollection();\r
- this.filters.getKey = function(o) {return o ? o.dataIndex : null};\r
- \r
- for(var i=0, len=config.filters.length; i<len; i++) {\r
- this.addFilter(config.filters[i]);\r
- }\r
- \r
- this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);\r
- \r
- delete config.filters;\r
- Ext.apply(this, config);\r
-};\r
-Ext.extend(Ext.grid.GridFilters, Ext.util.Observable, {\r
- /**\r
- * @cfg {Integer} updateBuffer\r
- * Number of milisecond to defer store updates since the last filter change.\r
- */\r
- updateBuffer: 500,\r
- /**\r
- * @cfg {String} paramPrefix\r
- * The url parameter prefix for the filters.\r
- */\r
- paramPrefix: 'filter',\r
- /**\r
- * @cfg {String} fitlerCls\r
- * The css class to be applied to column headers that active filters. Defaults to 'ux-filterd-column'\r
- */\r
- filterCls: 'ux-filtered-column',\r
- /**\r
- * @cfg {Boolean} local\r
- * True to use Ext.data.Store filter functions instead of server side filtering.\r
- */\r
- local: false,\r
- /**\r
- * @cfg {Boolean} autoReload\r
- * True to automagicly reload the datasource when a filter change happens.\r
- */\r
- autoReload: true,\r
- /**\r
- * @cfg {String} stateId\r
- * Name of the Ext.data.Store value to be used to store state information.\r
- */\r
- stateId: undefined,\r
- /**\r
- * @cfg {Boolean} showMenu\r
- * True to show the filter menus\r
- */\r
- showMenu: true,\r
- /**\r
- * @cfg {String} filtersText\r
- * The text displayed for the "Filters" menu item\r
- */\r
- filtersText: 'Filters',\r
-\r
- init: function(grid){\r
- if(grid instanceof Ext.grid.GridPanel){\r
- this.grid = grid;\r
- \r
- this.store = this.grid.getStore();\r
- if(this.local){\r
- this.store.on('load', function(store) {\r
- store.filterBy(this.getRecordFilter());\r
- }, this);\r
- } else {\r
- this.store.on('beforeload', this.onBeforeLoad, this);\r
- }\r
- \r
- this.grid.filters = this;\r
- \r
- this.grid.addEvents('filterupdate');\r
- \r
- grid.on("render", this.onRender, this);\r
- grid.on("beforestaterestore", this.applyState, this);\r
- grid.on("beforestatesave", this.saveState, this);\r
- \r
- } else if(grid instanceof Ext.PagingToolbar) {\r
- this.toolbar = grid;\r
- }\r
- },\r
- \r
- /** private **/\r
- applyState: function(grid, state) {\r
- this.suspendStateStore = true;\r
- this.clearFilters();\r
- if(state.filters) {\r
- for(var key in state.filters) {\r
- var filter = this.filters.get(key);\r
- if(filter) {\r
- filter.setValue(state.filters[key]);\r
- filter.setActive(true);\r
- }\r
- }\r
- }\r
- \r
- this.deferredUpdate.cancel();\r
- if(this.local) {\r
- this.reload();\r
- }\r
- \r
- this.suspendStateStore = false;\r
- },\r
- \r
- /** private **/\r
- saveState: function(grid, state){\r
- var filters = {};\r
- this.filters.each(function(filter) {\r
- if(filter.active) {\r
- filters[filter.dataIndex] = filter.getValue();\r
- }\r
- });\r
- return state.filters = filters;\r
- },\r
- \r
- /** private **/\r
- onRender: function(){\r
- var hmenu;\r
- \r
- if(this.showMenu) {\r
- hmenu = this.grid.getView().hmenu;\r
- \r
- this.sep = hmenu.addSeparator();\r
- this.menu = hmenu.add(new Ext.menu.CheckItem({\r
- text: this.filtersText,\r
- menu: new Ext.menu.Menu()\r
- }));\r
- this.menu.on('checkchange', this.onCheckChange, this);\r
- this.menu.on('beforecheckchange', this.onBeforeCheck, this);\r
- \r
- hmenu.on('beforeshow', this.onMenu, this);\r
- }\r
- \r
- this.grid.getView().on("refresh", this.onRefresh, this);\r
- this.updateColumnHeadings(this.grid.getView());\r
- },\r
- \r
- /** private **/\r
- onMenu: function(filterMenu) {\r
- var filter = this.getMenuFilter();\r
- if(filter) {\r
- this.menu.menu = filter.menu;\r
- this.menu.setChecked(filter.active, false);\r
- }\r
- \r
- this.menu.setVisible(filter !== undefined);\r
- this.sep.setVisible(filter !== undefined);\r
- },\r
- \r
- /** private **/\r
- onCheckChange: function(item, value) {\r
- this.getMenuFilter().setActive(value);\r
- },\r
- \r
- /** private **/\r
- onBeforeCheck: function(check, value) {\r
- return !value || this.getMenuFilter().isActivatable();\r
- },\r
- \r
- /** private **/\r
- onStateChange: function(event, filter) {\r
- if(event == "serialize") {\r
- return;\r
- }\r
- \r
- if(filter == this.getMenuFilter()) {\r
- this.menu.setChecked(filter.active, false);\r
- }\r
- \r
- if(this.autoReload || this.local) {\r
- this.deferredUpdate.delay(this.updateBuffer);\r
- }\r
- \r
- var view = this.grid.getView();\r
- this.updateColumnHeadings(view);\r
- \r
- this.grid.saveState();\r
- \r
- this.grid.fireEvent('filterupdate', this, filter);\r
- },\r
- \r
- /** private **/\r
- onBeforeLoad: function(store, options) {\r
- options.params = options.params || {};\r
- this.cleanParams(options.params); \r
- var params = this.buildQuery(this.getFilterData());\r
- Ext.apply(options.params, params);\r
- },\r
- \r
- /** private **/\r
- onRefresh: function(view) {\r
- this.updateColumnHeadings(view);\r
- },\r
- \r
- /** private **/\r
- getMenuFilter: function() {\r
- var view = this.grid.getView();\r
- if(!view || view.hdCtxIndex === undefined) {\r
- return null;\r
- }\r
- \r
- return this.filters.get(view.cm.config[view.hdCtxIndex].dataIndex);\r
- },\r
- \r
- /** private **/\r
- updateColumnHeadings: function(view) {\r
- if(!view || !view.mainHd) {\r
- return;\r
- }\r
- \r
- var hds = view.mainHd.select('td').removeClass(this.filterCls);\r
- for(var i=0, len=view.cm.config.length; i<len; i++) {\r
- var filter = this.getFilter(view.cm.config[i].dataIndex);\r
- if(filter && filter.active) {\r
- hds.item(i).addClass(this.filterCls);\r
- }\r
- }\r
- },\r
- \r
- /** private **/\r
- reload: function() {\r
- if(this.local){\r
- this.grid.store.clearFilter(true);\r
- this.grid.store.filterBy(this.getRecordFilter());\r
- } else {\r
- this.deferredUpdate.cancel();\r
- var store = this.grid.store;\r
- if(this.toolbar) {\r
- var start = this.toolbar.paramNames.start;\r
- if(store.lastOptions && store.lastOptions.params && store.lastOptions.params[start]) {\r
- store.lastOptions.params[start] = 0;\r
- }\r
- }\r
- store.reload();\r
- }\r
- },\r
- \r
- /**\r
- * Method factory that generates a record validator for the filters active at the time\r
- * of invokation.\r
- * \r
- * @private\r
- */\r
- getRecordFilter: function() {\r
- var f = [];\r
- this.filters.each(function(filter) {\r
- if(filter.active) {\r
- f.push(filter);\r
- }\r
- });\r
- \r
- var len = f.length;\r
- return function(record) {\r
- for(var i=0; i<len; i++) {\r
- if(!f[i].validateRecord(record)) {\r
- return false;\r
- }\r
- }\r
- return true;\r
- };\r
- },\r
- \r
- /**\r
- * Adds a filter to the collection.\r
- * \r
- * @param {Object/Ext.grid.filter.Filter} config A filter configuration or a filter object.\r
- * \r
- * @return {Ext.grid.filter.Filter} The existing or newly created filter object.\r
- */\r
- addFilter: function(config) {\r
- var filter = config.menu ? config : new (this.getFilterClass(config.type))(config);\r
- this.filters.add(filter);\r
- \r
- Ext.util.Observable.capture(filter, this.onStateChange, this);\r
- return filter;\r
- },\r
- \r
- /**\r
- * Returns a filter for the given dataIndex, if on exists.\r
- * \r
- * @param {String} dataIndex The dataIndex of the desired filter object.\r
- * \r
- * @return {Ext.grid.filter.Filter}\r
- */\r
- getFilter: function(dataIndex){\r
- return this.filters.get(dataIndex);\r
- },\r
-\r
- /**\r
- * Turns all filters off. This does not clear the configuration information.\r
- */\r
- clearFilters: function() {\r
- this.filters.each(function(filter) {\r
- filter.setActive(false);\r
- });\r
- },\r
-\r
- /** private **/\r
- getFilterData: function() {\r
- var filters = [];\r
- \r
- this.filters.each(function(f) {\r
- if(f.active) {\r
- var d = [].concat(f.serialize());\r
- for(var i=0, len=d.length; i<len; i++) {\r
- filters.push({field: f.dataIndex, data: d[i]});\r
- }\r
- }\r
- });\r
- \r
- return filters;\r
- },\r
- \r
- /**\r
- * Function to take structured filter data and 'flatten' it into query parameteres. The default function\r
- * will produce a query string of the form:\r
- * filters[0][field]=dataIndex&filters[0][data][param1]=param&filters[0][data][param2]=param...\r
- * \r
- * @param {Array} filters A collection of objects representing active filters and their configuration.\r
- * Each element will take the form of {field: dataIndex, data: filterConf}. dataIndex is not assured\r
- * to be unique as any one filter may be a composite of more basic filters for the same dataIndex.\r
- * \r
- * @return {Object} Query keys and values\r
- */\r
- buildQuery: function(filters) {\r
- var p = {};\r
- for(var i=0, len=filters.length; i<len; i++) {\r
- var f = filters[i];\r
- var root = [this.paramPrefix, '[', i, ']'].join('');\r
- p[root + '[field]'] = f.field;\r
- \r
- var dataPrefix = root + '[data]';\r
- for(var key in f.data) {\r
- p[[dataPrefix, '[', key, ']'].join('')] = f.data[key];\r
- }\r
- }\r
- \r
- return p;\r
- },\r
- \r
- /**\r
- * Removes filter related query parameters from the provided object.\r
- * \r
- * @param {Object} p Query parameters that may contain filter related fields.\r
- */\r
- cleanParams: function(p) {\r
- var regex = new RegExp("^" + this.paramPrefix + "\[[0-9]+\]");\r
- for(var key in p) {\r
- if(regex.test(key)) {\r
- delete p[key];\r
- }\r
- }\r
- },\r
- \r
- /**\r
- * Function for locating filter classes, overwrite this with your favorite\r
- * loader to provide dynamic filter loading.\r
- * \r
- * @param {String} type The type of filter to load.\r
- * \r
- * @return {Class}\r
- */\r
- getFilterClass: function(type){\r
- return Ext.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];\r
- }\r
-});
\ No newline at end of file