/** * The date grid filter allows you to create a filter selection that limits results * to values matching specific date constraints. The filter can be set programmatically or via * user input with a configurable {@link Ext.picker.Date DatePicker menu} in the filter section * of the column header. * * Example Date Filter Usage: * * @example * var shows = Ext.create('Ext.data.Store', { * fields: ['id','show', { * name: 'airDate', * type: 'date', * dateFormat: 'Y-m-d' * }], * data: [ * {id: 0, show: 'Battlestar Galactica', airDate: '1978-09-17'}, * {id: 1, show: 'Doctor Who', airDate: '1963-11-23'}, * {id: 2, show: 'Farscape', airDate: '1999-03-19'}, * {id: 3, show: 'Firefly', airDate: '2002-12-20'}, * {id: 4, show: 'Star Trek', airDate: '1966-09-08'}, * {id: 5, show: 'Star Wars: Christmas Special', airDate: '1978-11-17'} * ] * }); * * Ext.create('Ext.grid.Panel', { * renderTo: Ext.getBody(), * title: 'Sci-Fi Television', * height: 250, * width: 375, * store: shows, * plugins: 'gridfilters', * columns: [{ * dataIndex: 'id', * text: 'ID', * width: 50 * },{ * dataIndex: 'show', * text: 'Show', * flex: 1 * },{ * xtype: 'datecolumn', * dataIndex: 'airDate', * text: 'Original Air Date', * width: 125, * filter: { * type: 'date', * * // optional picker config * pickerDefaults: { * // any DatePicker configs * } * } * }] * }); */Ext.define('Ext.grid.filters.filter.Date', { extend: 'Ext.grid.filters.filter.TriFilter', alias: 'grid.filter.date', uses: ['Ext.picker.Date', 'Ext.menu.DatePicker'], type: 'date', config: { /** * @cfg {Object} [fields] * Configures field items individually. These properties override those defined * by `{@link #itemDefaults}`. * * Example usage: * fields: { * gt: { // override fieldCfg options * width: 200 * } * }, * @locale */ fields: { lt: {text: 'Before'}, gt: {text: 'After'}, eq: {text: 'On'} }, /** * @cfg {Object} pickerDefaults * Configuration options for the date picker associated with each field. */ pickerDefaults: { xtype: 'datepicker', border: 0 }, updateBuffer: 0, /** * @cfg {String} dateFormat * The date format to return when using getValue. * Defaults to {@link Ext.Date#defaultFormat}. */ dateFormat: undefined }, itemDefaults: { xtype: 'menucheckitem', selectOnFocus: true, width: 125, menu: { layout: 'auto', plain: true } }, /** * @cfg {Date} maxDate * Allowable date as passed to the Ext.DatePicker * Defaults to undefined. */ /** * @cfg {Date} minDate * Allowable date as passed to the Ext.DatePicker * Defaults to undefined. */ applyDateFormat: function(dateFormat) { return dateFormat || Ext.Date.defaultFormat; }, /** * @private * Template method that is to initialize the filter and install required menu items. */ createMenu: function (config) { var me = this, listeners = { scope: me, checkchange: me.onCheckChange }, menuItems = me.menuItems, fields, itemDefaults, pickerCfg, i, len, key, item, cfg, field; me.callParent(arguments); itemDefaults = me.getItemDefaults(); fields = me.getFields(); pickerCfg = Ext.apply({ minDate: me.minDate, maxDate: me.maxDate, format: me.dateFormat, listeners: { scope: me, select: me.onMenuSelect } }, me.getPickerDefaults()); me.fields = {}; for (i = 0, len = menuItems.length; i < len; i++) { key = menuItems[i]; if (key !== '-') { cfg = { menu: { xtype: 'datemenu', hideOnClick: false, pickerCfg: Ext.apply({ itemId: key }, pickerCfg) } }; if (itemDefaults) { Ext.merge(cfg, itemDefaults); } if (fields) { Ext.merge(cfg, fields[key]); } item = me.menu.add(cfg); // Date filter types need the field to be the datepicker in TriFilter.setValue(). field = me.fields[key] = item.down('datepicker'); field.filter = me.filter[key]; field.filterKey = key; item.on(listeners); } else { me.menu.add(key); } } }, /** * Gets the menu picker associated with the passed field * @param {String} item The field identifier ('lt', 'gt', 'eq') * @return {Object} The menu picker */ getPicker: function (item){ return this.fields[item]; }, /** * @private * Remove the filter from the store but don't update its value or the field UI. */ onCheckChange: function (field, checked) { // Only do something if unchecked. If checked, it doesn't mean anything at this point since the column's store filter won't have // any value (i.e., if a user checked this from an unchecked state, the corresponding field won't have a value for its filter). var filter = field.down('datepicker').filter, v; // Only proceed if unchecked AND there's a filter value (i.e., there's something to do!). if (!checked && filter.getValue()) { // Normally we just want to remove the filter from the store, not also to null out the filter value. But, we want to call setValue() // which will take care of unchecking the top-level menu item if it's been determined that Date* doesn't have any filters. v = {}; v[filter.getOperator()] = null; this.setValue(v); } }, onFilterRemove: function (operator) { var v = {}; v[operator] = null; this.setValue(v); this.fields[operator].up('menuitem').setChecked(false, /*suppressEvents*/ true); }, onStateRestore: function(filter) { filter.setSerializer(this.getSerializer()); filter.setConvert(this.convertDateOnly); }, getFilterConfig: function(config, key) { config = this.callParent([config, key]); config.serializer = this.getSerializer(); config.convert = this.convertDateOnly; return config; }, convertDateOnly: function(v) { var result = null; if (v) { result = Ext.Date.clearTime(v, true).getTime(); } return result; }, getSerializer: function() { var me = this; return function(data) { var value = data.value; if (value) { data.value = Ext.Date.format(value, me.getDateFormat()); } }; }, /** * Handler for when the DatePicker for a field fires the 'select' event * @param {Ext.picker.Date} picker * @param {Object} date */ onMenuSelect: function (picker, date) { var me = this, fields = me.fields, filters = me.filter, field = fields[picker.itemId], gt = fields.gt, lt = fields.lt, eq = fields.eq, v = {}; field.up('menuitem').setChecked(true, /*suppressEvents*/ true); if (field === eq) { lt.up('menuitem').setChecked(false, true); gt.up('menuitem').setChecked(false, true); } else { eq.up('menuitem').setChecked(false, true); if (field === gt && (+lt.value < +date)) { lt.up('menuitem').setChecked(false, true); // Null so filter will be removed from store, but only if it currently has a value. // The Trifilter uses the number of removed filters as one of the determinants to determine // whether the gridfilter should be active, so don't push a value in unless it's changed. if (filters.lt.getValue() != null) { v.lt = null; } } else if (field === lt && (+gt.value > +date)) { gt.up('menuitem').setChecked(false, true); // Null so filter will be removed from store, but only if it currently has a value. // The Trifilter uses the number of removed filters as one of the determinants to determine // whether the gridfilter should be active, so don't push a value in unless it's changed. if (filters.gt.getValue() != null) { v.gt = null; } } } v[field.filterKey] = date; me.setValue(v); picker.up('menu').hide(); }});