673 lines
23 KiB
JavaScript
673 lines
23 KiB
JavaScript
"use strict";
|
||
|
||
exports.__esModule = true;
|
||
require("core-js/modules/es.array.push.js");
|
||
var _base = require("../base");
|
||
var _pluginHooks = _interopRequireDefault(require("../../pluginHooks"));
|
||
var _array = require("../../helpers/array");
|
||
var _element = require("../../helpers/dom/element");
|
||
var _number = require("../../helpers/number");
|
||
var _eventManager = _interopRequireDefault(require("../../eventManager"));
|
||
var _backlight = _interopRequireDefault(require("./ui/backlight"));
|
||
var _guideline = _interopRequireDefault(require("./ui/guideline"));
|
||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
_pluginHooks.default.getSingleton().register('beforeRowMove');
|
||
_pluginHooks.default.getSingleton().register('afterRowMove');
|
||
const PLUGIN_KEY = 'manualRowMove';
|
||
exports.PLUGIN_KEY = PLUGIN_KEY;
|
||
const PLUGIN_PRIORITY = 140;
|
||
exports.PLUGIN_PRIORITY = PLUGIN_PRIORITY;
|
||
const privatePool = new WeakMap();
|
||
const CSS_PLUGIN = 'ht__manualRowMove';
|
||
const CSS_SHOW_UI = 'show-ui';
|
||
const CSS_ON_MOVING = 'on-moving--rows';
|
||
const CSS_AFTER_SELECTION = 'after-selection--rows';
|
||
|
||
/* eslint-disable jsdoc/require-description-complete-sentence */
|
||
|
||
/**
|
||
* @plugin ManualRowMove
|
||
* @class ManualRowMove
|
||
*
|
||
* @description
|
||
* This plugin allows to change rows order. To make rows order persistent the {@link Options#persistentState}
|
||
* plugin should be enabled.
|
||
*
|
||
* API:
|
||
* - `moveRow` - move single row to the new position.
|
||
* - `moveRows` - move many rows (as an array of indexes) to the new position.
|
||
* - `dragRow` - drag single row to the new position.
|
||
* - `dragRows` - drag many rows (as an array of indexes) to the new position.
|
||
*
|
||
* [Documentation](@/guides/rows/row-moving.md) explain differences between drag and move actions. Please keep in mind that if you want apply visual changes,
|
||
* you have to call manually the `render` method on the instance of Handsontable.
|
||
*
|
||
* The plugin creates additional components to make moving possibly using user interface:
|
||
* - backlight - highlight of selected rows.
|
||
* - guideline - line which shows where rows has been moved.
|
||
*
|
||
* @class ManualRowMove
|
||
* @plugin ManualRowMove
|
||
*/
|
||
class ManualRowMove extends _base.BasePlugin {
|
||
static get PLUGIN_KEY() {
|
||
return PLUGIN_KEY;
|
||
}
|
||
static get PLUGIN_PRIORITY() {
|
||
return PLUGIN_PRIORITY;
|
||
}
|
||
constructor(hotInstance) {
|
||
super(hotInstance);
|
||
|
||
/**
|
||
* Set up WeakMap of plugin to sharing private parameters;.
|
||
*/
|
||
privatePool.set(this, {
|
||
rowsToMove: [],
|
||
pressed: void 0,
|
||
target: {
|
||
eventPageY: void 0,
|
||
coords: void 0,
|
||
TD: void 0,
|
||
row: void 0
|
||
},
|
||
cachedDropIndex: void 0
|
||
});
|
||
|
||
/**
|
||
* Event Manager object.
|
||
*
|
||
* @private
|
||
* @type {object}
|
||
*/
|
||
this.eventManager = new _eventManager.default(this);
|
||
/**
|
||
* Backlight UI object.
|
||
*
|
||
* @private
|
||
* @type {object}
|
||
*/
|
||
this.backlight = new _backlight.default(hotInstance);
|
||
/**
|
||
* Guideline UI object.
|
||
*
|
||
* @private
|
||
* @type {object}
|
||
*/
|
||
this.guideline = new _guideline.default(hotInstance);
|
||
}
|
||
|
||
/**
|
||
* 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 ManualRowMove#enablePlugin} method is called.
|
||
*
|
||
* @returns {boolean}
|
||
*/
|
||
isEnabled() {
|
||
return !!this.hot.getSettings()[PLUGIN_KEY];
|
||
}
|
||
|
||
/**
|
||
* Enables the plugin functionality for this Handsontable instance.
|
||
*/
|
||
enablePlugin() {
|
||
var _this = this;
|
||
if (this.enabled) {
|
||
return;
|
||
}
|
||
this.addHook('beforeOnCellMouseDown', function () {
|
||
return _this.onBeforeOnCellMouseDown(...arguments);
|
||
});
|
||
this.addHook('beforeOnCellMouseOver', function () {
|
||
return _this.onBeforeOnCellMouseOver(...arguments);
|
||
});
|
||
this.addHook('afterScrollHorizontally', () => this.onAfterScrollHorizontally());
|
||
this.addHook('afterLoadData', function () {
|
||
return _this.onAfterLoadData(...arguments);
|
||
});
|
||
this.buildPluginUI();
|
||
this.registerEvents();
|
||
|
||
// TODO: move adding plugin classname to BasePlugin.
|
||
(0, _element.addClass)(this.hot.rootElement, CSS_PLUGIN);
|
||
super.enablePlugin();
|
||
}
|
||
|
||
/**
|
||
* Updates the plugin's state.
|
||
*
|
||
* This method is executed when [`updateSettings()`](@/api/core.md#updatesettings) is invoked with any of the following configuration options:
|
||
* - [`manualRowMove`](@/api/options.md#manualrowmove)
|
||
*/
|
||
updatePlugin() {
|
||
this.disablePlugin();
|
||
this.enablePlugin();
|
||
this.moveBySettingsOrLoad();
|
||
super.updatePlugin();
|
||
}
|
||
|
||
/**
|
||
* Disables the plugin functionality for this Handsontable instance.
|
||
*/
|
||
disablePlugin() {
|
||
(0, _element.removeClass)(this.hot.rootElement, CSS_PLUGIN);
|
||
this.unregisterEvents();
|
||
this.backlight.destroy();
|
||
this.guideline.destroy();
|
||
super.disablePlugin();
|
||
}
|
||
|
||
/**
|
||
* Moves a single row.
|
||
*
|
||
* To see the outcome, rerender your grid by calling [`render()`](@/api/core.md#render).
|
||
*
|
||
* @param {number} row Visual row index to be moved.
|
||
* @param {number} finalIndex Visual row index, being a start index for the moved rows. Points to where the elements will be placed after the moving action.
|
||
* To check the visualization of the final index, please take a look at [documentation](@/guides/rows/row-moving.md#drag-and-move-actions-of-manualrowmove-plugin).
|
||
* @fires Hooks#beforeRowMove
|
||
* @fires Hooks#afterRowMove
|
||
* @returns {boolean}
|
||
*/
|
||
moveRow(row, finalIndex) {
|
||
return this.moveRows([row], finalIndex);
|
||
}
|
||
|
||
/**
|
||
* Moves multiple rows.
|
||
*
|
||
* To see the outcome, rerender your grid by calling [`render()`](@/api/core.md#render).
|
||
*
|
||
* @param {Array} rows Array of visual row indexes to be moved.
|
||
* @param {number} finalIndex Visual row index, being a start index for the moved rows. Points to where the elements will be placed after the moving action.
|
||
* To check the visualization of the final index, please take a look at [documentation](@/guides/rows/row-moving.md#drag-and-move-actions-of-manualrowmove-plugin).
|
||
* @fires Hooks#beforeRowMove
|
||
* @fires Hooks#afterRowMove
|
||
* @returns {boolean}
|
||
*/
|
||
moveRows(rows, finalIndex) {
|
||
const priv = privatePool.get(this);
|
||
const dropIndex = priv.cachedDropIndex;
|
||
const movePossible = this.isMovePossible(rows, finalIndex);
|
||
const beforeMoveHook = this.hot.runHooks('beforeRowMove', rows, finalIndex, dropIndex, movePossible);
|
||
priv.cachedDropIndex = void 0;
|
||
if (beforeMoveHook === false) {
|
||
return;
|
||
}
|
||
if (movePossible) {
|
||
this.hot.rowIndexMapper.moveIndexes(rows, finalIndex);
|
||
}
|
||
const movePerformed = movePossible && this.isRowOrderChanged(rows, finalIndex);
|
||
this.hot.runHooks('afterRowMove', rows, finalIndex, dropIndex, movePossible, movePerformed);
|
||
return movePerformed;
|
||
}
|
||
|
||
/**
|
||
* Drag a single row to drop index position.
|
||
*
|
||
* @param {number} row Visual row index to be dragged.
|
||
* @param {number} dropIndex Visual row index, being a drop index for the moved rows. Points to where we are going to drop the moved elements.
|
||
* To check visualization of drop index please take a look at [documentation](@/guides/rows/row-moving.md#drag-and-move-actions-of-manualrowmove-plugin).
|
||
* @fires Hooks#beforeRowMove
|
||
* @fires Hooks#afterRowMove
|
||
* @returns {boolean}
|
||
*/
|
||
dragRow(row, dropIndex) {
|
||
return this.dragRows([row], dropIndex);
|
||
}
|
||
|
||
/**
|
||
* Drag multiple rows to drop index position.
|
||
*
|
||
* @param {Array} rows Array of visual row indexes to be dragged.
|
||
* @param {number} dropIndex Visual row index, being a drop index for the moved rows. Points to where we are going to drop the moved elements.
|
||
* To check visualization of drop index please take a look at [documentation](@/guides/rows/row-moving.md#drag-and-move-actions-of-manualrowmove-plugin).
|
||
* @fires Hooks#beforeRowMove
|
||
* @fires Hooks#afterRowMove
|
||
* @returns {boolean}
|
||
*/
|
||
dragRows(rows, dropIndex) {
|
||
const finalIndex = this.countFinalIndex(rows, dropIndex);
|
||
const priv = privatePool.get(this);
|
||
priv.cachedDropIndex = dropIndex;
|
||
return this.moveRows(rows, finalIndex);
|
||
}
|
||
|
||
/**
|
||
* Indicates if it's possible to move rows to the desired position. Some of the actions aren't possible, i.e. You can’t move more than one element to the last position.
|
||
*
|
||
* @param {Array} movedRows Array of visual row indexes to be moved.
|
||
* @param {number} finalIndex Visual row index, being a start index for the moved rows. Points to where the elements will be placed after the moving action.
|
||
* To check the visualization of the final index, please take a look at [documentation](@/guides/rows/row-moving.md#drag-and-move-actions-of-manualrowmove-plugin).
|
||
* @returns {boolean}
|
||
*/
|
||
isMovePossible(movedRows, finalIndex) {
|
||
const length = this.hot.rowIndexMapper.getNotTrimmedIndexesLength();
|
||
|
||
// An attempt to transfer more rows to start destination than is possible (only when moving from the top to the bottom).
|
||
const tooHighDestinationIndex = movedRows.length + finalIndex > length;
|
||
const tooLowDestinationIndex = finalIndex < 0;
|
||
const tooLowMovedRowIndex = movedRows.some(movedRow => movedRow < 0);
|
||
const tooHighMovedRowIndex = movedRows.some(movedRow => movedRow >= length);
|
||
if (tooHighDestinationIndex || tooLowDestinationIndex || tooLowMovedRowIndex || tooHighMovedRowIndex) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Indicates if order of rows was changed.
|
||
*
|
||
* @private
|
||
* @param {Array} movedRows Array of visual row indexes to be moved.
|
||
* @param {number} finalIndex Visual row index, being a start index for the moved rows. Points to where the elements will be placed after the moving action.
|
||
* To check the visualization of the final index, please take a look at [documentation](@/guides/rows/row-moving.md#drag-and-move-actions-of-manualrowmove-plugin).
|
||
* @returns {boolean}
|
||
*/
|
||
isRowOrderChanged(movedRows, finalIndex) {
|
||
return movedRows.some((row, nrOfMovedElement) => row - nrOfMovedElement !== finalIndex);
|
||
}
|
||
|
||
/**
|
||
* Count the final row index from the drop index.
|
||
*
|
||
* @private
|
||
* @param {Array} movedRows Array of visual row indexes to be moved.
|
||
* @param {number} dropIndex Visual row index, being a drop index for the moved rows.
|
||
* @returns {number} Visual row index, being a start index for the moved rows.
|
||
*/
|
||
countFinalIndex(movedRows, dropIndex) {
|
||
const numberOfRowsLowerThanDropIndex = (0, _array.arrayReduce)(movedRows, (numberOfRows, currentRowIndex) => {
|
||
if (currentRowIndex < dropIndex) {
|
||
numberOfRows += 1;
|
||
}
|
||
return numberOfRows;
|
||
}, 0);
|
||
return dropIndex - numberOfRowsLowerThanDropIndex;
|
||
}
|
||
|
||
/**
|
||
* Gets the sum of the heights of rows in the provided range.
|
||
*
|
||
* @private
|
||
* @param {number} fromRow Visual row index.
|
||
* @param {number} toRow Visual row index.
|
||
* @returns {number}
|
||
*/
|
||
getRowsHeight(fromRow, toRow) {
|
||
const rowMapper = this.hot.rowIndexMapper;
|
||
let rowsHeight = 0;
|
||
for (let visualRowIndex = fromRow; visualRowIndex <= toRow; visualRowIndex++) {
|
||
const renderableIndex = rowMapper.getRenderableFromVisualIndex(visualRowIndex);
|
||
if (renderableIndex !== null) {
|
||
rowsHeight += this.hot.view._wt.wtTable.getRowHeight(renderableIndex) || 23;
|
||
}
|
||
}
|
||
return rowsHeight;
|
||
}
|
||
|
||
/**
|
||
* Loads initial settings when persistent state is saved or when plugin was initialized as an array.
|
||
*
|
||
* @private
|
||
*/
|
||
moveBySettingsOrLoad() {
|
||
const pluginSettings = this.hot.getSettings()[PLUGIN_KEY];
|
||
if (Array.isArray(pluginSettings)) {
|
||
this.moveRows(pluginSettings, 0);
|
||
} else if (pluginSettings !== void 0) {
|
||
const persistentState = this.persistentStateLoad();
|
||
if (persistentState.length) {
|
||
this.moveRows(persistentState, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Checks if the provided row is in the fixedRowsTop section.
|
||
*
|
||
* @private
|
||
* @param {number} row Visual row index to check.
|
||
* @returns {boolean}
|
||
*/
|
||
isFixedRowTop(row) {
|
||
return row < this.hot.getSettings().fixedRowsTop;
|
||
}
|
||
|
||
/**
|
||
* Checks if the provided row is in the fixedRowsBottom section.
|
||
*
|
||
* @private
|
||
* @param {number} row Visual row index to check.
|
||
* @returns {boolean}
|
||
*/
|
||
isFixedRowBottom(row) {
|
||
return row > this.hot.countRows() - 1 - this.hot.getSettings().fixedRowsBottom;
|
||
}
|
||
|
||
/**
|
||
* Saves the manual row positions to the persistent state (the {@link Options#persistentState} option has to be enabled).
|
||
*
|
||
* @private
|
||
* @fires Hooks#persistentStateSave
|
||
*/
|
||
persistentStateSave() {
|
||
// The `PersistentState` plugin should be refactored.
|
||
this.hot.runHooks('persistentStateSave', 'manualRowMove', this.hot.rowIndexMapper.getIndexesSequence());
|
||
}
|
||
|
||
/**
|
||
* Loads the manual row positions from the persistent state (the {@link Options#persistentState} option has to be enabled).
|
||
*
|
||
* @private
|
||
* @fires Hooks#persistentStateLoad
|
||
* @returns {Array} Stored state.
|
||
*/
|
||
persistentStateLoad() {
|
||
const storedState = {};
|
||
this.hot.runHooks('persistentStateLoad', 'manualRowMove', storedState);
|
||
return storedState.value ? storedState.value : [];
|
||
}
|
||
|
||
/**
|
||
* Prepares an array of indexes based on actual selection.
|
||
*
|
||
* @private
|
||
* @returns {Array}
|
||
*/
|
||
prepareRowsToMoving() {
|
||
const selection = this.hot.getSelectedRangeLast();
|
||
const selectedRows = [];
|
||
if (!selection) {
|
||
return selectedRows;
|
||
}
|
||
const {
|
||
from,
|
||
to
|
||
} = selection;
|
||
const start = Math.min(from.row, to.row);
|
||
const end = Math.max(from.row, to.row);
|
||
(0, _number.rangeEach)(start, end, i => {
|
||
selectedRows.push(i);
|
||
});
|
||
return selectedRows;
|
||
}
|
||
|
||
/**
|
||
* Update the UI visual position.
|
||
*
|
||
* @private
|
||
*/
|
||
refreshPositions() {
|
||
const priv = privatePool.get(this);
|
||
const coords = priv.target.coords;
|
||
const firstVisible = this.hot.view.getFirstFullyVisibleRow();
|
||
const lastVisible = this.hot.view.getLastFullyVisibleRow();
|
||
const countRows = this.hot.countRows();
|
||
if (this.isFixedRowTop(coords.row) && firstVisible > 0) {
|
||
this.hot.scrollViewportTo(this.hot.rowIndexMapper.getNearestNotHiddenIndex(firstVisible - 1, -1));
|
||
}
|
||
if (this.isFixedRowBottom(coords.row) && lastVisible < countRows) {
|
||
this.hot.scrollViewportTo(this.hot.rowIndexMapper.getNearestNotHiddenIndex(lastVisible + 1, 1), undefined, true);
|
||
}
|
||
const wtTable = this.hot.view._wt.wtTable;
|
||
const TD = priv.target.TD;
|
||
const rootElement = this.hot.rootElement;
|
||
const rootElementOffset = (0, _element.offset)(rootElement);
|
||
const trimmingContainer = (0, _element.getTrimmingContainer)(rootElement);
|
||
const tableScroll = wtTable.holder.scrollTop;
|
||
let trimmingContainerScroll;
|
||
|
||
// Trimming container is the `window` element.
|
||
if (this.hot.rootWindow === trimmingContainer) {
|
||
trimmingContainerScroll = trimmingContainer.scrollY;
|
||
} else {
|
||
trimmingContainerScroll = trimmingContainer.scrollTop;
|
||
}
|
||
const pixelsAbove = rootElementOffset.top - trimmingContainerScroll;
|
||
const pixelsRelToTableStart = priv.target.eventPageY - pixelsAbove + tableScroll;
|
||
const hiderHeight = wtTable.hider.offsetHeight;
|
||
const tbodyOffsetTop = wtTable.TBODY.offsetTop;
|
||
const backlightElemMarginTop = this.backlight.getOffset().top;
|
||
const backlightElemHeight = this.backlight.getSize().height;
|
||
const tdMiddle = TD.offsetHeight / 2;
|
||
const tdHeight = TD.offsetHeight;
|
||
let tdStartPixel = this.hot.view.THEAD.offsetHeight + this.getRowsHeight(0, coords.row - 1);
|
||
const isBelowTable = pixelsRelToTableStart >= tdStartPixel + tdMiddle;
|
||
if (this.isFixedRowTop(coords.row)) {
|
||
tdStartPixel += wtTable.holder.scrollTop;
|
||
}
|
||
if (coords.row < 0) {
|
||
// if hover on colHeader
|
||
priv.target.row = firstVisible > 0 ? firstVisible - 1 : firstVisible;
|
||
} else if (isBelowTable) {
|
||
// if hover on lower part of TD
|
||
priv.target.row = coords.row + 1;
|
||
// unfortunately first row is bigger than rest
|
||
tdStartPixel += coords.row === 0 ? tdHeight - 1 : tdHeight;
|
||
} else {
|
||
// elsewhere on table
|
||
priv.target.row = coords.row;
|
||
}
|
||
let backlightTop = pixelsRelToTableStart;
|
||
let guidelineTop = tdStartPixel;
|
||
if (pixelsRelToTableStart + backlightElemHeight + backlightElemMarginTop >= hiderHeight) {
|
||
// prevent display backlight below table
|
||
backlightTop = hiderHeight - backlightElemHeight - backlightElemMarginTop;
|
||
} else if (pixelsRelToTableStart + backlightElemMarginTop < tbodyOffsetTop) {
|
||
// prevent display above below table
|
||
backlightTop = tbodyOffsetTop + Math.abs(backlightElemMarginTop);
|
||
}
|
||
if (tdStartPixel >= hiderHeight - 1) {
|
||
// prevent display guideline below table
|
||
guidelineTop = hiderHeight - 1;
|
||
}
|
||
this.backlight.setPosition(backlightTop);
|
||
this.guideline.setPosition(guidelineTop);
|
||
}
|
||
|
||
/**
|
||
* Binds the events used by the plugin.
|
||
*
|
||
* @private
|
||
*/
|
||
registerEvents() {
|
||
const {
|
||
documentElement
|
||
} = this.hot.rootDocument;
|
||
this.eventManager.addEventListener(documentElement, 'mousemove', event => this.onMouseMove(event));
|
||
this.eventManager.addEventListener(documentElement, 'mouseup', () => this.onMouseUp());
|
||
}
|
||
|
||
/**
|
||
* Unbinds the events used by the plugin.
|
||
*
|
||
* @private
|
||
*/
|
||
unregisterEvents() {
|
||
this.eventManager.clear();
|
||
}
|
||
|
||
/**
|
||
* Change the behavior of selection / dragging.
|
||
*
|
||
* @private
|
||
* @param {MouseEvent} event `mousedown` event properties.
|
||
* @param {CellCoords} coords Visual cell coordinates where was fired event.
|
||
* @param {HTMLElement} TD Cell represented as HTMLElement.
|
||
* @param {object} controller An object with properties `row`, `column` and `cell`. Each property contains
|
||
* a boolean value that allows or disallows changing the selection for that particular area.
|
||
*/
|
||
onBeforeOnCellMouseDown(event, coords, TD, controller) {
|
||
const {
|
||
wtTable,
|
||
wtViewport
|
||
} = this.hot.view._wt;
|
||
const isHeaderSelection = this.hot.selection.isSelectedByRowHeader();
|
||
const selection = this.hot.getSelectedRangeLast();
|
||
const priv = privatePool.get(this);
|
||
if (!selection || !isHeaderSelection || priv.pressed || event.button !== 0) {
|
||
priv.pressed = false;
|
||
priv.rowsToMove.length = 0;
|
||
(0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI]);
|
||
return;
|
||
}
|
||
const guidelineIsNotReady = this.guideline.isBuilt() && !this.guideline.isAppended();
|
||
const backlightIsNotReady = this.backlight.isBuilt() && !this.backlight.isAppended();
|
||
if (guidelineIsNotReady && backlightIsNotReady) {
|
||
this.guideline.appendTo(wtTable.hider);
|
||
this.backlight.appendTo(wtTable.hider);
|
||
}
|
||
const {
|
||
from,
|
||
to
|
||
} = selection;
|
||
const start = Math.min(from.row, to.row);
|
||
const end = Math.max(from.row, to.row);
|
||
if (coords.col < 0 && coords.row >= start && coords.row <= end) {
|
||
controller.row = true;
|
||
priv.pressed = true;
|
||
priv.target.eventPageY = event.pageY;
|
||
priv.target.coords = coords;
|
||
priv.target.TD = TD;
|
||
priv.rowsToMove = this.prepareRowsToMoving();
|
||
const leftPos = wtTable.holder.scrollLeft + wtViewport.getRowHeaderWidth();
|
||
this.backlight.setPosition(null, leftPos);
|
||
this.backlight.setSize(wtTable.hider.offsetWidth - leftPos, this.getRowsHeight(start, end));
|
||
this.backlight.setOffset((this.getRowsHeight(start, coords.row - 1) + event.offsetY) * -1, null);
|
||
(0, _element.addClass)(this.hot.rootElement, CSS_ON_MOVING);
|
||
this.refreshPositions();
|
||
} else {
|
||
(0, _element.removeClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
|
||
priv.pressed = false;
|
||
priv.rowsToMove.length = 0;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 'mouseMove' event callback. Fired when pointer move on document.documentElement.
|
||
*
|
||
* @private
|
||
* @param {MouseEvent} event `mousemove` event properties.
|
||
*/
|
||
onMouseMove(event) {
|
||
const priv = privatePool.get(this);
|
||
if (!priv.pressed) {
|
||
return;
|
||
}
|
||
|
||
// callback for browser which doesn't supports CSS pointer-event: none
|
||
if (event.target === this.backlight.element) {
|
||
const height = this.backlight.getSize().height;
|
||
this.backlight.setSize(null, 0);
|
||
setTimeout(function () {
|
||
this.backlight.setPosition(null, height);
|
||
});
|
||
}
|
||
priv.target.eventPageY = event.pageY;
|
||
this.refreshPositions();
|
||
}
|
||
|
||
/**
|
||
* 'beforeOnCellMouseOver' hook callback. Fired when pointer was over cell.
|
||
*
|
||
* @private
|
||
* @param {MouseEvent} event `mouseover` event properties.
|
||
* @param {CellCoords} coords Visual cell coordinates where was fired event.
|
||
* @param {HTMLElement} TD Cell represented as HTMLElement.
|
||
* @param {object} controller An object with properties `row`, `column` and `cell`. Each property contains
|
||
* a boolean value that allows or disallows changing the selection for that particular area.
|
||
*/
|
||
onBeforeOnCellMouseOver(event, coords, TD, controller) {
|
||
const selectedRange = this.hot.getSelectedRangeLast();
|
||
const priv = privatePool.get(this);
|
||
if (!selectedRange || !priv.pressed) {
|
||
return;
|
||
}
|
||
if (priv.rowsToMove.indexOf(coords.row) > -1) {
|
||
(0, _element.removeClass)(this.hot.rootElement, CSS_SHOW_UI);
|
||
} else {
|
||
(0, _element.addClass)(this.hot.rootElement, CSS_SHOW_UI);
|
||
}
|
||
controller.row = true;
|
||
controller.column = true;
|
||
controller.cell = true;
|
||
priv.target.coords = coords;
|
||
priv.target.TD = TD;
|
||
}
|
||
|
||
/**
|
||
* `onMouseUp` hook callback.
|
||
*
|
||
* @private
|
||
*/
|
||
onMouseUp() {
|
||
const priv = privatePool.get(this);
|
||
const target = priv.target.row;
|
||
const rowsLen = priv.rowsToMove.length;
|
||
priv.pressed = false;
|
||
priv.backlightHeight = 0;
|
||
(0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI, CSS_AFTER_SELECTION]);
|
||
if (this.hot.selection.isSelectedByRowHeader()) {
|
||
(0, _element.addClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
|
||
}
|
||
if (rowsLen < 1 || target === void 0) {
|
||
return;
|
||
}
|
||
const firstMovedVisualRow = priv.rowsToMove[0];
|
||
const firstMovedPhysicalRow = this.hot.toPhysicalRow(firstMovedVisualRow);
|
||
const movePerformed = this.dragRows(priv.rowsToMove, target);
|
||
priv.rowsToMove.length = 0;
|
||
if (movePerformed === true) {
|
||
this.persistentStateSave();
|
||
this.hot.render();
|
||
this.hot.view.adjustElementsSize(true);
|
||
const selectionStart = this.hot.toVisualRow(firstMovedPhysicalRow);
|
||
const selectionEnd = selectionStart + rowsLen - 1;
|
||
this.hot.selectRows(selectionStart, selectionEnd);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* `afterScrollHorizontally` hook callback. Fired the table was scrolled horizontally.
|
||
*
|
||
* @private
|
||
*/
|
||
onAfterScrollHorizontally() {
|
||
const wtTable = this.hot.view._wt.wtTable;
|
||
const headerWidth = this.hot.view._wt.wtViewport.getRowHeaderWidth();
|
||
const scrollLeft = wtTable.holder.scrollLeft;
|
||
const posLeft = headerWidth + scrollLeft;
|
||
this.backlight.setPosition(null, posLeft);
|
||
this.backlight.setSize(wtTable.hider.offsetWidth - posLeft);
|
||
}
|
||
|
||
/**
|
||
* Builds the plugin's UI.
|
||
*
|
||
* @private
|
||
*/
|
||
buildPluginUI() {
|
||
this.backlight.build();
|
||
this.guideline.build();
|
||
}
|
||
|
||
/**
|
||
* Callback for the `afterLoadData` hook.
|
||
*
|
||
* @private
|
||
*/
|
||
onAfterLoadData() {
|
||
this.moveBySettingsOrLoad();
|
||
}
|
||
|
||
/**
|
||
* Destroys the plugin instance.
|
||
*/
|
||
destroy() {
|
||
this.backlight.destroy();
|
||
this.guideline.destroy();
|
||
super.destroy();
|
||
}
|
||
}
|
||
exports.ManualRowMove = ManualRowMove; |