UNPKG

handsontable

Version:

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

198 lines (188 loc) • 8.07 kB
"use strict"; exports.__esModule = true; require("core-js/modules/es.error.cause.js"); var _cursor2 = require("./cursor"); function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); } function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); } function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); } function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; } function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); } /** * Helper class for positioning the menu and submenus in the correct place relative to the * cursor position (DOM element or mouse coordinates). * * @private * @class Positioner */ var _container = /*#__PURE__*/new WeakMap(); var _parentContainer = /*#__PURE__*/new WeakMap(); var _cursor = /*#__PURE__*/new WeakMap(); var _keepInViewport = /*#__PURE__*/new WeakMap(); var _offset = /*#__PURE__*/new WeakMap(); class Positioner { constructor(keepInViewport) { /** * The menu container element the positioning will be applied to. * * @type {HTMLElement} */ _classPrivateFieldInitSpec(this, _container, void 0); /** * For positioning the submenu, the parent element is used to calculate offsets to ensure that submenu * is positioned right next to the parent menu. * * @type {HTMLElement} */ _classPrivateFieldInitSpec(this, _parentContainer, void 0); /** * The instance of the Cursor class. * * @type {Cursor} */ _classPrivateFieldInitSpec(this, _cursor, void 0); /** * Enabling the option allows changing the position calculation so that the menus (or submenus) * are always placed within the visible viewport of the browser. * * @type {boolean} */ _classPrivateFieldInitSpec(this, _keepInViewport, false); /** * Allows apply the position offset for directions. * * @type {{above: number, below: number, left: number, right: number}} */ _classPrivateFieldInitSpec(this, _offset, { above: 0, below: 0, left: 0, right: 0 }); _classPrivateFieldSet(_keepInViewport, this, keepInViewport); } /** * Sets offset position for specified directions (`above`, `below`, `left` or `right`). * * @param {'above' | 'below' | 'left' | 'right'} direction A direction name. * @param {number} [offset=0] Offset value. * @returns {Positioner} */ setOffset(direction) { let offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; _classPrivateFieldGet(_offset, this)[direction] = offset; return this; } /** * Sets the menu element to work with. The element can be owned by the main menu or the submenu. * * @param {HTMLElement} container The menu container element. * @returns {Positioner} */ setElement(container) { _classPrivateFieldSet(_container, this, container); return this; } /** * Sets the parent menu element to work with. * * @param {HTMLElement} container The parent menu container element. * @returns {Positioner} */ setParentElement(container) { _classPrivateFieldSet(_parentContainer, this, container); return this; } /** * Updates the menu position. * * @param {object|MouseEvent} coords The literal object with `top`, `left`, `width` and `height` props or a * mouse event object. */ updatePosition(coords) { _classPrivateFieldSet(_cursor, this, new _cursor2.Cursor(coords, _classPrivateFieldGet(_container, this).ownerDocument.defaultView)); if (_classPrivateFieldGet(_keepInViewport, this)) { if (_classPrivateFieldGet(_cursor, this).fitsBelow(_classPrivateFieldGet(_container, this))) { this.setPositionBelowCursor(); } else if (_classPrivateFieldGet(_cursor, this).fitsAbove(_classPrivateFieldGet(_container, this))) { this.setPositionAboveCursor(); } else { this.setPositionBelowCursor(); } this.updateHorizontalPosition(); } else { this.setPositionBelowCursor(); this.setPositionOnRightOfCursor(); } } /** * Updates the menu horizontal position. */ updateHorizontalPosition() { if (_classPrivateFieldGet(_container, this).dir === 'rtl') { if (_classPrivateFieldGet(_cursor, this).fitsOnLeft(_classPrivateFieldGet(_container, this))) { this.setPositionOnLeftOfCursor(); } else { this.setPositionOnRightOfCursor(); } } else if (_classPrivateFieldGet(_cursor, this).fitsOnRight(_classPrivateFieldGet(_container, this))) { this.setPositionOnRightOfCursor(); } else { this.setPositionOnLeftOfCursor(); } } /** * Sets the menu position above the cursor object. */ setPositionAboveCursor() { let top = _classPrivateFieldGet(_offset, this).above + _classPrivateFieldGet(_cursor, this).top - _classPrivateFieldGet(_container, this).offsetHeight; if (_classPrivateFieldGet(_parentContainer, this)) { const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView; const style = rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.ht_master')); const paddingTop = Number.parseInt(style.paddingTop, 10); const borderTop = Number.parseInt(style.borderTop, 10); top = _classPrivateFieldGet(_cursor, this).top + _classPrivateFieldGet(_cursor, this).cellHeight - _classPrivateFieldGet(_container, this).scrollHeight + paddingTop + borderTop; } _classPrivateFieldGet(_container, this).style.top = `${top}px`; } /** * Sets the menu position below the cursor object. */ setPositionBelowCursor() { let top = _classPrivateFieldGet(_offset, this).below + _classPrivateFieldGet(_cursor, this).top + 1; if (_classPrivateFieldGet(_parentContainer, this)) { const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView; const style = rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.ht_master')); const paddingTop = Number.parseInt(style.paddingTop, 10); const borderTop = Number.parseInt(style.borderTop, 10); top = _classPrivateFieldGet(_cursor, this).top - paddingTop - borderTop - 1; } _classPrivateFieldGet(_container, this).style.top = `${top}px`; } /** * Sets the menu position on the right of the cursor object. */ setPositionOnRightOfCursor() { let left = _classPrivateFieldGet(_cursor, this).left; if (_classPrivateFieldGet(_parentContainer, this)) { const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView; const borderRightWidth = Number.parseInt(rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.htCore')).borderRightWidth, 10); left += _classPrivateFieldGet(_cursor, this).cellWidth + borderRightWidth; } else { left += _classPrivateFieldGet(_offset, this).right; } _classPrivateFieldGet(_container, this).style.left = `${left}px`; } /** * Sets the menu position on the left of the cursor object. */ setPositionOnLeftOfCursor() { let left = _classPrivateFieldGet(_offset, this).left + _classPrivateFieldGet(_cursor, this).left - _classPrivateFieldGet(_container, this).offsetWidth; if (_classPrivateFieldGet(_parentContainer, this)) { const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView; const borderLeftWidth = Number.parseInt(rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.htCore')).borderLeftWidth, 10); left -= borderLeftWidth; } _classPrivateFieldGet(_container, this).style.left = `${left}px`; } } exports.Positioner = Positioner;