UNPKG

@reactual/handsontable

Version:

Spreadsheet-like data grid editor

253 lines (209 loc) 6 kB
import BasePlugin from './../_base'; import {registerPlugin} from './../../plugins'; import {arrayEach} from './../../helpers/array'; import freezeColumnItem from './contextMenuItem/freezeColumn'; import unfreezeColumnItem from './contextMenuItem/unfreezeColumn'; import './manualColumnFreeze.css'; const privatePool = new WeakMap(); /** * This plugin allows to manually "freeze" and "unfreeze" a column using an entry in the Context Menu. * You can turn it on by setting a `manualColumnFreeze` property to `true`. * * @plugin ManualColumnFreeze * @dependencies ManualColumnMove */ class ManualColumnFreeze extends BasePlugin { constructor(hotInstance) { super(hotInstance); privatePool.set(this, { moveByFreeze: false, afterFirstUse: false, }); /** * Original column positions * * @type {Array} */ this.frozenColumnsBasePositions = []; /** * Reference to the `ManualColumnMove` plugin. */ this.manualColumnMovePlugin = void 0; } /** * Check if the plugin is enabled in the Handsontable settings. * * @returns {Boolean} */ isEnabled() { return !!this.hot.getSettings().manualColumnFreeze; } /** * Enable plugin for this Handsontable instance. */ enablePlugin() { if (this.enabled) { return; } this.addHook('afterContextMenuDefaultOptions', (options) => this.addContextMenuEntry(options)); this.addHook('afterInit', () => this.onAfterInit()); this.addHook('beforeColumnMove', (rows, target) => this.onBeforeColumnMove(rows, target)); super.enablePlugin(); } /** * Disable plugin for this Handsontable instance. */ disablePlugin() { let priv = privatePool.get(this); priv.afterFirstUse = false; priv.moveByFreeze = false; super.disablePlugin(); } /** * Updates the plugin to use the latest options you have specified. */ updatePlugin() { this.disablePlugin(); this.enablePlugin(); super.updatePlugin(); } /** * Freeze the given column (add it to fixed columns). * * @param {Number} column Visual column index. */ freezeColumn(column) { let priv = privatePool.get(this); let settings = this.hot.getSettings(); if (!priv.afterFirstUse) { priv.afterFirstUse = true; } if (settings.fixedColumnsLeft === this.hot.countCols() || column <= settings.fixedColumnsLeft - 1) { return; // already fixed } priv.moveByFreeze = true; if (column !== this.getMovePlugin().columnsMapper.getValueByIndex(column)) { this.frozenColumnsBasePositions[settings.fixedColumnsLeft] = column; } this.getMovePlugin().moveColumn(column, settings.fixedColumnsLeft++); } /** * Unfreeze the given column (remove it from fixed columns and bring to it's previous position). * * @param {Number} column Visual column index. */ unfreezeColumn(column) { let priv = privatePool.get(this); let settings = this.hot.getSettings(); if (!priv.afterFirstUse) { priv.afterFirstUse = true; } if (settings.fixedColumnsLeft <= 0 || (column > settings.fixedColumnsLeft - 1)) { return; // not fixed } let returnCol = this.getBestColumnReturnPosition(column); priv.moveByFreeze = true; settings.fixedColumnsLeft--; this.getMovePlugin().moveColumn(column, returnCol + 1); } /** * Get the reference to the ManualColumnMove plugin. * * @private * @returns {Object} */ getMovePlugin() { if (!this.manualColumnMovePlugin) { this.manualColumnMovePlugin = this.hot.getPlugin('manualColumnMove'); } return this.manualColumnMovePlugin; } /** * Estimates the most fitting return position for unfrozen column. * * @private * @param {Number} column Visual column index. */ getBestColumnReturnPosition(column) { let movePlugin = this.getMovePlugin(); let settings = this.hot.getSettings(); let i = settings.fixedColumnsLeft; let j = movePlugin.columnsMapper.getValueByIndex(i); let initialCol; if (this.frozenColumnsBasePositions[column] == null) { initialCol = movePlugin.columnsMapper.getValueByIndex(column); while (j < initialCol) { i++; j = movePlugin.columnsMapper.getValueByIndex(i); } } else { initialCol = this.frozenColumnsBasePositions[column]; this.frozenColumnsBasePositions[column] = void 0; while (j <= initialCol) { i++; j = movePlugin.columnsMapper.getValueByIndex(i); } i = j; } return i - 1; } /** * Add the manualColumnFreeze context menu entries. * * @private * @param {Object} options Context menu options. */ addContextMenuEntry(options) { options.items.push( {name: '---------'}, freezeColumnItem(this), unfreezeColumnItem(this) ); } /** * Enabling `manualColumnMove` plugin on `afterInit` hook. * * @private */ onAfterInit() { if (!this.getMovePlugin().isEnabled()) { this.getMovePlugin().enablePlugin(); } } /** * Prevent moving the rows from/to fixed area. * * @private * @param {Array} rows * @param {Number} target */ onBeforeColumnMove(rows, target) { let priv = privatePool.get(this); if (priv.afterFirstUse && !priv.moveByFreeze) { let frozenLen = this.hot.getSettings().fixedColumnsLeft; let disallowMoving = target < frozenLen; if (!disallowMoving) { arrayEach(rows, (value, index, array) => { if (value < frozenLen) { disallowMoving = true; return false; } }); } if (disallowMoving) { return false; } } if (priv.moveByFreeze) { priv.moveByFreeze = false; } } /** * Destroy plugin instance. */ destroy() { super.destroy(); } } registerPlugin('manualColumnFreeze', ManualColumnFreeze); export default ManualColumnFreeze;