UNPKG

@quantlab/handsontable

Version:

Spreadsheet-like data grid editor that provides copy/paste functionality compatible with Excel/Google Docs

369 lines (323 loc) 10.7 kB
import Hooks from './../../pluginHooks'; import {getWindowScrollTop, hasClass, getWindowScrollLeft} from './../../helpers/dom/element'; import {isMobileBrowser} from './../../helpers/browser'; import BasePlugin from './../_base'; import EventManager from './../../eventManager'; import {registerPlugin} from './../../plugins'; import {CellCoords} from './../../3rdparty/walkontable/src'; /** * @private * @plugin MultipleSelectionHandles */ class MultipleSelectionHandles extends BasePlugin { /** * @param {Object} hotInstance */ constructor(hotInstance) { super(hotInstance); /** * @type {Array} */ this.dragged = []; /** * Instance of EventManager. * * @type {EventManager} */ this.eventManager = null; /** * @type {null} */ this.lastSetCell = null; } /** * Check if the plugin is enabled in the handsontable settings. * * @returns {Boolean} */ isEnabled() { return isMobileBrowser(); } /** * Enable plugin for this Handsontable instance. */ enablePlugin() { if (this.enabled) { return; } if (!this.eventManager) { this.eventManager = new EventManager(this); } this.registerListeners(); super.enablePlugin(); } /** * Bind the touch events * @private */ registerListeners() { var _this = this; function removeFromDragged(query) { if (_this.dragged.length === 1) { // clear array _this.dragged.splice(0, _this.dragged.length); return true; } var entryPosition = _this.dragged.indexOf(query); if (entryPosition == -1) { return false; } else if (entryPosition === 0) { _this.dragged = _this.dragged.slice(0, 1); } else if (entryPosition == 1) { _this.dragged = _this.dragged.slice(-1); } } this.eventManager.addEventListener(this.hot.rootElement, 'touchstart', (event) => { let selectedRange; if (hasClass(event.target, 'topLeftSelectionHandle-HitArea')) { selectedRange = _this.hot.getSelectedRange(); _this.dragged.push('topLeft'); _this.touchStartRange = { width: selectedRange.getWidth(), height: selectedRange.getHeight(), direction: selectedRange.getDirection() }; event.preventDefault(); return false; } else if (hasClass(event.target, 'bottomRightSelectionHandle-HitArea')) { selectedRange = _this.hot.getSelectedRange(); _this.dragged.push('bottomRight'); _this.touchStartRange = { width: selectedRange.getWidth(), height: selectedRange.getHeight(), direction: selectedRange.getDirection() }; event.preventDefault(); return false; } }); this.eventManager.addEventListener(this.hot.rootElement, 'touchend', (event) => { if (hasClass(event.target, 'topLeftSelectionHandle-HitArea')) { removeFromDragged.call(_this, 'topLeft'); _this.touchStartRange = void 0; event.preventDefault(); return false; } else if (hasClass(event.target, 'bottomRightSelectionHandle-HitArea')) { removeFromDragged.call(_this, 'bottomRight'); _this.touchStartRange = void 0; event.preventDefault(); return false; } }); this.eventManager.addEventListener(this.hot.rootElement, 'touchmove', (event) => { let scrollTop = getWindowScrollTop(), scrollLeft = getWindowScrollLeft(), endTarget, targetCoords, selectedRange, rangeWidth, rangeHeight, rangeDirection, newRangeCoords; if (_this.dragged.length === 0) { return; } endTarget = document.elementFromPoint( event.touches[0].screenX - scrollLeft, event.touches[0].screenY - scrollTop); if (!endTarget || endTarget === _this.lastSetCell) { return; } if (endTarget.nodeName == 'TD' || endTarget.nodeName == 'TH') { targetCoords = _this.hot.getCoords(endTarget); if (targetCoords.col == -1) { targetCoords.col = 0; } selectedRange = _this.hot.getSelectedRange(); rangeWidth = selectedRange.getWidth(); rangeHeight = selectedRange.getHeight(); rangeDirection = selectedRange.getDirection(); if (rangeWidth == 1 && rangeHeight == 1) { _this.hot.selection.setRangeEnd(targetCoords); } newRangeCoords = _this.getCurrentRangeCoords(selectedRange, targetCoords, _this.touchStartRange.direction, rangeDirection, _this.dragged[0]); if (newRangeCoords.start !== null) { _this.hot.selection.setRangeStart(newRangeCoords.start); } _this.hot.selection.setRangeEnd(newRangeCoords.end); _this.lastSetCell = endTarget; } event.preventDefault(); }); } getCurrentRangeCoords(selectedRange, currentTouch, touchStartDirection, currentDirection, draggedHandle) { var topLeftCorner = selectedRange.getTopLeftCorner(), bottomRightCorner = selectedRange.getBottomRightCorner(), bottomLeftCorner = selectedRange.getBottomLeftCorner(), topRightCorner = selectedRange.getTopRightCorner(); var newCoords = { start: null, end: null }; switch (touchStartDirection) { case 'NE-SW': switch (currentDirection) { case 'NE-SW': case 'NW-SE': if (draggedHandle == 'topLeft') { newCoords = { start: new CellCoords(currentTouch.row, selectedRange.highlight.col), end: new CellCoords(bottomLeftCorner.row, currentTouch.col) }; } else { newCoords = { start: new CellCoords(selectedRange.highlight.row, currentTouch.col), end: new CellCoords(currentTouch.row, topLeftCorner.col) }; } break; case 'SE-NW': if (draggedHandle == 'bottomRight') { newCoords = { start: new CellCoords(bottomRightCorner.row, currentTouch.col), end: new CellCoords(currentTouch.row, topLeftCorner.col) }; } break; default: break; } break; case 'NW-SE': switch (currentDirection) { case 'NE-SW': if (draggedHandle == 'topLeft') { newCoords = { start: currentTouch, end: bottomLeftCorner }; } else { newCoords.end = currentTouch; } break; case 'NW-SE': if (draggedHandle == 'topLeft') { newCoords = { start: currentTouch, end: bottomRightCorner }; } else { newCoords.end = currentTouch; } break; case 'SE-NW': if (draggedHandle == 'topLeft') { newCoords = { start: currentTouch, end: topLeftCorner }; } else { newCoords.end = currentTouch; } break; case 'SW-NE': if (draggedHandle == 'topLeft') { newCoords = { start: currentTouch, end: topRightCorner }; } else { newCoords.end = currentTouch; } break; default: break; } break; case 'SW-NE': switch (currentDirection) { case 'NW-SE': if (draggedHandle == 'bottomRight') { newCoords = { start: new CellCoords(currentTouch.row, topLeftCorner.col), end: new CellCoords(bottomLeftCorner.row, currentTouch.col) }; } else { newCoords = { start: new CellCoords(topLeftCorner.row, currentTouch.col), end: new CellCoords(currentTouch.row, bottomRightCorner.col) }; } break; // case 'NE-SW': // // break; case 'SW-NE': if (draggedHandle == 'topLeft') { newCoords = { start: new CellCoords(selectedRange.highlight.row, currentTouch.col), end: new CellCoords(currentTouch.row, bottomRightCorner.col) }; } else { newCoords = { start: new CellCoords(currentTouch.row, topLeftCorner.col), end: new CellCoords(topLeftCorner.row, currentTouch.col) }; } break; case 'SE-NW': if (draggedHandle == 'bottomRight') { newCoords = { start: new CellCoords(currentTouch.row, topRightCorner.col), end: new CellCoords(topLeftCorner.row, currentTouch.col) }; } else if (draggedHandle == 'topLeft') { newCoords = { start: bottomLeftCorner, end: currentTouch }; } break; default: break; } break; case 'SE-NW': switch (currentDirection) { case 'NW-SE': case 'NE-SW': case 'SW-NE': if (draggedHandle == 'topLeft') { newCoords.end = currentTouch; } break; case 'SE-NW': if (draggedHandle == 'topLeft') { newCoords.end = currentTouch; } else { newCoords = { start: currentTouch, end: topLeftCorner }; } break; default: break; } break; default: break; } return newCoords; } /** * Check if user is currently dragging the handle. * * @returns {boolean} Dragging state */ isDragged() { return this.dragged.length > 0; } } registerPlugin('multipleSelectionHandles', MultipleSelectionHandles); export default MultipleSelectionHandles;