    /** * Base implementation of a filter. It handles common type of filters. */Ext.define('Ext.pivot.filter.Base', {    alternateClassName: [        'Mz.aggregate.filter.Abstract'    ],     alias: 'pivotfilter.base',     mixins: [        'Ext.mixin.Factoryable'    ],     /**     * @cfg {String} [type=abstract]     *     * Used when you define a filter on a dimension to set what kind of filter is to be     * instantiated.     */     /**     * @cfg {String} operator (required)     *     * Operator to use to compare labels/values to this Filter's {@link #value}.     *     * The `between` and `not between` operators expect this filter's {@link #value} to be an array with two values.     *     * Possible values are:     *     *    * `<`     *    * `<=`     *    * `=`     *    * `>=`     *    * `>`     *    * `!=`     *    * `between`     *    * `not between`     */    operator:       null,     /**     * @cfg {String/Array} value (required)     *     * Value to filter by. For 'between' and 'not between' operators this should be an array of values.     */    value:          null,     /**     * @cfg {Boolean} [caseSensitive=true]     *     * During filtering should we use case sensitive comparison?     *     */    caseSensitive:  true,     /**     * @property {Ext.pivot.dimension.Item} parent Reference to the parent dimension object.     * @readonly     *     * @private     */    parent:         null,     isFilter:       true,     constructor: function(config){        var me = this,            fmt = Ext.util.Format;         // define thousand and decimal separator regexp         me.thousandRe = new RegExp('[' + fmt.thousandSeparator + ']', 'g');        me.decimalRe = new RegExp('[' + fmt.decimalSeparator + ']');         Ext.apply(this, config);        return this.callParent([config]);    },     destroy: function(){        var me = this;         me.parent = me.thousandRe = me.decimalRe = null;        me.callParent();    },        /**     * Returns the serialized filter data as an object.     *     * @returns {Object}     */    serialize: function(){        var me = this;                return Ext.apply({            type:           me.type,            operator:       me.operator,            value:          me.value,            caseSensitive:  me.caseSensitive        }, me.getSerialArgs() || {});    },        /**     * @method     * Template method to be implemented by all subclasses that is used to     * get and return serialized filter data.     *     * Defaults to Ext.emptyFn.     *     */    getSerialArgs: Ext.emptyFn,        /**     * Check if the specified value matches the filter.     *     * @returns Boolean True if the value matches the filter     * @param value     *     */    isMatch: function(value){        var me = this,            v = me.value,            ret, retFrom, retTo, from, to;         v = (Ext.isArray(v) ? v[0] : v) || '';        ret = me.compare(value, v);         if(me.operator == '='){            return (ret === 0);        }         if(me.operator == '!='){            return (ret !== 0);        }         if(me.operator == '>'){            return (ret > 0);        }         if(me.operator == '>='){            return (ret >= 0);        }         if(me.operator == '<'){            return (ret < 0);        }         if(me.operator == '<='){            return (ret <= 0);        }         v = me.value;        from = (Ext.isArray(v) ? v[0] : v) || '';        to = (Ext.isArray(v) ? v[1] : v) || '';        retFrom = me.compare(value, from);        retTo = me.compare(value, to);         if(me.operator == 'between'){            return (retFrom >= 0 && retTo <= 0);        }         if(me.operator == 'not between'){            return !(retFrom >= 0 && retTo <= 0);        }         // no valid operator was specified. ignore filtering         return true;    },     /**     * Check if the specified value is a number and returns it.     *     * Takes care of the regional settings (decimal and thousand separators).     *     * @param value     * @return {Number} Returns the number or null if the value is not numeric     * @private     */    parseNumber: function(value){        var v;         if(typeof value === 'number'){            return value;        }         if(Ext.isEmpty(value)){            value = '';        }         // if the value comes as a string it may be a number formatted using locale settings         // which means that we need to convert it to a number with `.` decimal separator.         v = String(value).replace(this.thousandRe, '');        v = v.replace(this.decimalRe, '.');         if(Ext.isNumeric(v)){            return parseFloat(v);        }        return null;    },     /**     * Compare 2 values and return the result.     *     * @param a     * @param b     * @private     */    compare: function(a, b){        var sorter = Ext.pivot.matrix.Base.prototype.naturalSort,            v1 = this.parseNumber(a),            v2 = this.parseNumber(b);         if(Ext.isNumber(v1) && Ext.isNumber(v2)){            return sorter(v1, v2);        }         if( Ext.isDate(a) ){            if(Ext.isDate(b)){                return sorter(a, b);            }else{                return sorter(a, Ext.Date.parse(b, Ext.Date.defaultFormat));            }        }         return (this.caseSensitive ? sorter(a || '', b || '') : sorter(String(a || '').toLowerCase(), String(b || '').toLowerCase()));     },     deprecated: {        '6.0': {            properties: {                /**                 * @cfg {String} mztype                  *                 * @deprecated 6.0 Use {@link #type} instead. The old type config was renamed to {@link #operator}.                 */                mztype: null,                /**                 * @cfg {String} from                  * @deprecated 6.0 Use {@link #value} instead as an array with 2 values.                 *                 * Used in case of a 'between/not between' type of filter                 *                 */                from: null,                /**                 * @cfg {String} to                  * @deprecated 6.0 Use {@link #value} instead as an array with 2 values.                 *                 * Used in case of a 'between/not between' operator                 *                 */                to: null            }        }    }});