UNPKG

angular2-data-table

Version:

angular2-data-table is a Angular2 component for presenting large and complex data.

446 lines 18.1 kB
"use strict"; var core_1 = require('@angular/core'); var utils_1 = require('../../utils'); var scroller_component_1 = require('./scroller.component'); var DataTableBodyComponent = (function () { function DataTableBodyComponent() { this.selected = []; this.scroll = new core_1.EventEmitter(); this.page = new core_1.EventEmitter(); this.activate = new core_1.EventEmitter(); this.select = new core_1.EventEmitter(); this.detailToggle = new core_1.EventEmitter(); this.rowContextmenu = new core_1.EventEmitter(false); this.rowHeightsCache = new utils_1.RowHeightCache(); this.temp = []; this.offsetY = 0; this.indexes = {}; // declare fn here so we can get access to the `this` property this.rowTrackingFn = function (index, row) { if (this.trackByProp) { return row.$$index + "-" + this.trackByProp; } else { return row.$$index; } }.bind(this); } Object.defineProperty(DataTableBodyComponent.prototype, "pageSize", { get: function () { return this._pageSize; }, set: function (val) { this._pageSize = val; this.recalcLayout(); }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "rows", { get: function () { return this._rows; }, set: function (val) { this._rows = val; this.recalcLayout(); }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "columns", { get: function () { return this._columns; }, set: function (val) { this._columns = val; var colsByPin = utils_1.columnsByPin(val); this.columnGroupWidths = utils_1.columnGroupWidths(colsByPin, val); }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "offset", { get: function () { return this._offset; }, set: function (val) { this._offset = val; this.recalcLayout(); }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "rowCount", { get: function () { return this._rowCount; }, set: function (val) { this._rowCount = val; this.recalcLayout(); }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "bodyWidth", { get: function () { if (this.scrollbarH) { return this.innerWidth + 'px'; } else { return '100%'; } }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "bodyHeight", { get: function () { return this._bodyHeight; }, set: function (val) { if (this.scrollbarV) { this._bodyHeight = val + 'px'; } else { this._bodyHeight = 'auto'; } this.recalcLayout(); }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "selectEnabled", { /** * Returns if selection is enabled. * * @readonly * @type {boolean} * @memberOf DataTableBodyComponent */ get: function () { return !!this.selectionType; }, enumerable: true, configurable: true }); Object.defineProperty(DataTableBodyComponent.prototype, "scrollHeight", { /** * Property that would calculate the height of scroll bar * based on the row heights cache for virtual scroll. Other scenarios * calculate scroll height automatically (as height will be undefined). * * @readonly * @type {number} * @memberOf DataTableBodyComponent */ get: function () { if (this.scrollbarV) { return this.rowHeightsCache.query(this.rowCount - 1); } }, enumerable: true, configurable: true }); /** * Updates the Y offset given a new offset. * * @param {number} [offset] * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.updateOffsetY = function (offset) { if (this.scrollbarV && offset) { // First get the row Index that we need to move to. var rowIndex = this.pageSize * offset; offset = this.rowHeightsCache.query(rowIndex - 1); } this.scroller.setOffset(offset || 0); }; /** * Body was scrolled, this is mainly useful for * when a user is server-side pagination via virtual scroll. * * @param {*} event * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.onBodyScroll = function (event) { var scrollYPos = event.scrollYPos; var scrollXPos = event.scrollXPos; // if scroll change, trigger update // this is mainly used for header cell positions if (this.offsetY !== scrollYPos || this.offsetX !== scrollXPos) { this.scroll.emit({ offsetY: scrollYPos, offsetX: scrollXPos }); } this.offsetY = scrollYPos; this.offsetX = scrollXPos; this.updateIndexes(); this.updatePage(event.direction); this.updateRows(); }; /** * Updates the page given a direction. * * @param {string} direction * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.updatePage = function (direction) { var offset = this.indexes.first / this.pageSize; if (direction === 'up') { offset = Math.floor(offset); } else if (direction === 'down') { offset = Math.ceil(offset); } if (direction !== undefined && !isNaN(offset)) { this.page.emit({ offset: offset }); } }; /** * Updates the rows in the view port * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.updateRows = function () { var _a = this.indexes, first = _a.first, last = _a.last; var rowIndex = first; var idx = 0; var temp = []; while (rowIndex < last && rowIndex < this.rowCount) { var row = this.rows[rowIndex]; if (row) { row.$$index = rowIndex; temp[idx] = row; } idx++; rowIndex++; } this.temp = temp; }; /** * Calculate row height based on the expanded state of the row. * * @param {*} row the row for which the height need to be calculated. * @returns {number} height of the row. * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.getRowHeight = function (row) { // Adding detail row height if its expanded. return this.rowHeight + (row.$$expanded === 1 ? this.detailRowHeight : 0); }; /** * Calculates the styles for the row so that the rows can be moved in 2D space * during virtual scroll inside the DOM. In the below case the Y position is * manipulated. As an example, if the height of row 0 is 30 px and row 1 is * 100 px then following styles are generated: * * transform: translate3d(0px, 0px, 0px); -> row0 * transform: translate3d(0px, 30px, 0px); -> row1 * transform: translate3d(0px, 130px, 0px); -> row2 * * Row heights have to be calculated based on the row heights cache as we wont * be able to determine which row is of what height before hand. In the above * case the positionY of the translate3d for row2 would be the sum of all the * heights of the rows before it (i.e. row0 and row1). * * @param {*} row The row that needs to be placed in the 2D space. * @returns {*} Returns the CSS3 style to be applied * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.getRowsStyles = function (row) { var rowHeight = this.getRowHeight(row); var styles = { height: rowHeight + 'px' }; if (this.scrollbarV) { var idx = row ? row.$$index : 0; // const pos = idx * rowHeight; // The position of this row would be the sum of all row heights // until the previous row position. var pos = this.rowHeightsCache.query(idx - 1); utils_1.translateXY(styles, 0, pos); } return styles; }; /** * Hides the loading indicator * * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.hideIndicator = function () { var _this = this; setTimeout(function () { return _this.loadingIndicator = false; }, 500); }; /** * Updates the index of the rows in the viewport * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.updateIndexes = function () { var first = 0; var last = 0; if (this.scrollbarV) { // Calculation of the first and last indexes will be based on where the // scrollY position would be at. The last index would be the one // that shows up inside the view port the last. var height = parseInt(this.bodyHeight, 0); first = this.rowHeightsCache.getRowIndex(this.offsetY); last = this.rowHeightsCache.getRowIndex(height + this.offsetY) + 1; } else { first = Math.max(this.offset * this.pageSize, 0); last = Math.min((first + this.pageSize), this.rowCount); } this.indexes = { first: first, last: last }; }; /** * Refreshes the full Row Height cache. Should be used * when the entire row array state has changed. * * @returns {void} * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.refreshRowHeightCache = function () { if (!this.scrollbarV) return; // clear the previous row height cache if already present. // this is useful during sorts, filters where the state of the // rows array is changed. this.rowHeightsCache.clearCache(); // Initialize the tree only if there are rows inside the tree. if (this.rows && this.rows.length) { this.rowHeightsCache.initCache(this.rows, this.rowHeight, this.detailRowHeight); } }; /** * Gets the index for the view port * * @returns {number} * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.getAdjustedViewPortIndex = function () { // Capture the row index of the first row that is visible on the viewport. // If the scroll bar is just below the row which is highlighted then make that as the // first index. var viewPortFirstRowIndex = this.indexes.first; if (this.scrollbarV) { var offsetScroll = this.rowHeightsCache.query(viewPortFirstRowIndex - 1); return offsetScroll <= this.offsetY ? viewPortFirstRowIndex - 1 : viewPortFirstRowIndex; } return viewPortFirstRowIndex; }; /** * Toggle the Expansion of the row i.e. if the row is expanded then it will * collapse and vice versa. Note that the expanded status is stored as * a part of the row object itself as we have to preserve the expanded row * status in case of sorting and filtering of the row set. * * @param {*} row The row for which the expansion needs to be toggled. * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.toggleRowExpansion = function (row) { // Capture the row index of the first row that is visible on the viewport. var viewPortFirstRowIndex = this.getAdjustedViewPortIndex(); // If the detailRowHeight is auto --> only in case of non-virtualized scroll if (this.scrollbarV) { var detailRowHeight = this.detailRowHeight * (row.$$expanded ? -1 : 1); this.rowHeightsCache.update(row.$$index, detailRowHeight); } // Update the toggled row and update the heights in the cache. row.$$expanded ^= 1; this.detailToggle.emit({ rows: [row], currentIndex: viewPortFirstRowIndex }); }; /** * Expand/Collapse all the rows no matter what their state is. * * @param {boolean} expanded When true, all rows are expanded and when false, all rows will be collapsed. * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.toggleAllRows = function (expanded) { var rowExpanded = expanded ? 1 : 0; // Capture the row index of the first row that is visible on the viewport. var viewPortFirstRowIndex = this.getAdjustedViewPortIndex(); for (var _i = 0, _a = this.rows; _i < _a.length; _i++) { var row = _a[_i]; row.$$expanded = rowExpanded; } if (this.scrollbarV) { // Refresh the full row heights cache since every row was affected. this.refreshRowHeightCache(); } // Emit all rows that have been expanded. this.detailToggle.emit({ rows: this.rows, currentIndex: viewPortFirstRowIndex }); }; /** * Recalculates the table * * @memberOf DataTableBodyComponent */ DataTableBodyComponent.prototype.recalcLayout = function () { this.refreshRowHeightCache(); this.updateIndexes(); this.updateRows(); }; DataTableBodyComponent.decorators = [ { type: core_1.Component, args: [{ selector: 'datatable-body', template: "\n <datatable-selection\n #selector\n [selected]=\"selected\"\n [rows]=\"temp\"\n [selectCheck]=\"selectCheck\"\n [selectEnabled]=\"selectEnabled\"\n [selectionType]=\"selectionType\"\n [rowIdentity]=\"rowIdentity\"\n (select)=\"select.emit($event)\"\n (activate)=\"activate.emit($event)\">\n <datatable-progress\n *ngIf=\"loadingIndicator\">\n </datatable-progress>\n <datatable-scroller\n *ngIf=\"rows?.length\"\n [scrollbarV]=\"scrollbarV\"\n [scrollbarH]=\"scrollbarH\"\n [scrollHeight]=\"scrollHeight\"\n [scrollWidth]=\"columnGroupWidths.total\"\n (scroll)=\"onBodyScroll($event)\">\n <datatable-row-wrapper\n *ngFor=\"let row of temp; let i = index; trackBy: rowTrackingFn;\"\n [ngStyle]=\"getRowsStyles(row)\"\n [rowDetailTemplate]=\"rowDetailTemplate\"\n [detailRowHeight]=\"detailRowHeight\"\n [row]=\"row\"\n [expanded]=\"row.$$expanded === 1\"\n (rowContextmenu)=\"rowContextmenu.emit($event)\">\n <datatable-body-row\n tabindex=\"-1\"\n [isSelected]=\"selector.getRowSelected(row)\"\n [innerWidth]=\"innerWidth\"\n [offsetX]=\"offsetX\"\n [columns]=\"columns\"\n [rowHeight]=\"rowHeight\"\n [row]=\"row\"\n (activate)=\"selector.onActivate($event, i)\">\n </datatable-body-row>\n </datatable-row-wrapper>\n </datatable-scroller>\n <div\n class=\"empty-row\"\n *ngIf=\"!rows?.length\"\n [innerHTML]=\"emptyMessage\">\n </div>\n </datatable-selection>\n ", host: { class: 'datatable-body' } },] }, ]; /** @nocollapse */ DataTableBodyComponent.ctorParameters = function () { return []; }; DataTableBodyComponent.propDecorators = { 'scrollbarV': [{ type: core_1.Input },], 'scrollbarH': [{ type: core_1.Input },], 'loadingIndicator': [{ type: core_1.Input },], 'rowHeight': [{ type: core_1.Input },], 'offsetX': [{ type: core_1.Input },], 'detailRowHeight': [{ type: core_1.Input },], 'emptyMessage': [{ type: core_1.Input },], 'selectionType': [{ type: core_1.Input },], 'selected': [{ type: core_1.Input },], 'rowIdentity': [{ type: core_1.Input },], 'rowDetailTemplate': [{ type: core_1.Input },], 'selectCheck': [{ type: core_1.Input },], 'trackByProp': [{ type: core_1.Input },], 'pageSize': [{ type: core_1.Input },], 'rows': [{ type: core_1.Input },], 'columns': [{ type: core_1.Input },], 'offset': [{ type: core_1.Input },], 'rowCount': [{ type: core_1.Input },], 'innerWidth': [{ type: core_1.Input },], 'bodyWidth': [{ type: core_1.HostBinding, args: ['style.width',] },], 'bodyHeight': [{ type: core_1.Input }, { type: core_1.HostBinding, args: ['style.height',] },], 'scroll': [{ type: core_1.Output },], 'page': [{ type: core_1.Output },], 'activate': [{ type: core_1.Output },], 'select': [{ type: core_1.Output },], 'detailToggle': [{ type: core_1.Output },], 'rowContextmenu': [{ type: core_1.Output },], 'scroller': [{ type: core_1.ViewChild, args: [scroller_component_1.ScrollerComponent,] },], }; return DataTableBodyComponent; }()); exports.DataTableBodyComponent = DataTableBodyComponent; //# sourceMappingURL=body.component.js.map