"use strict"; exports.__esModule = true; var _base = require("../base"); var _eventManager = _interopRequireDefault(require("../../eventManager")); var _event = require("../../helpers/dom/event"); var _element = require("../../helpers/dom/element"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const PLUGIN_KEY = 'dragToScroll'; exports.PLUGIN_KEY = PLUGIN_KEY; const PLUGIN_PRIORITY = 100; /* eslint-disable jsdoc/require-description-complete-sentence */ /** * @description * Plugin used to scroll Handsontable by selecting a cell and dragging outside of the visible viewport. * * * @class DragToScroll * @plugin DragToScroll */ exports.PLUGIN_PRIORITY = PLUGIN_PRIORITY; class DragToScroll extends _base.BasePlugin { static get PLUGIN_KEY() { return PLUGIN_KEY; } static get PLUGIN_PRIORITY() { return PLUGIN_PRIORITY; } constructor(hotInstance) { super(hotInstance); /** * Instance of {@link EventManager}. * * @private * @type {EventManager} */ this.eventManager = new _eventManager.default(this); /** * Size of an element and its position relative to the viewport, * e.g. {bottom: 449, height: 441, left: 8, right: 814, top: 8, width: 806, x: 8, y:8}. * * @type {DOMRect} */ this.boundaries = null; /** * Callback function. * * @private * @type {Function} */ this.callback = null; /** * Flag indicates mouseDown/mouseUp. * * @private * @type {boolean} */ this.listening = false; } /** * 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 DragToScroll#enablePlugin} method is called. * * @returns {boolean} */ isEnabled() { return !!this.hot.getSettings()[PLUGIN_KEY]; } /** * Enables the plugin functionality for this Handsontable instance. */ enablePlugin() { if (this.enabled) { return; } this.addHook('afterOnCellMouseDown', event => this.setupListening(event)); this.addHook('afterOnCellCornerMouseDown', event => this.setupListening(event)); this.registerEvents(); 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: * - [`dragToScroll`](@/api/options.md#dragtoscroll) */ updatePlugin() { this.disablePlugin(); this.enablePlugin(); super.updatePlugin(); } /** * Disables the plugin functionality for this Handsontable instance. */ disablePlugin() { this.unregisterEvents(); super.disablePlugin(); } /** * Sets the value of the visible element. * * @param {DOMRect} boundaries An object with coordinates compatible with DOMRect. */ setBoundaries(boundaries) { this.boundaries = boundaries; } /** * Changes callback function. * * @param {Function} callback The callback function. */ setCallback(callback) { this.callback = callback; } /** * Checks if the mouse position (X, Y) is outside of the viewport and fires a callback with calculated X an Y diffs * between passed boundaries. * * @param {number} x Mouse X coordinate to check. * @param {number} y Mouse Y coordinate to check. */ check(x, y) { let diffX = 0; let diffY = 0; if (y < this.boundaries.top) { // y is less than top diffY = y - this.boundaries.top; } else if (y > this.boundaries.bottom) { // y is more than bottom diffY = y - this.boundaries.bottom; } if (x < this.boundaries.left) { // x is less than left diffX = x - this.boundaries.left; } else if (x > this.boundaries.right) { // x is more than right diffX = x - this.boundaries.right; } this.callback(diffX, diffY); } /** * Enables listening on `mousemove` event. * * @private */ listen() { this.listening = true; } /** * Disables listening on `mousemove` event. * * @private */ unlisten() { this.listening = false; } /** * Returns current state of listening. * * @private * @returns {boolean} */ isListening() { return this.listening; } /** * Registers dom listeners. * * @private */ registerEvents() { const { rootWindow } = this.hot; let frame = rootWindow; while (frame) { this.eventManager.addEventListener(frame.document, 'contextmenu', () => this.unlisten()); this.eventManager.addEventListener(frame.document, 'mouseup', () => this.unlisten()); this.eventManager.addEventListener(frame.document, 'mousemove', event => this.onMouseMove(event)); frame = (0, _element.getParentWindow)(frame); } } /** * Unbinds the events used by the plugin. * * @private */ unregisterEvents() { this.eventManager.clear(); } /** * On after on cell/cellCorner mouse down listener. * * @private * @param {MouseEvent} event The mouse event object. */ setupListening(event) { if ((0, _event.isRightClick)(event)) { return; } const scrollHandler = this.hot.view._wt.wtTable.holder; // native scroll if (scrollHandler === this.hot.rootWindow) { // not much we can do currently return; } this.setBoundaries(scrollHandler.getBoundingClientRect()); this.setCallback((scrollX, scrollY) => { if (scrollX < 0) { scrollHandler.scrollLeft -= 50; } else if (scrollX > 0) { scrollHandler.scrollLeft += 50; } if (scrollY < 0) { scrollHandler.scrollTop -= 20; } else if (scrollY > 0) { scrollHandler.scrollTop += 20; } }); this.listen(); } /** * 'mouseMove' event callback. * * @private * @param {MouseEvent} event `mousemove` event properties. */ onMouseMove(event) { if (!this.isListening()) { return; } this.check(event.clientX, event.clientY); } /** * Destroys the plugin instance. */ destroy() { super.destroy(); } } exports.DragToScroll = DragToScroll;