UNPKG

handsontable

Version:

Handsontable is a JavaScript Spreadsheet Component available for React, Angular and Vue.

247 lines (206 loc) • 7.3 kB
"use strict"; exports.__esModule = true; exports.default = void 0; var _constants = require("./constants"); var _viewSizeSet = _interopRequireDefault(require("./viewSizeSet")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } /** * Executive model for each table renderer. It's responsible for injecting DOM nodes in a * specified order and adjusting the number of elements in the root node. * * Only this class have rights to juggling DOM elements within the root node (see render method). * * @class {OrderView} */ var OrderView = /*#__PURE__*/function () { function OrderView(rootNode, nodesPool, childNodeType) { _classCallCheck(this, OrderView); /** * The root node to manage with. * * @type {HTMLElement} */ this.rootNode = rootNode; /** * Factory for newly created DOM elements. * * @type {Function} */ this.nodesPool = nodesPool; /** * Holder for sizing and positioning of the view. * * @type {ViewSizeSet} */ this.sizeSet = new _viewSizeSet.default(); /** * Node type which the order view will manage while rendering the DOM elements. * * @type {string} */ this.childNodeType = childNodeType.toUpperCase(); /** * The visual index of currently processed row. * * @type {number} */ this.visualIndex = 0; /** * The list of DOM elements which are rendered for this render cycle. * * @type {HTMLElement[]} */ this.collectedNodes = []; } /** * Sets the size for rendered elements. It can be a size for rows, cells or size for row * headers etc. It depends for what table renderer this instance was created. * * @param {number} size The size. * @returns {OrderView} */ _createClass(OrderView, [{ key: "setSize", value: function setSize(size) { this.sizeSet.setSize(size); return this; } /** * Sets the offset for rendered elements. The offset describes the shift between 0 and * the first rendered element according to the scroll position. * * @param {number} offset The offset. * @returns {OrderView} */ }, { key: "setOffset", value: function setOffset(offset) { this.sizeSet.setOffset(offset); return this; } /** * Checks if this instance of the view shares the root node with another instance. This happens only once when * a row (TR) as a root node is managed by two OrderView instances. If this happens another DOM injection * algorithm is performed to achieve consistent order. * * @returns {boolean} */ }, { key: "isSharedViewSet", value: function isSharedViewSet() { return this.sizeSet.isShared(); } /** * Returns rendered DOM element based on visual index. * * @param {number} visualIndex The visual index. * @returns {HTMLElement} */ }, { key: "getNode", value: function getNode(visualIndex) { return visualIndex < this.collectedNodes.length ? this.collectedNodes[visualIndex] : null; } /** * Returns currently processed DOM element. * * @returns {HTMLElement} */ }, { key: "getCurrentNode", value: function getCurrentNode() { var length = this.collectedNodes.length; return length > 0 ? this.collectedNodes[length - 1] : null; } /** * Returns rendered child count for this instance. * * @returns {number} */ }, { key: "getRenderedChildCount", value: function getRenderedChildCount() { var rootNode = this.rootNode, sizeSet = this.sizeSet; var childElementCount = 0; if (this.isSharedViewSet()) { var element = rootNode.firstElementChild; while (element) { if (element.tagName === this.childNodeType) { childElementCount += 1; } else if (sizeSet.isPlaceOn(_constants.WORKING_SPACE_TOP)) { break; } element = element.nextElementSibling; } } else { childElementCount = rootNode.childElementCount; } return childElementCount; } /** * Setups and prepares all necessary properties and start the rendering process. * This method has to be called only once (at the start) for the render cycle. */ }, { key: "start", value: function start() { this.collectedNodes.length = 0; this.visualIndex = 0; var rootNode = this.rootNode, sizeSet = this.sizeSet; var isShared = this.isSharedViewSet(); var _sizeSet$getViewSize = sizeSet.getViewSize(), nextSize = _sizeSet$getViewSize.nextSize; var childElementCount = this.getRenderedChildCount(); while (childElementCount < nextSize) { var newNode = this.nodesPool(); if (!isShared || isShared && sizeSet.isPlaceOn(_constants.WORKING_SPACE_BOTTOM)) { rootNode.appendChild(newNode); } else { rootNode.insertBefore(newNode, rootNode.firstChild); } childElementCount += 1; } var isSharedPlacedOnTop = isShared && sizeSet.isPlaceOn(_constants.WORKING_SPACE_TOP); while (childElementCount > nextSize) { rootNode.removeChild(isSharedPlacedOnTop ? rootNode.firstChild : rootNode.lastChild); childElementCount -= 1; } } /** * Renders the DOM element based on visual index (which is calculated internally). * This method has to be called as many times as the size count is met (to cover all previously rendered DOM elements). */ }, { key: "render", value: function render() { var rootNode = this.rootNode, sizeSet = this.sizeSet; var visualIndex = this.visualIndex; if (this.isSharedViewSet() && sizeSet.isPlaceOn(_constants.WORKING_SPACE_BOTTOM)) { visualIndex += sizeSet.sharedSize.nextSize; } var node = rootNode.childNodes[visualIndex]; if (node.tagName !== this.childNodeType) { var newNode = this.nodesPool(); rootNode.replaceChild(newNode, node); node = newNode; } this.collectedNodes.push(node); this.visualIndex += 1; } /** * Ends the render process. * This method has to be called only once (at the end) for the render cycle. */ }, { key: "end", value: function end() {} }]); return OrderView; }(); exports.default = OrderView;