UNPKG

handsontable

Version:

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

292 lines (278 loc) • 10.9 kB
import "core-js/modules/es.error.cause.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 { APPEND_COLUMN_CONFIG_STRATEGY, ColumnSorting } from "../columnSorting/index.mjs"; import { registerRootComparator } from "../columnSorting/sortService/index.mjs"; import { wasHeaderClickedProperly } from "../columnSorting/utils.mjs"; import { addClass, removeClass } from "../../helpers/dom/element.mjs"; import { rootComparator } from "./rootComparator.mjs"; import { getClassesToAdd, getClassesToRemove } from "./domHelpers.mjs"; import { EDITOR_EDIT_GROUP as SHORTCUTS_GROUP_EDITOR } from "../../shortcutContexts/index.mjs"; export const PLUGIN_KEY = 'multiColumnSorting'; export const PLUGIN_PRIORITY = 170; const SHORTCUTS_GROUP = PLUGIN_KEY; registerRootComparator(PLUGIN_KEY, rootComparator); /** * @plugin MultiColumnSorting * @class MultiColumnSorting * * @description * This plugin sorts the view by columns (but does not sort the data source!). To enable the plugin, set the * {@link Options#multiColumnSorting} property to the correct value (see the examples below). * * @example * ```js * // as boolean * multiColumnSorting: true * * // as an object with initial sort config (sort ascending for column at index 1 and then sort descending for column at index 0) * multiColumnSorting: { * initialConfig: [{ * column: 1, * sortOrder: 'asc' * }, { * column: 0, * sortOrder: 'desc' * }] * } * * // as an object which define specific sorting options for all columns * multiColumnSorting: { * sortEmptyCells: true, // true = the table sorts empty cells, false = the table moves all empty cells to the end of the table (by default) * indicator: true, // true = shows indicator for all columns (by default), false = don't show indicator for columns * headerAction: true, // true = allow to click on the headers to sort (by default), false = turn off possibility to click on the headers to sort * compareFunctionFactory: function(sortOrder, columnMeta) { * return function(value, nextValue) { * // Some value comparisons which will return -1, 0 or 1... * } * } * } * * // as an object passed to the `column` property, allows specifying a custom options for the desired column. * // please take a look at documentation of `column` property: {@link Options#columns} * columns: [{ * multiColumnSorting: { * indicator: false, // disable indicator for the first column, * sortEmptyCells: true, * headerAction: false, // clicks on the first column won't sort * compareFunctionFactory: function(sortOrder, columnMeta) { * return function(value, nextValue) { * return 0; // Custom compare function for the first column (don't sort) * } * } * } * }] * ``` */ export class MultiColumnSorting extends ColumnSorting { constructor() { super(...arguments); /** * Main settings key designed for the plugin. * * @private * @type {string} */ _defineProperty(this, "pluginKey", PLUGIN_KEY); } static get PLUGIN_KEY() { return PLUGIN_KEY; } static get PLUGIN_PRIORITY() { return PLUGIN_PRIORITY; } /** * Checks if the plugin is enabled in the Handsontable settings. This method is executed in {@link Hooks#beforeInit} * hook and if it returns `true` then the {@link MultiColumnSorting#enablePlugin} method is called. * * @returns {boolean} */ isEnabled() { return !!this.hot.getSettings()[this.pluginKey]; } /** * Enables the plugin functionality for this Handsontable instance. */ enablePlugin() { super.enablePlugin(); } /** * Disables the plugin functionality for this Handsontable instance. */ disablePlugin() { super.disablePlugin(); } /** * Register shortcuts responsible for toggling column sorting functionality. * * @private */ registerShortcuts() { super.registerShortcuts(); this.hot.getShortcutManager().getContext('grid').addShortcut({ keys: [['Shift', 'Enter']], callback: () => { const { highlight } = this.hot.getSelectedRangeActive(); if (highlight.row === -1 && highlight.col >= 0) { this.sort(this.getNextSortConfig(highlight.col, APPEND_COLUMN_CONFIG_STRATEGY)); } // prevent default Enter behavior (move to the next row within a selection range) return false; }, runOnlyIf: () => { var _this$hot$getSelected, _this$hot$getSelected2; const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeActive()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight; return highlight && ((_this$hot$getSelected2 = this.hot.getSelectedRangeActive()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.isSingle()) && this.hot.selection.isCellVisible(highlight) && highlight.isHeader(); }, relativeToGroup: SHORTCUTS_GROUP_EDITOR, position: 'before', group: SHORTCUTS_GROUP }); } /** * Unregister shortcuts responsible for toggling column sorting functionality. * * @private */ unregisterShortcuts() { super.unregisterShortcuts(); this.hot.getShortcutManager().getContext('grid').removeShortcutsByGroup(SHORTCUTS_GROUP); } /** * Sorts the table by chosen columns and orders. * * @param {undefined|object|Array} sortConfig Single column sort configuration or full sort configuration (for all sorted columns). * The configuration object contains `column` and `sortOrder` properties. First of them contains visual column index, the second one contains * sort order (`asc` for ascending, `desc` for descending). * * **Note**: Please keep in mind that every call of `sort` function set an entirely new sort order. Previous sort configs aren't preserved. * * @example * ```js * // sort ascending first visual column * hot.getPlugin('multiColumnSorting').sort({ column: 0, sortOrder: 'asc' }); * * // sort first two visual column in the defined sequence * hot.getPlugin('multiColumnSorting').sort([{ * column: 1, sortOrder: 'asc' * }, { * column: 0, sortOrder: 'desc' * }]); * ``` * * @fires Hooks#beforeColumnSort * @fires Hooks#afterColumnSort */ sort(sortConfig) { super.sort(sortConfig); } /** * Clear the sort performed on the table. */ clearSort() { super.clearSort(); } /** * Checks if the table is sorted (any column have to be sorted). * * @returns {boolean} */ isSorted() { return super.isSorted(); } /** * Get sort configuration for particular column or for all sorted columns. Objects contain `column` and `sortOrder` properties. * * **Note**: Please keep in mind that returned objects expose **visual** column index under the `column` key. They are handled by the `sort` function. * * @param {number} [column] Visual column index. * @returns {undefined|object|Array} */ getSortConfig(column) { return super.getSortConfig(column); } /** * @description * Warn: Useful mainly for providing server side sort implementation (see in the example below). It doesn't sort the data set. It just sets sort configuration for all sorted columns. * Note: Please keep in mind that this method doesn't re-render the table. * * @example * ```js * beforeColumnSort: function(currentSortConfig, destinationSortConfigs) { * const columnSortPlugin = this.getPlugin('multiColumnSorting'); * * columnSortPlugin.setSortConfig(destinationSortConfigs); * * // const newData = ... // Calculated data set, ie. from an AJAX call. * * this.loadData(newData); // Load new data set and re-render the table. * * return false; // The blockade for the default sort action. * } * ``` * * @param {undefined|object|Array} sortConfig Single column sort configuration or full sort configuration (for all sorted columns). * The configuration object contains `column` and `sortOrder` properties. First of them contains visual column index, the second one contains * sort order (`asc` for ascending, `desc` for descending). */ setSortConfig(sortConfig) { super.setSortConfig(sortConfig); } /** * Get normalized sort configs. * * @private * @param {object|Array} [sortConfig=[]] Single column sort configuration or full sort configuration (for all sorted columns). * The configuration object contains `column` and `sortOrder` properties. First of them contains visual column index, the second one contains * sort order (`asc` for ascending, `desc` for descending). * @returns {Array} */ getNormalizedSortConfigs() { let sortConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; if (Array.isArray(sortConfig)) { return sortConfig; } return [sortConfig]; } /** * Update header classes. * * @private * @param {HTMLElement} headerSpanElement Header span element. * @param {...*} args Extra arguments for helpers. */ updateHeaderClasses(headerSpanElement) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } super.updateHeaderClasses(headerSpanElement, ...args); removeClass(headerSpanElement, getClassesToRemove(headerSpanElement)); if (this.enabled !== false) { addClass(headerSpanElement, getClassesToAdd(...args)); } } /** * Callback for the `onAfterOnCellMouseDown` hook. * * @private * @param {Event} event Event which are provided by hook. * @param {CellCoords} coords Visual coords of the selected cell. */ onAfterOnCellMouseDown(event, coords) { if (wasHeaderClickedProperly(coords.row, coords.col, event) === false) { return; } if (this.wasClickableHeaderClicked(event, coords.col)) { if (this.hot.getShortcutManager().isCtrlPressed()) { this.hot.deselectCell(); this.hot.selectColumns(coords.col); this.sort(this.getNextSortConfig(coords.col, APPEND_COLUMN_CONFIG_STRATEGY)); } else { this.sort(this.getColumnNextConfig(coords.col)); } } } }