handsontable
Version:
Handsontable is a JavaScript Data Grid available for React, Angular and Vue.
240 lines (230 loc) • 8.4 kB
JavaScript
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.filter.js";
function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
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); }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
import { addClass } from "../../../helpers/dom/element.mjs";
import { stopImmediatePropagation } from "../../../helpers/dom/event.mjs";
import { arrayEach } from "../../../helpers/array.mjs";
import { isKey } from "../../../helpers/unicode.mjs";
import { clone } from "../../../helpers/object.mjs";
import * as C from "../../../i18n/constants.mjs";
import { BaseComponent } from "./_base.mjs";
import getOptionsList, { CONDITION_NONE } from "../constants.mjs";
import { InputUI } from "../ui/input.mjs";
import { SelectUI } from "../ui/select.mjs";
import { getConditionDescriptor } from "../conditionRegisterer.mjs";
/**
* @private
* @class ConditionComponent
*/
var _ConditionComponent_brand = /*#__PURE__*/new WeakSet();
export class ConditionComponent extends BaseComponent {
constructor(hotInstance, options) {
super(hotInstance, {
id: options.id,
stateless: false
});
/**
* On condition select listener.
*
* @param {object} command Menu item object (command).
*/
_classPrivateMethodInitSpec(this, _ConditionComponent_brand);
/**
* The name of the component.
*
* @type {string}
*/
_defineProperty(this, "name", '');
/**
* @type {boolean}
*/
_defineProperty(this, "addSeparator", false);
this.name = options.name;
this.addSeparator = options.addSeparator;
this.elements.push(new SelectUI(this.hot, {
menuContainer: options.menuContainer
}));
this.elements.push(new InputUI(this.hot, {
placeholder: C.FILTERS_BUTTONS_PLACEHOLDER_VALUE
}));
this.elements.push(new InputUI(this.hot, {
placeholder: C.FILTERS_BUTTONS_PLACEHOLDER_SECOND_VALUE
}));
this.registerHooks();
}
/**
* Register all necessary hooks.
*
* @private
*/
registerHooks() {
this.getSelectElement().addLocalHook('select', command => _assertClassBrand(_ConditionComponent_brand, this, _onConditionSelect).call(this, command)).addLocalHook('afterClose', () => this.runLocalHooks('afterClose')).addLocalHook('tabKeydown', event => this.runLocalHooks('selectTabKeydown', event));
arrayEach(this.getInputElements(), input => {
input.addLocalHook('keydown', event => _assertClassBrand(_ConditionComponent_brand, this, _onInputKeyDown).call(this, event));
});
}
/**
* Set state of the component.
*
* @param {object} value State to restore.
*/
setState(value) {
this.reset();
if (!value) {
return;
}
const copyOfCommand = clone(value.command);
if (copyOfCommand.name.startsWith(C.FILTERS_CONDITIONS_NAMESPACE)) {
copyOfCommand.name = this.hot.getTranslatedPhrase(copyOfCommand.name);
}
this.getSelectElement().setValue(copyOfCommand);
arrayEach(value.args, (arg, index) => {
if (index > copyOfCommand.inputsCount - 1) {
return false;
}
const element = this.getInputElement(index);
element.setValue(arg);
element[copyOfCommand.inputsCount > index ? 'show' : 'hide']();
if (!index) {
this.hot._registerTimeout(() => element.focus(), 10);
}
});
}
/**
* Export state of the component (get selected filter and filter arguments).
*
* @returns {object} Returns object where `command` key keeps used condition filter and `args` key its arguments.
*/
getState() {
const command = this.getSelectElement().getValue() || getConditionDescriptor(CONDITION_NONE);
const args = [];
arrayEach(this.getInputElements(), (element, index) => {
if (command.inputsCount > index) {
args.push(element.getValue());
}
});
return {
command,
args
};
}
/**
* Update state of component.
*
* @param {object} condition The condition object.
* @param {object} condition.command The command object with condition name as `key` property.
* @param {Array} condition.args An array of values to compare.
* @param {number} column Physical column index.
*/
updateState(condition, column) {
const command = condition ? getConditionDescriptor(condition.name) : getConditionDescriptor(CONDITION_NONE);
this.state.setValueAtIndex(column, {
command,
args: condition ? condition.args : []
});
if (!condition) {
arrayEach(this.getInputElements(), element => element.setValue(null));
}
}
/**
* Get select element.
*
* @returns {SelectUI}
*/
getSelectElement() {
return this.elements.filter(element => element instanceof SelectUI)[0];
}
/**
* Get input element.
*
* @param {number} index Index an array of elements.
* @returns {InputUI}
*/
getInputElement() {
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
return this.getInputElements()[index];
}
/**
* Get input elements.
*
* @returns {Array}
*/
getInputElements() {
return this.elements.filter(element => element instanceof InputUI);
}
/**
* Get menu object descriptor.
*
* @returns {object}
*/
getMenuItemDescriptor() {
return {
key: this.id,
name: this.name,
isCommand: false,
disableSelection: true,
hidden: () => this.isHidden(),
renderer: (hot, wrapper, row, col, prop, value) => {
addClass(wrapper.parentNode, 'htFiltersMenuCondition');
if (this.addSeparator) {
addClass(wrapper.parentNode, 'border');
}
const label = this.hot.rootDocument.createElement('div');
addClass(label, 'htFiltersMenuLabel');
label.textContent = value;
wrapper.appendChild(label);
// The SelectUI should not extend the menu width (it should adjust to the menu item width only).
// That's why it's skipped from rendering when the GhostTable tries to render it.
if (!wrapper.parentElement.hasAttribute('ghost-table')) {
arrayEach(this.elements, ui => wrapper.appendChild(ui.element));
}
return wrapper;
}
};
}
/**
* Reset elements to their initial state.
*/
reset() {
const selectedColumn = this.hot.getPlugin('filters').getSelectedColumn();
let items = [getConditionDescriptor(CONDITION_NONE)];
if (selectedColumn !== null) {
const {
visualIndex
} = selectedColumn;
items = getOptionsList(this.hot.getDataType(0, visualIndex, this.hot.countRows(), visualIndex));
}
arrayEach(this.getInputElements(), element => element.hide());
this.getSelectElement().setItems(items);
super.reset();
// Select element as default 'None'
this.getSelectElement().setValue(items[0]);
}
}
function _onConditionSelect(command) {
arrayEach(this.getInputElements(), (element, index) => {
element[command.inputsCount > index ? 'show' : 'hide']();
if (index === 0) {
this.hot._registerTimeout(() => element.focus(), 10);
}
});
this.runLocalHooks('change', command);
}
/**
* Key down listener.
*
* @param {Event} event The DOM event object.
*/
function _onInputKeyDown(event) {
if (isKey(event.keyCode, 'ESCAPE')) {
this.runLocalHooks('cancel');
stopImmediatePropagation(event);
}
}