"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 2011-2012
 * @version $Id$
 *

/*egw:uses
    /vendor/bower-asset/jquery/dist/jquery.js;
    et2_core_common;

    et2_dataview_model_columns;
    et2_dataview_view_grid;
    et2_dataview_view_rowProvider;
    et2_dataview_view_resizeable;
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.et2_dataview = void 0;
var et2_dataview_model_columns_1 = require("./et2_dataview_model_columns");
var et2_dataview_view_resizeable_1 = require("./et2_dataview_view_resizeable");
var et2_dataview_view_grid_1 = require("./et2_dataview_view_grid");
var et2_dataview_view_rowProvider_1 = require("./et2_dataview_view_rowProvider");
/**
 * The et2_dataview class is the main class for displaying a dataview. The
 * dataview class manages the creation of the outer html nodes (like the table,
 * header, etc.) and contains the root container: an instance of
 * et2_dataview_view_grid, which can be accessed using the "grid" property of
 * this object.
 *
 * @augments Class
 */
var et2_dataview = /** @class */ (function () {
    /**
     * Constructor for the grid container
     *
     * @param {DOMElement} _parentNode is the DOM-Node into which the grid view will be inserted
     * @param {egw} _egw
     * @memberOf et2_dataview
     */
    function et2_dataview(_parentNode, _egw) {
        // Copy the arguments
        this.parentNode = jQuery(_parentNode);
        this.egw = _egw;
        // Initialize some variables
        this.columnNodes = []; // Array with the header containers
        this.columns = [];
        this.columnMgr = null;
        this.rowProvider = null;
        this.width = 0;
        this.height = 0;
        this.uniqueId = "gridCont_" + this.egw.uid();
        // Build the base nodes
        this._createElements();
        // Read the browser dependant variables
        this._getDepVars();
    }
    /**
     * Destroys the object, removes all dom nodes and clears all references.
     */
    et2_dataview.prototype.destroy = function () {
        // Clear the columns
        this._clearHeader();
        // Free the grid
        if (this.grid) {
            this.grid.destroy();
        }
        // Free the row provider
        if (this.rowProvider) {
            this.rowProvider.destroy();
        }
        // Detatch the outer element
        this.table.remove();
    };
    /**
     * Clears all data rows and reloads them
     */
    et2_dataview.prototype.clear = function () {
        if (this.grid) {
            this.grid.clear();
        }
    };
    /**
     * Returns the column container node for the given column index
     *
     * @param _columnIdx the integer column index
     */
    et2_dataview.prototype.getHeaderContainerNode = function (_columnIdx) {
        if (typeof this.columnNodes[_columnIdx] != "undefined") {
            return this.columnNodes[_columnIdx].container[0];
        }
        return null;
    };
    /**
     * Sets the column descriptors and creates the column header according to it.
     * The inner grid will be emptied if it has already been built.
     */
    et2_dataview.prototype.setColumns = function (_columnData) {
        // Free all column objects which have been created till this moment
        this._clearHeader();
        // Copy the given column data
        this.columnMgr = new et2_dataview_model_columns_1.et2_dataview_columns(_columnData);
        // Create the stylesheets
        this.updateColumns();
        // Build the header row
        this._buildHeader();
        // Build the grid
        this._buildGrid();
    };
    /**
     * Resizes the grid
     */
    et2_dataview.prototype.resize = function (_w, _h) {
        // Not fully initialized yet...
        if (!this.columnMgr)
            return;
        if (this.width != _w) {
            this.width = _w;
            // Take grid border width into account
            _w -= (this.table.outerWidth(true) - this.table.innerWidth());
            // Take grid header border's width into account. eg. category colors may add extra pixel into width
            _w = _w - (this.thead.find('tr').outerWidth() - this.thead.find('tr').innerWidth());
            // Rebuild the column stylesheets
            this.columnMgr.setTotalWidth(_w - this.scrollbarWidth);
            this._updateColumns();
        }
        if (this.height != _h) {
            this.height = _h;
            // Set the height of the grid.
            if (this.grid) {
                this.grid.setScrollHeight(this.height -
                    this.headTr.outerHeight(true));
            }
        }
    };
    /**
     * Returns the column manager object. You can use it to set the visibility
     * of columns etc. Call "updateHeader" if you did any changes.
     */
    et2_dataview.prototype.getColumnMgr = function () {
        return this.columnMgr;
    };
    /**
     * Recalculates the stylesheets which determine the column visibility and
     * width.
     *
     * @param setDefault boolean Allow admins to save current settings as default for all users
     */
    et2_dataview.prototype.updateColumns = function (setDefault) {
        if (setDefault === void 0) { setDefault = false; }
        if (this.columnMgr) {
            this._updateColumns();
        }
        // Ability to notify parent / someone else
        if (this.onUpdateColumns) {
            this.onUpdateColumns(setDefault);
        }
    };
    /* --- PRIVATE FUNCTIONS --- */
    /* --- Code for building the grid container DOM-Tree elements ---- */
    /**
     * Builds the base DOM-Tree elements
     */
    et2_dataview.prototype._createElements = function () {
        /*
            Structure:
            <table class="egwGridView_outer">
                <thead>
                    <tr> [HEAD] </tr>
                </thead>
                <tbody>
                    <tr> [GRID CONTAINER] </tr>
                </tbody>
            </table>
        */
        this.containerTr = jQuery(document.createElement("tr"));
        this.headTr = jQuery(document.createElement("tr"));
        this.thead = jQuery(document.createElement("thead"))
            .append(this.headTr);
        this.tbody = jQuery(document.createElement("tbody"))
            .append(this.containerTr);
        this.table = jQuery(document.createElement("table"))
            .addClass("egwGridView_outer")
            .append(this.thead, this.tbody)
            .appendTo(this.parentNode);
    };
    /* --- Code for building the header row --- */
    /**
     * Clears the header row
     */
    et2_dataview.prototype._clearHeader = function () {
        if (this.columnMgr) {
            this.columnMgr.destroy();
            this.columnMgr = null;
        }
        // Remove dynamic CSS,
        for (var i = 0; i < this.columns.length; i++) {
            if (this.columns[i].tdClass) {
                this.egw.css('.' + this.columns[i].tdClass);
            }
            if (this.columns[i].divClass) {
                this.egw.css('.' + this.columns[i].divClass);
                this.egw.css(".egwGridView_outer ." + this.columns[i].divClass);
                this.egw.css(".egwGridView_grid ." + this.columns[i].divClass);
            }
        }
        this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow");
        this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow");
        this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow");
        // Reset the headerColumns array and empty the table row
        this.columnNodes = [];
        this.columns = [];
        this.headTr.empty();
    };
    /**
     * Sets the column data which is retrieved by calling egwGridColumns.getColumnData.
     * The columns will be updated.
     */
    et2_dataview.prototype._updateColumns = function () {
        // Copy the columns data
        this.columns = this.columnMgr.getColumnData();
        // Count the visible rows
        var total_cnt = 0;
        for (var i = 0; i < this.columns.length; i++) {
            if (this.columns[i].visible) {
                total_cnt++;
            }
        }
        // Set the grid column styles
        var first = true;
        var vis_col = this.visibleColumnCount = 0;
        var totalWidth = 0;
        for (var i = 0; i < this.columns.length; i++) {
            var col = this.columns[i];
            col.tdClass = this.uniqueId + "_td_" + col.id;
            col.divClass = this.uniqueId + "_div_" + col.id;
            if (col.visible) {
                vis_col++;
                this.visibleColumnCount++;
                // Update the visibility of the column
                this.egw.css("." + col.tdClass, "display: table-cell; " +
                    "!important;");
                // Ugly browser dependant code - each browser seems to treat the
                // right (collapsed) border of the row differently
                var subBorder = 0;
                var subHBorder = 0;
                /*
                if (jQuery.browser.mozilla)
                {
                    var maj = jQuery.browser.version.split(".")[0];
                    if (maj < 2) {
                        subBorder = 1; // Versions <= FF 3.6
                    }
                }
                if (jQuery.browser.webkit)
                {
                    if (!first)
                    {
                        subBorder = 1;
                    }
                    subHBorder = 1;
                }
                if ((jQuery.browser.msie || jQuery.browser.opera) && first)
                {
                    subBorder = -1;
                }
                */
                // Make the last columns one pixel smaller, to prevent a horizontal
                // scrollbar from showing up
                if (vis_col == total_cnt) {
                    subBorder += 1;
                }
                // Write the width of the header columns
                var headerWidth = Math.max(0, (col.width - this.headerBorderWidth - subHBorder));
                this.egw.css(".egwGridView_outer ." + col.divClass, "width: " + headerWidth + "px;");
                // Write the width of the body-columns
                var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - subBorder));
                this.egw.css(".egwGridView_grid ." + col.divClass, "width: " + columnWidth + "px;");
                totalWidth += col.width;
                first = false;
            }
            else {
                this.egw.css("." + col.tdClass, "display: none;");
            }
        }
        // Add the full row and spacer class
        this.egw.css(".egwGridView_grid ." + this.uniqueId + "_div_fullRow", "width: " + (totalWidth - this.columnBorderWidth - 2) + "px; border-right-width: 0 !important;");
        this.egw.css(".egwGridView_outer ." + this.uniqueId + "_td_fullRow", "border-right-width: 0 !important;");
        this.egw.css(".egwGridView_outer ." + this.uniqueId + "_spacer_fullRow", "width: " + (totalWidth - 1) + "px; border-right-width: 0 !important;");
    };
    /**
     * Builds the containers for the header row
     */
    et2_dataview.prototype._buildHeader = function () {
        var self = this;
        var handler = function (event) {
        };
        for (var i = 0; i < this.columns.length; i++) {
            var col = this.columns[i];
            // Create the column header and the container element
            var cont = jQuery(document.createElement("div"))
                .addClass("innerContainer")
                .addClass(col.divClass);
            var column = jQuery(document.createElement("th"))
                .addClass(col.tdClass)
                .attr("align", "left")
                .append(cont)
                .appendTo(this.headTr);
            if (this.columnMgr && this.columnMgr.getColumnById(i)) {
                column.addClass(this.columnMgr.getColumnById(i).fixedWidth ? 'fixedWidth' : 'relativeWidth');
                if (this.columnMgr.getColumnById(i).visibility === et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT) {
                    column.addClass('noResize');
                }
            }
            // make column resizable
            var enc_column = self.columnMgr.getColumnById(col.id);
            if (enc_column.visibility !== et2_dataview_column.ET2_COL_VISIBILITY_ALWAYS_NOSELECT) {
                et2_dataview_view_resizeable_1.et2_dataview_view_resizable.makeResizeable(column, function (_w) {
                    // User wants the column to stay where they put it, even for relative
                    // width columns, so set it explicitly first and adjust other relative
                    // columns to match.
                    if (this.relativeWidth) {
                        // Set to selected width
                        this.set_width(_w + "px");
                        self.columnMgr.updated();
                        // Just triggers recalculation
                        self.columnMgr.getColumnWidth(0);
                        // Set relative widths to match
                        var relative = self.columnMgr.totalWidth - self.columnMgr.totalFixed + _w;
                        this.set_width(_w / relative);
                        for (var i = 0; i < self.columnMgr.columnCount(); i++) {
                            var col = self.columnMgr.getColumnById('col_' + i);
                            if (!col || col == this || col.fixedWidth)
                                continue;
                            col.set_width(self.columnMgr.getColumnWidth(i) / relative);
                        }
                        // Triggers column change callback, which saves
                        self.updateColumns();
                    }
                    else {
                        this.set_width(this.relativeWidth ? (_w / self.columnMgr.totalWidth) : _w + "px");
                        self.columnMgr.updated();
                        self.updateColumns();
                    }
                }, enc_column);
            }
            // Store both nodes in the columnNodes array
            this.columnNodes.push({
                "column": column,
                "container": cont
            });
        }
        this._buildSelectCol();
    };
    /**
     * Builds the select cols column
     */
    et2_dataview.prototype._buildSelectCol = function () {
        // Build the "select columns" icon
        this.selectColIcon = jQuery(document.createElement("span"))
            .addClass("selectcols")
            .css('display', 'inline-block'); // otherwise jQuery('span.selectcols',this.dataview.headTr).show() set it to "inline" causing it to not show up because 0 height
        // Build the option column
        this.selectCol = jQuery(document.createElement("th"))
            .addClass("optcol")
            .append(this.selectColIcon)
            // Toggle display of option popup
            .click(this, function (e) { if (e.data.selectColumnsClick)
            e.data.selectColumnsClick(e); })
            .appendTo(this.headTr);
        this.selectCol.css("width", this.scrollbarWidth - this.selectCol.outerWidth()
            + this.selectCol.width() + 1);
    };
    /**
     * Builds the inner grid class
     */
    et2_dataview.prototype._buildGrid = function () {
        // Create the collection of column ids
        var colIds = [];
        for (var i = 0; i < this.columns.length; i++) {
            if (this.columns[i].visible) {
                colIds[i] = this.columns[i].id;
            }
        }
        // Create the row provider
        if (this.rowProvider) {
            this.rowProvider.destroy();
        }
        this.rowProvider = new et2_dataview_view_rowProvider_1.et2_dataview_rowProvider(this.uniqueId, colIds);
        // Create the grid class and pass "19" as the starting average row height
        this.grid = new et2_dataview_view_grid_1.et2_dataview_grid(null, null, this.egw, this.rowProvider, 19);
        // Insert the grid into the DOM-Tree
        var tr = jQuery(this.grid.getFirstNode());
        this.containerTr.replaceWith(tr);
        this.containerTr = tr;
    };
    /* --- Code for calculating the browser/css depending widths --- */
    /**
     * Reads the browser dependant variables
     */
    et2_dataview.prototype._getDepVars = function () {
        if (typeof this.scrollbarWidth === 'undefined') {
            // Clone the table and attach it to the outer body tag
            var clone = this.table.clone();
            jQuery(egw.top.document.getElementsByTagName("body")[0])
                .append(clone);
            // Read the scrollbar width
            this.scrollbarWidth = this.constructor.prototype.scrollbarWidth =
                this._getScrollbarWidth(clone);
            // Read the header border width
            this.headerBorderWidth = this.constructor.prototype.headerBorderWidth =
                this._getHeaderBorderWidth(clone);
            // Read the column border width
            this.columnBorderWidth = this.constructor.prototype.columnBorderWidth =
                this._getColumnBorderWidth(clone);
            // Remove the cloned DOM-Node again from the outer body
            clone.remove();
        }
    };
    /**
     * Reads the scrollbar width
     */
    et2_dataview.prototype._getScrollbarWidth = function (_table) {
        // Create a temporary td and two divs, which are inserted into the
        // DOM-Tree. The outer div has a fixed size and "overflow" set to auto.
        // When the second div is inserted, it will be forced to display a scrollbar.
        var div_inner = jQuery(document.createElement("div"))
            .css("height", "1000px");
        var div_outer = jQuery(document.createElement("div"))
            .css("height", "100px")
            .css("width", "100px")
            .css("overflow", "auto")
            .append(div_inner);
        var td = jQuery(document.createElement("td"))
            .append(div_outer);
        // Store the scrollbar width statically.
        jQuery("tbody tr", _table).append(td);
        var width = Math.max(10, div_outer.outerWidth() - div_inner.outerWidth());
        // Remove the elements again
        div_outer.remove();
        return width;
    };
    /**
     * Calculates the total width of the header column border
     */
    et2_dataview.prototype._getHeaderBorderWidth = function (_table) {
        // Create a temporary th which is appended to the outer thead row
        var cont = jQuery(document.createElement("div"))
            .addClass("innerContainer");
        var th = jQuery(document.createElement("th"))
            .append(cont);
        // Insert the th into the document tree
        jQuery("thead tr", _table).append(th);
        // Calculate the total border width
        var width = th.outerWidth(true) - cont.width();
        // Remove the appended element again
        th.remove();
        return width;
    };
    /**
     * Calculates the total width of the column border
     */
    et2_dataview.prototype._getColumnBorderWidth = function (_table) {
        // Create a temporary th which is appended to the outer thead row
        var cont = jQuery(document.createElement("div"))
            .addClass("innerContainer");
        var td = jQuery(document.createElement("td"))
            .append(cont);
        // Insert the th into the document tree
        jQuery("tbody tr", _table).append(td);
        // Calculate the total border width
        _table.addClass("egwGridView_grid");
        var width = td.outerWidth(true) - cont.width();
        // Remove the appended element again
        td.remove();
        return width;
    };
    return et2_dataview;
}());
exports.et2_dataview = et2_dataview;
//# sourceMappingURL=et2_dataview.js.map