UNPKG

handsontable

Version:

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

297 lines (281 loc) • 12 kB
"use strict"; exports.__esModule = true; require("core-js/modules/es.error.cause.js"); var _element = require("../../../helpers/dom/element"); var _object = require("../../../helpers/object"); function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); } function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 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"); } /** * @class Scroll */ var _Scroll_brand = /*#__PURE__*/new WeakSet(); class Scroll { /** * @param {ScrollDao} dataAccessObject Tha data access object. */ constructor(dataAccessObject) { /** * Get last visible column based on virtual dom and how table is visible in browser window viewport. * * @param {number} lastColumnIndex The last visible column index. * @returns {number} */ _classPrivateMethodInitSpec(this, _Scroll_brand); /** * The data access object. * * @protected * @type {ScrollDao} */ _defineProperty(this, "dataAccessObject", void 0); this.dataAccessObject = dataAccessObject; } /** * Scrolls viewport to a cell. * * @param {CellCoords} coords The cell coordinates. * @param {'auto' | 'start' | 'end'} [horizontalSnap='auto'] If `'start'`, viewport is scrolled to show * the cell on the left of the table. If `'end'`, viewport is scrolled to show the cell on the right of * the table. When `'auto'`, the viewport is scrolled only when the column is outside of the viewport. * @param {'auto' | 'top' | 'bottom'} [verticalSnap='auto'] If `'top'`, viewport is scrolled to show * the cell on the top of the table. If `'bottom'`, viewport is scrolled to show the cell on the bottom of * the table. When `'auto'`, the viewport is scrolled only when the row is outside of the viewport. * @returns {boolean} */ scrollViewport(coords, horizontalSnap, verticalSnap) { if (coords.col < 0 || coords.row < 0) { return false; } const scrolledHorizontally = this.scrollViewportHorizontally(coords.col, horizontalSnap); const scrolledVertically = this.scrollViewportVertically(coords.row, verticalSnap); return scrolledHorizontally || scrolledVertically; } /** * Scrolls viewport to a column. * * @param {number} column Visual column index. * @param {'auto' | 'start' | 'end'} [snapping='auto'] If `'start'`, viewport is scrolled to show * the cell on the left of the table. If `'end'`, viewport is scrolled to show the cell on the right of * the table. When `'auto'`, the viewport is scrolled only when the column is outside of the viewport. * @returns {boolean} */ scrollViewportHorizontally(column) { let snapping = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'auto'; const { drawn, totalColumns } = this.dataAccessObject; if (!drawn) { return false; } const snappingObject = (0, _object.createObjectPropListener)(snapping); column = this.dataAccessObject.wtSettings.getSetting('onBeforeViewportScrollHorizontally', column, snappingObject); if (!Number.isInteger(column) || column < 0 || column > totalColumns) { return false; } snapping = snappingObject.value; const { fixedColumnsStart, inlineStartOverlay } = this.dataAccessObject; const autoSnapping = snapping === 'auto'; // for auto-snapping do not scroll the viewport when the columns points to the overlays if (autoSnapping && column < fixedColumnsStart) { return false; } const firstColumn = this.getFirstVisibleColumn(); const lastColumn = this.getLastVisibleColumn(); let result = false; if (autoSnapping && (column < firstColumn || column > lastColumn) || !autoSnapping) { // if there is at least one fully visible column determine the snapping direction based on // that columns or by snapping flag, if provided. result = inlineStartOverlay.scrollTo(column, autoSnapping ? column >= this.getLastPartiallyVisibleColumn() : snapping === 'end'); } return result; } /** * Scrolls viewport to a row. * * @param {number} row Visual row index. * @param {'auto' | 'top' | 'bottom'} [snapping='auto'] If `'top'`, viewport is scrolled to show * the cell on the top of the table. If `'bottom'`, viewport is scrolled to show the cell on * the bottom of the table. When `'auto'`, the viewport is scrolled only when the row is outside of * the viewport. * @returns {boolean} */ scrollViewportVertically(row) { let snapping = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'auto'; const { drawn, totalRows } = this.dataAccessObject; if (!drawn) { return false; } const snappingObject = (0, _object.createObjectPropListener)(snapping); row = this.dataAccessObject.wtSettings.getSetting('onBeforeViewportScrollVertically', row, snappingObject); if (!Number.isInteger(row) || row < 0 || row > totalRows) { return false; } snapping = snappingObject.value; const { fixedRowsBottom, fixedRowsTop, topOverlay } = this.dataAccessObject; const autoSnapping = snapping === 'auto'; // for auto-snapping do not scroll the viewport when the rows points to the overlays if (autoSnapping && (row < fixedRowsTop || row > totalRows - fixedRowsBottom - 1)) { return false; } const firstRow = this.getFirstVisibleRow(); const lastRow = this.getLastVisibleRow(); let result = false; if (autoSnapping && (row < firstRow || row > lastRow) || !autoSnapping) { // if there is at least one fully visible row determine the snapping direction based on // that rows or by snapping flag, if provided. result = topOverlay.scrollTo(row, autoSnapping ? row >= this.getLastPartiallyVisibleRow() : snapping === 'bottom'); } return result; } /** * Get first visible row based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getFirstVisibleRow() { return this.dataAccessObject.wtTable.getFirstVisibleRow(); } /** * Get last visible row based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getLastVisibleRow() { return _assertClassBrand(_Scroll_brand, this, _getLastRowIndex).call(this, this.dataAccessObject.wtTable.getLastVisibleRow()); } /** * Get first partially visible row based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getFirstPartiallyVisibleRow() { return this.dataAccessObject.wtTable.getFirstPartiallyVisibleRow(); } /** * Get last visible row based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getLastPartiallyVisibleRow() { return _assertClassBrand(_Scroll_brand, this, _getLastRowIndex).call(this, this.dataAccessObject.wtTable.getLastPartiallyVisibleRow()); } /** * Get first visible column based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getFirstVisibleColumn() { return this.dataAccessObject.wtTable.getFirstVisibleColumn(); } /** * Get last visible column based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getLastVisibleColumn() { return _assertClassBrand(_Scroll_brand, this, _getLastColumnIndex).call(this, this.dataAccessObject.wtTable.getLastVisibleColumn()); } /** * Get first partially visible column based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getFirstPartiallyVisibleColumn() { return this.dataAccessObject.wtTable.getFirstPartiallyVisibleColumn(); } /** * Get last partially visible column based on virtual dom and how table is visible in browser window viewport. * * @returns {number} */ getLastPartiallyVisibleColumn() { return _assertClassBrand(_Scroll_brand, this, _getLastColumnIndex).call(this, this.dataAccessObject.wtTable.getLastPartiallyVisibleColumn()); } } function _getLastColumnIndex(lastColumnIndex) { const { wtSettings, inlineStartOverlay, wtTable, wtViewport, totalColumns, rootWindow } = this.dataAccessObject; if (inlineStartOverlay.mainTableScrollableElement === rootWindow) { const isRtl = wtSettings.getSetting('rtlMode'); let inlineStartRootElementOffset = null; if (isRtl) { const tableRect = wtTable.TABLE.getBoundingClientRect(); const rootDocument = this.dataAccessObject.rootWindow.document; const docOffsetWidth = rootDocument.documentElement.offsetWidth; inlineStartRootElementOffset = Math.abs(tableRect.right - docOffsetWidth); } else { const rootElementOffset = (0, _element.offset)(wtTable.wtRootElement); inlineStartRootElementOffset = rootElementOffset.left; } const windowScrollLeft = Math.abs((0, _element.getScrollLeft)(rootWindow, rootWindow)); // Only calculate lastColumnIndex when table didn't filled (from right) whole viewport space if (inlineStartRootElementOffset > windowScrollLeft) { const windowWidth = (0, _element.innerWidth)(rootWindow); let columnsWidth = wtViewport.getRowHeaderWidth(); for (let column = 1; column <= totalColumns; column++) { columnsWidth += inlineStartOverlay.sumCellSizes(column - 1, column); if (inlineStartRootElementOffset + columnsWidth - windowScrollLeft >= windowWidth) { // Return physical column - 1 (-2 because rangeEach gives column index + 1 - sumCellSizes requirements) lastColumnIndex = column - 2; break; } } } } return lastColumnIndex; } /** * Get last visible row based on virtual dom and how table is visible in browser window viewport. * * @param {number} lastRowIndex The last visible row index. * @returns {number} */ function _getLastRowIndex(lastRowIndex) { const { topOverlay, wtTable, wtViewport, totalRows, rootWindow } = this.dataAccessObject; if (topOverlay.mainTableScrollableElement === rootWindow) { const rootElementOffset = (0, _element.offset)(wtTable.wtRootElement); const windowScrollTop = (0, _element.getScrollTop)(rootWindow, rootWindow); // Only calculate lastRowIndex when table didn't filled (from bottom) whole viewport space if (rootElementOffset.top > windowScrollTop) { const windowHeight = (0, _element.innerHeight)(rootWindow); let rowsHeight = wtViewport.getColumnHeaderHeight(); for (let row = 1; row <= totalRows; row++) { rowsHeight += topOverlay.sumCellSizes(row - 1, row); if (rootElementOffset.top + rowsHeight - windowScrollTop >= windowHeight) { // Return physical row - 1 (-2 because rangeEach gives row index + 1 - sumCellSizes requirements) lastRowIndex = row - 2; break; } } } } return lastRowIndex; } var _default = exports.default = Scroll;