/** * The dc.js filters are functions which are passed into crossfilter to chose which records will be * accumulated to produce values for the charts. In the crossfilter model, any filters applied on one * dimension will affect all the other dimensions but not that one. dc always applies a filter * function to the dimension; the function combines multiple filters and if any of them accept a * record, it is filtered in. * * These filter constructors are used as appropriate by the various charts to implement brushing. We * mention below which chart uses which filter. In some cases, many instances of a filter will be added. * * Each of the dc.js filters is an object with the following properties: * * `isFiltered` - a function that returns true if a value is within the filter * * `filterType` - a string identifying the filter, here the name of the constructor * * Currently these filter objects are also arrays, but this is not a requirement. Custom filters * can be used as long as they have the properties above. * @namespace filters * @type {{}} */ export const filters = {}; /** * RangedFilter is a filter which accepts keys between `low` and `high`. It is used to implement X * axis brushing for the {@link CoordinateGridMixin coordinate grid charts}. * * Its `filterType` is 'RangedFilter' * @name RangedFilter * @memberof filters * @param {Number} low * @param {Number} high * @returns {Array<Number>} * @constructor */ filters.RangedFilter = function (low, high) { const range = new Array(low, high); range.isFiltered = function (value) { return value >= this[0] && value < this[1]; }; range.filterType = 'RangedFilter'; return range; }; /** * TwoDimensionalFilter is a filter which accepts a single two-dimensional value. It is used by the * {@link HeatMap heat map chart} to include particular cells as they are clicked. (Rows and columns are * filtered by filtering all the cells in the row or column.) * * Its `filterType` is 'TwoDimensionalFilter' * @name TwoDimensionalFilter * @memberof filters * @param {Array<Number>} filter * @returns {Array<Number>} * @constructor */ filters.TwoDimensionalFilter = function (filter) { if (filter === null) { return null; } const f = filter; f.isFiltered = function (value) { return value.length && value.length === f.length && value[0] === f[0] && value[1] === f[1]; }; f.filterType = 'TwoDimensionalFilter'; return f; }; /** * The RangedTwoDimensionalFilter allows filtering all values which fit within a rectangular * region. It is used by the {@link ScatterPlot scatter plot} to implement rectangular brushing. * * It takes two two-dimensional points in the form `[[x1,y1],[x2,y2]]`, and normalizes them so that * `x1 <= x2` and `y1 <= y2`. It then returns a filter which accepts any points which are in the * rectangular range including the lower values but excluding the higher values. * * If an array of two values are given to the RangedTwoDimensionalFilter, it interprets the values as * two x coordinates `x1` and `x2` and returns a filter which accepts any points for which `x1 <= x < * x2`. * * Its `filterType` is 'RangedTwoDimensionalFilter' * @name RangedTwoDimensionalFilter * @memberof filters * @param {Array<Array<Number>>} filter * @returns {Array<Array<Number>>} * @constructor */ filters.RangedTwoDimensionalFilter = function (filter) { if (filter === null) { return null; } const f = filter; let fromBottomLeft; if (f[0] instanceof Array) { fromBottomLeft = [ [Math.min(filter[0][0], filter[1][0]), Math.min(filter[0][1], filter[1][1])], [Math.max(filter[0][0], filter[1][0]), Math.max(filter[0][1], filter[1][1])] ]; } else { fromBottomLeft = [[filter[0], -Infinity], [filter[1], Infinity]]; } f.isFiltered = function (value) { let x, y; if (value instanceof Array) { x = value[0]; y = value[1]; } else { x = value; y = fromBottomLeft[0][1]; } return x >= fromBottomLeft[0][0] && x < fromBottomLeft[1][0] && y >= fromBottomLeft[0][1] && y < fromBottomLeft[1][1]; }; f.filterType = 'RangedTwoDimensionalFilter'; return f; }; // ******** Sunburst Chart ******** /** * HierarchyFilter is a filter which accepts a key path as an array. It matches any node at, or * child of, the given path. It is used by the {@link SunburstChart sunburst chart} to include particular cells and all * their children as they are clicked. * * @name HierarchyFilter * @memberof filters * @param {String} path * @returns {Array<String>} * @constructor */ filters.HierarchyFilter = function (path) { if (path === null) { return null; } const filter = path.slice(0); filter.isFiltered = function (value) { if (!(filter.length && value && value.length && value.length >= filter.length)) { return false; } for (let i = 0; i < filter.length; i++) { if (value[i] !== filter[i]) { return false; } } return true; }; return filter; };