handsontable
Version:
Handsontable is a JavaScript Data Grid available for React, Angular and Vue.
190 lines (180 loc) • 6.16 kB
JavaScript
"use strict";
exports.__esModule = true;
require("core-js/modules/es.error.cause.js");
require("core-js/modules/es.array.push.js");
var _viewSizeSet = require("./viewSizeSet");
var _viewDiffer = require("./viewDiffer");
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); }
/**
* 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}
*/
class OrderView {
constructor(rootNode, nodesPool) {
/**
* The root node to manage with.
*
* @type {HTMLElement}
*/
_defineProperty(this, "rootNode", void 0);
/**
* Factory for newly created DOM elements.
*
* @type {function(number): HTMLElement}
*/
_defineProperty(this, "nodesPool", void 0);
/**
* Holder for sizing and positioning of the view.
*
* @type {ViewSizeSet}
*/
_defineProperty(this, "sizeSet", new _viewSizeSet.ViewSizeSet());
/**
* The list of DOM elements which are rendered for this render cycle.
*
* @type {HTMLElement[]}
*/
_defineProperty(this, "collectedNodes", []);
/**
* The differ which calculates the differences between current and next view. It generates
* commands that are processed by the OrderView (see `applyCommand` method).
*
* @type {ViewDiffer}
*/
_defineProperty(this, "viewDiffer", new _viewDiffer.ViewDiffer(this.sizeSet));
/**
* The list of render commands to execute. The command is an array with the following
* structure: [
* [
* 'prepend' | 'append' | 'insert_before' | 'replace' | 'remove', // command name
* 10, // processed node index
* 9, // previous node index (only for 'insert_before' and 'replace' commands)
* 8 // node index to remove (only for 'insert_before' command)
* ],
* ...
* ].
*
* @type {Array[]}
*/
_defineProperty(this, "leads", []);
this.rootNode = rootNode;
this.nodesPool = nodesPool;
}
/**
* 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}
*/
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}
*/
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}
*/
isSharedViewSet() {
return this.sizeSet.isShared();
}
/**
* Returns rendered DOM element based on visual index.
*
* @param {number} visualIndex The visual index.
* @returns {HTMLElement}
*/
getNode(visualIndex) {
return visualIndex < this.collectedNodes.length ? this.collectedNodes[visualIndex] : null;
}
/**
* Returns currently processed DOM element.
*
* @returns {HTMLElement}
*/
getCurrentNode() {
const length = this.collectedNodes.length;
return length > 0 ? this.collectedNodes[length - 1] : null;
}
/**
* Applies the commands generated by the differ into the specific DOM operations.
*
* @param {Array} command The command to apply.
*/
applyCommand(command) {
const {
rootNode
} = this;
const [name, nodeIndex, nodePrevIndex, nodeIndexToRemove] = command;
const node = this.nodesPool(nodeIndex);
this.collectedNodes.push(node);
switch (name) {
case 'prepend':
rootNode.insertBefore(node, rootNode.firstChild);
break;
case 'append':
rootNode.appendChild(node);
break;
case 'insert_before':
rootNode.insertBefore(node, this.nodesPool(nodePrevIndex));
// To keep the constant length of child nodes (after inserting a node) remove the last child.
rootNode.removeChild(this.nodesPool(nodeIndexToRemove));
break;
case 'replace':
rootNode.replaceChild(node, this.nodesPool(nodePrevIndex));
break;
case 'remove':
rootNode.removeChild(node);
break;
default:
break;
}
}
/**
* 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.
*/
start() {
this.collectedNodes.length = 0;
this.leads = this.viewDiffer.diff();
}
/**
* 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).
*/
render() {
if (this.leads.length > 0) {
this.applyCommand(this.leads.shift());
}
}
/**
* Ends the render process.
* This method has to be called only once (at the end) for the render cycle.
*/
end() {
while (this.leads.length > 0) {
this.applyCommand(this.leads.shift());
}
}
}
exports.OrderView = OrderView;