UNPKG

handsontable

Version:

Handsontable is a JavaScript Data Grid available for React, Angular and Vue.

289 lines (274 loc) • 10.6 kB
import "core-js/modules/es.error.cause.js"; import "core-js/modules/es.array.push.js"; import "core-js/modules/esnext.iterator.constructor.js"; import "core-js/modules/esnext.iterator.for-each.js"; import "core-js/modules/esnext.iterator.map.js"; import "core-js/modules/esnext.iterator.reduce.js"; import "core-js/modules/esnext.iterator.some.js"; function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } import { mixin } from "../../helpers/object.mjs"; import { toSingleLine } from "../../helpers/templateLiteralTag.mjs"; import localHooks from "../../mixins/localHooks.mjs"; import { getCondition } from "./conditionRegisterer.mjs"; import { OPERATION_ID as OPERATION_AND } from "./logicalOperations/conjunction.mjs"; import { operations, getOperationFunc } from "./logicalOperationRegisterer.mjs"; import { isUndefined } from "../../helpers/mixed.mjs"; import { LinkedPhysicalIndexToValueMap as IndexToValueMap } from "../../translations/index.mjs"; const MAP_NAME = 'ConditionCollection.filteringStates'; /** * @private * @class ConditionCollection */ class ConditionCollection { constructor(hot) { let isMapRegistrable = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; /** * Handsontable instance. * * @type {Core} */ _defineProperty(this, "hot", void 0); /** * Indicates whether the internal IndexMap should be registered or not. Generally, * registered Maps responds to the index changes. Within that collection, sometimes * this is not necessary. * * @type {boolean} */ _defineProperty(this, "isMapRegistrable", void 0); /** * Index map storing filtering states for every column. ConditionCollection write and read to/from element. * * @type {LinkedPhysicalIndexToValueMap} */ _defineProperty(this, "filteringStates", new IndexToValueMap()); this.hot = hot; this.isMapRegistrable = isMapRegistrable; if (this.isMapRegistrable === true) { this.hot.columnIndexMapper.registerMap(MAP_NAME, this.filteringStates); } else { this.filteringStates.init(this.hot.columnIndexMapper.getNumberOfIndexes()); } } /** * Check if condition collection is empty (so no needed to filter data). * * @returns {boolean} */ isEmpty() { return this.getFilteredColumns().length === 0; } /** * Check if value is matched to the criteria of conditions chain. * * @param {object} value Object with `value` and `meta` keys. * @param {number} column The physical column index. * @returns {boolean} */ isMatch(value, column) { var _stateForColumn$condi; const stateForColumn = this.filteringStates.getValueAtIndex(column); const conditions = (_stateForColumn$condi = stateForColumn === null || stateForColumn === void 0 ? void 0 : stateForColumn.conditions) !== null && _stateForColumn$condi !== void 0 ? _stateForColumn$condi : []; const operation = stateForColumn === null || stateForColumn === void 0 ? void 0 : stateForColumn.operation; return this.isMatchInConditions(conditions, value, operation); } /** * Check if the value is matches the conditions. * * @param {Array} conditions List of conditions. * @param {object} value Object with `value` and `meta` keys. * @param {string} [operationType='conjunction'] Type of conditions operation. * @returns {boolean} */ isMatchInConditions(conditions, value) { let operationType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : OPERATION_AND; if (conditions.length) { return getOperationFunc(operationType)(conditions, value); } return true; } /** * Add condition to the collection. * * @param {number} column The physical column index. * @param {object} conditionDefinition Object with keys: * * `command` Object, Command object with condition name as `key` property. * * `args` Array, Condition arguments. * @param {string} [operation='conjunction'] Type of conditions operation. * @param {number} [position] Position to which condition will be added. When argument is undefined * the condition will be processed as the last condition. * @fires ConditionCollection#beforeAdd * @fires ConditionCollection#afterAdd */ addCondition(column, conditionDefinition) { let operation = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : OPERATION_AND; let position = arguments.length > 3 ? arguments[3] : undefined; const localeForColumn = this.hot.getCellMeta(0, column).locale; const args = conditionDefinition.args.map(v => typeof v === 'string' ? v.toLocaleLowerCase(localeForColumn) : v); const name = conditionDefinition.name || conditionDefinition.command.key; this.runLocalHooks('beforeAdd', column); const columnType = this.getOperation(column); if (columnType) { if (columnType !== operation) { throw Error(toSingleLine`The column of index ${column} has been already applied with a \`${columnType}\`\x20 filter operation. Use \`removeConditions\` to clear the current conditions and then add new ones.\x20 Mind that you cannot mix different types of operations (for instance, if you use \`conjunction\`,\x20 use it consequently for a particular column).`); } } else if (isUndefined(operations[operation])) { throw new Error(toSingleLine`Unexpected operation named \`${operation}\`. Possible ones are\x20 \`disjunction\` and \`conjunction\`.`); } const conditionsForColumn = this.getConditions(column); if (conditionsForColumn.length === 0) { // Create first condition for particular column. this.filteringStates.setValueAtIndex(column, { operation, conditions: [{ name, args, func: getCondition(name, args) }] }, position); } else { // Add next condition for particular column (by reference). conditionsForColumn.push({ name, args, func: getCondition(name, args) }); } this.runLocalHooks('afterAdd', column); } /** * Get all added conditions from the collection at specified column index. * * @param {number} column The physical column index. * @returns {Array} Returns conditions collection as an array. */ getConditions(column) { var _this$filteringStates, _this$filteringStates2; return (_this$filteringStates = (_this$filteringStates2 = this.filteringStates.getValueAtIndex(column)) === null || _this$filteringStates2 === void 0 ? void 0 : _this$filteringStates2.conditions) !== null && _this$filteringStates !== void 0 ? _this$filteringStates : []; } /** * Get operation for particular column. * * @param {number} column The physical column index. * @returns {string|undefined} */ getOperation(column) { var _this$filteringStates3; return (_this$filteringStates3 = this.filteringStates.getValueAtIndex(column)) === null || _this$filteringStates3 === void 0 ? void 0 : _this$filteringStates3.operation; } /** * Get all filtered physical columns in the order in which actions are performed. * * @returns {Array} */ getFilteredColumns() { return this.filteringStates.getEntries().map(_ref => { let [physicalColumn] = _ref; return physicalColumn; }); } /** * Gets position in the filtering states stack for the specific column. * * @param {number} column The physical column index. * @returns {number} Returns -1 when the column doesn't exist in the stack. */ getColumnStackPosition(column) { return this.getFilteredColumns().indexOf(column); } /** * Export all previously added conditions. * * @returns {Array} */ exportAllConditions() { return this.filteringStates.getEntries().reduce((allConditions, _ref2) => { let [column, { operation, conditions }] = _ref2; allConditions.push({ column, operation, conditions: conditions.map(_ref3 => { let { name, args } = _ref3; return { name, args: [...args] }; }) }); return allConditions; }, []); } /** * Import conditions to the collection. * * @param {Array} conditions The collection of the conditions. */ importAllConditions(conditions) { this.clean(); conditions.forEach(stack => { stack.conditions.forEach(condition => this.addCondition(stack.column, condition)); }); } /** * Remove conditions at given column index. * * @param {number} column The physical column index. * @fires ConditionCollection#beforeRemove * @fires ConditionCollection#afterRemove */ removeConditions(column) { this.runLocalHooks('beforeRemove', column); this.filteringStates.clearValue(column); this.runLocalHooks('afterRemove', column); } /** * Clean all conditions collection and reset order stack. * * @fires ConditionCollection#beforeClean * @fires ConditionCollection#afterClean */ clean() { this.runLocalHooks('beforeClean'); this.filteringStates.clear(); this.runLocalHooks('afterClean'); } /** * Check if at least one condition was added at specified column index. And if second parameter is passed then additionally * check if condition exists under its name. * * @param {number} column The physical column index. * @param {string} [name] Condition name. * @returns {boolean} */ hasConditions(column, name) { const conditions = this.getConditions(column); if (name) { return conditions.some(condition => condition.name === name); } return conditions.length > 0; } /** * Destroy object. */ destroy() { if (this.isMapRegistrable) { this.hot.columnIndexMapper.unregisterMap(MAP_NAME); } this.filteringStates = null; this.clearLocalHooks(); } } mixin(ConditionCollection, localHooks); export default ConditionCollection;