"use strict"; /** * EGroupware eTemplate2 - dataview code * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package etemplate * @subpackage dataview * @link http://www.egroupware.org * @author Andreas Stöckel * @copyright Stylite 2012 * @version $Id$ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.et2_dataview_container = void 0; /** * The et2_dataview_container class is the main object each dataview consits of. * Each row, spacer as well as the grid itself are containers. A container is * described by its parent element and a certain height. On the DOM-Level a * container may consist of multiple "tr" nodes, which are treated as a unit. * Some containers (like grid containers) are capable of managing a set of child * containers. Each container can indicate, that it thinks that it's height * might have changed. In that case it informs its parent element about that. * The only requirement for the parent element is, that it implements the * et2_dataview_IInvalidatable interface. * A container does not know where it resides inside the grid, or whether it is * currently visible or not -- this information is efficiently managed by the * et2_dataview_grid container. * * @augments Class */ var et2_dataview_container = /** @class */ (function () { /** * Initializes the container object. * * @param _parent is an object which implements the IInvalidatable * interface. _parent may not be null. * @memberOf et2_dataview_container */ function et2_dataview_container(_parent) { // Copy the given invalidation element this._parent = _parent; this._nodes = []; this._inTree = false; this._attachData = { "node": null, "prepend": false }; this._destroyCallback = null; this._destroyContext = null; this._height = -1; this._index = 0; this._top = 0; } /** * Destroys this container. Classes deriving from et2_dataview_container * should override this method and take care of unregistering all event * handlers etc. */ et2_dataview_container.prototype.destroy = function () { // Remove the nodes from the tree this.removeFromTree(); // Call the callback function (if one is registered) if (this._destroyCallback) { this._destroyCallback.call(this._destroyContext, this); } }; /** * Sets the "destroyCallback" -- the given function gets called whenever * the container is destroyed. This instance is passed as an parameter to * the callback. * * @param {function} _callback * @param {object} _context */ et2_dataview_container.prototype.setDestroyCallback = function (_callback, _context) { this._destroyCallback = _callback; this._destroyContext = _context; }; /** * Inserts all container nodes into the DOM tree after or before the given * element. * * @param _node is the node after/before which the container "tr"s should * get inserted. _node should be a simple DOM node, not a jQuery object. * @param _prepend specifies whether the container should be inserted before * or after the given node. Inserting before is needed for inserting the * first element in front of an spacer. */ et2_dataview_container.prototype.insertIntoTree = function (_node, _prepend) { if (!this._inTree && _node != null && this._nodes.length > 0) { // Store the parent node and indicate that this element is now in // the tree. this._attachData = { node: _node, prepend: _prepend }; this._inTree = true; for (var i = 0; i < this._nodes.length; i++) { if (i == 0) { if (_prepend) { _node.before(this._nodes[0]); } else { _node.after(this._nodes[0]); } } else { // Insert all following nodes after the previous node this._nodes[i - 1].after(this._nodes[i]); } } // Invalidate this element in order to update the height of the // parent this.invalidate(); } }; /** * Removes all container nodes from the tree. */ et2_dataview_container.prototype.removeFromTree = function () { if (this._inTree) { // Call the jQuery remove function to remove all nodes from the tree // again. for (var i = 0; i < this._nodes.length; i++) { this._nodes[i].remove(); } // Reset the "attachData" this._inTree = false; this._attachData = { "node": null, "prepend": false }; } }; /** * Appends a node to the container. * * @param _node is the DOM-Node which should be appended. */ et2_dataview_container.prototype.appendNode = function (_node) { // Add the given node to the "nodes" array this._nodes.push(_node); // If the container is already in the tree, attach the given node to the // tree. if (this._inTree) { if (this._nodes.length === 1) { if (this._attachData.prepend) { this._attachData.node.before(_node); } else { this._attachData.node.after(_node); } } else { this._nodes[this._nodes.length - 2].after(_node); } this.invalidate(); } }; /** * Removes a certain node from the container * * @param {HTMLElement} _node */ et2_dataview_container.prototype.removeNode = function (_node) { // Get the index of the node in the nodes array var idx = this._nodes.indexOf(_node); if (idx >= 0) { // Remove the node if the container is currently attached if (this._inTree) { _node.parentNode.removeChild(_node); } // Remove the node from the nodes array this._nodes.splice(idx, 1); } }; /** * Returns the last node of the container - new nodes have to be appended * after it. */ et2_dataview_container.prototype.getLastNode = function () { if (this._nodes.length > 0) { return this._nodes[this._nodes.length - 1]; } return null; }; /** * Returns the first node of the container. */ et2_dataview_container.prototype.getFirstNode = function () { return this._nodes.length > 0 ? this._nodes[0] : null; }; /** * Returns the accumulated height of all container nodes. Only visible nodes * (without "display: none" etc.) are taken into account. */ et2_dataview_container.prototype.getHeight = function () { if (this._height === -1 && this._inTree) { this._height = 0; // Setting this before measuring height helps with issues getting the // wrong height due to margins & collapsed borders this.tr.css('display', 'block'); // Increment the height value for each visible container node for (var i = 0; i < this._nodes.length; i++) { if (et2_dataview_container._isVisible(this._nodes[i][0])) { this._height += et2_dataview_container._nodeHeight(this._nodes[i][0]); } } this.tr.css('display', ''); } return (this._height === -1) ? 0 : this._height; }; /** * Returns a datastructure containing information used for calculating the * average row height of a grid. * The datastructure has the * { * avgHeight: , * avgCount: * } */ et2_dataview_container.prototype.getAvgHeightData = function () { return { "avgHeight": this.getHeight(), "avgCount": 1 }; }; /** * Returns the previously set "pixel top" of the container. */ et2_dataview_container.prototype.getTop = function () { return this._top; }; /** * Returns the "pixel bottom" of the container. */ et2_dataview_container.prototype.getBottom = function () { return this._top + this.getHeight(); }; /** * Returns the range of the element. */ et2_dataview_container.prototype.getRange = function () { return et2_bounds(this.getTop(), this.getBottom()); }; /** * Returns the index of the element. */ et2_dataview_container.prototype.getIndex = function () { return this._index; }; /** * Returns how many elements this container represents. */ et2_dataview_container.prototype.getCount = function () { return 1; }; /** * Sets the top of the element. * * @param {number} _value */ et2_dataview_container.prototype.setTop = function (_value) { this._top = _value; }; /** * Sets the index of the element. * * @param {number} _value */ et2_dataview_container.prototype.setIndex = function (_value) { this._index = _value; }; /* -- et2_dataview_IInvalidatable -- */ /** * Broadcasts an invalidation through the container tree. Marks the own * height as invalid. */ et2_dataview_container.prototype.invalidate = function () { // Abort if this element is already marked as invalid. if (this._height !== -1) { // Delete the own, probably computed height this._height = -1; // Broadcast the invalidation to the parent element this._parent.invalidate(); } }; /* -- PRIVATE FUNCTIONS -- */ /** * Used to check whether an element is visible or not (non recursive). * * @param _obj is the element which should be checked for visibility, it is * only checked whether some stylesheet makes the element invisible, not if * the given object is actually inside the DOM. */ et2_dataview_container._isVisible = function (_obj) { // Check whether the element is localy invisible if (_obj.style && (_obj.style.display === "none" || _obj.style.visibility === "none")) { return false; } // Get the computed style of the element var style = window.getComputedStyle ? window.getComputedStyle(_obj, null) // @ts-ignore : _obj.currentStyle; if (style.display === "none" || style.visibility === "none") { return false; } return true; }; /** * Returns the height of a node in pixels and zero if the element is not * visible. The height is clamped to positive values. * * @param {HTMLElement} _node */ et2_dataview_container._nodeHeight = function (_node) { return _node.offsetHeight; }; return et2_dataview_container; }()); exports.et2_dataview_container = et2_dataview_container; //# sourceMappingURL=et2_dataview_view_container.js.map