UNPKG

@swimlane/ngx-datatable

Version:

ngx-datatable is an Angular table grid component for presenting large and complex data.

138 lines 16.2 kB
/** * This object contains the cache of the various row heights that are present inside * the data table. Its based on Fenwick tree data structure that helps with * querying sums that have time complexity of log n. * * Fenwick Tree Credits: http://petr-mitrichev.blogspot.com/2013/05/fenwick-tree-range-updates.html * https://github.com/mikolalysenko/fenwick-tree * */ export class RowHeightCache { constructor() { /** * Tree Array stores the cumulative information of the row heights to perform efficient * range queries and updates. Currently the tree is initialized to the base row * height instead of the detail row height. */ this.treeArray = []; } /** * Clear the Tree array. */ clearCache() { this.treeArray = []; } /** * Initialize the Fenwick tree with row Heights. * * @param rows The array of rows which contain the expanded status. * @param rowHeight The row height. * @param detailRowHeight The detail row height. */ initCache(details) { const { rows, rowHeight, detailRowHeight, externalVirtual, rowCount, rowIndexes, rowExpansions } = details; const isFn = typeof rowHeight === 'function'; const isDetailFn = typeof detailRowHeight === 'function'; if (!isFn && isNaN(rowHeight)) { throw new Error(`Row Height cache initialization failed. Please ensure that 'rowHeight' is a valid number or function value: (${rowHeight}) when 'scrollbarV' is enabled.`); } // Add this additional guard in case detailRowHeight is set to 'auto' as it wont work. if (!isDetailFn && isNaN(detailRowHeight)) { throw new Error(`Row Height cache initialization failed. Please ensure that 'detailRowHeight' is a valid number or function value: (${detailRowHeight}) when 'scrollbarV' is enabled.`); } const n = externalVirtual ? rowCount : rows.length; this.treeArray = new Array(n); for (let i = 0; i < n; ++i) { this.treeArray[i] = 0; } for (let i = 0; i < n; ++i) { const row = rows[i]; let currentRowHeight = rowHeight; if (isFn) { currentRowHeight = rowHeight(row); } // Add the detail row height to the already expanded rows. // This is useful for the table that goes through a filter or sort. const expanded = rowExpansions.has(row); if (row && expanded) { if (isDetailFn) { const index = rowIndexes.get(row); currentRowHeight += detailRowHeight(row, index); } else { currentRowHeight += detailRowHeight; } } this.update(i, currentRowHeight); } } /** * Given the ScrollY position i.e. sum, provide the rowIndex * that is present in the current view port. Below handles edge cases. */ getRowIndex(scrollY) { if (scrollY === 0) return 0; return this.calcRowIndex(scrollY); } /** * When a row is expanded or rowHeight is changed, update the height. This can * be utilized in future when Angular Data table supports dynamic row heights. */ update(atRowIndex, byRowHeight) { if (!this.treeArray.length) { throw new Error(`Update at index ${atRowIndex} with value ${byRowHeight} failed: Row Height cache not initialized.`); } const n = this.treeArray.length; atRowIndex |= 0; while (atRowIndex < n) { this.treeArray[atRowIndex] += byRowHeight; atRowIndex |= atRowIndex + 1; } } /** * Range Sum query from 1 to the rowIndex */ query(atIndex) { if (!this.treeArray.length) { throw new Error(`query at index ${atIndex} failed: Fenwick tree array not initialized.`); } let sum = 0; atIndex |= 0; while (atIndex >= 0) { sum += this.treeArray[atIndex]; atIndex = (atIndex & (atIndex + 1)) - 1; } return sum; } /** * Find the total height between 2 row indexes */ queryBetween(atIndexA, atIndexB) { return this.query(atIndexB) - this.query(atIndexA - 1); } /** * Given the ScrollY position i.e. sum, provide the rowIndex * that is present in the current view port. */ calcRowIndex(sum) { if (!this.treeArray.length) return 0; let pos = -1; const dataLength = this.treeArray.length; // Get the highest bit for the block size. const highestBit = Math.pow(2, dataLength.toString(2).length - 1); for (let blockSize = highestBit; blockSize !== 0; blockSize >>= 1) { const nextPos = pos + blockSize; if (nextPos < dataLength && sum >= this.treeArray[nextPos]) { sum -= this.treeArray[nextPos]; pos = nextPos; } } return pos + 1; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm93LWhlaWdodC1jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N3aW1sYW5lL25neC1kYXRhdGFibGUvc3JjL2xpYi91dGlscy9yb3ctaGVpZ2h0LWNhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFPLGNBQWM7SUFBM0I7UUFDRTs7OztXQUlHO1FBQ0ssY0FBUyxHQUFhLEVBQUUsQ0FBQztJQTJJbkMsQ0FBQztJQXpJQzs7T0FFRztJQUNILFVBQVU7UUFDUixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsU0FBUyxDQUFDLE9BQVk7UUFDcEIsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUMzRyxNQUFNLElBQUksR0FBRyxPQUFPLFNBQVMsS0FBSyxVQUFVLENBQUM7UUFDN0MsTUFBTSxVQUFVLEdBQUcsT0FBTyxlQUFlLEtBQUssVUFBVSxDQUFDO1FBRXpELElBQUksQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQzdCLE1BQU0sSUFBSSxLQUFLLENBQUM7MkNBQ3FCLFNBQVMsaUNBQWlDLENBQUMsQ0FBQztTQUNsRjtRQUVELHNGQUFzRjtRQUN0RixJQUFJLENBQUMsVUFBVSxJQUFJLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBRTtZQUN6QyxNQUFNLElBQUksS0FBSyxDQUFDOzJDQUNxQixlQUFlLGlDQUFpQyxDQUFDLENBQUM7U0FDeEY7UUFFRCxNQUFNLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUNuRCxJQUFJLENBQUMs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O0lBQ0ssWUFBWSxDQUFDLEdBQVc7UUFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTTtZQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXJDLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2IsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7UUFFekMsMENBQTBDO1FBQzFDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRWxFLEtBQUssSUFBSSxTQUFTLEdBQUcsVUFBVSxFQUFFLFNBQVMsS0FBSyxDQUFDLEVBQUUsU0FBUyxLQUFLLENBQUMsRUFBRTtZQUNqRSxNQUFNLE9BQU8sR0FBRyxHQUFHLEdBQUcsU0FBUyxDQUFDO1lBQ2hDLElBQUksT0FBTyxHQUFHLFVBQVUsSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDMUQsR0FBRyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQy9CLEdBQUcsR0FBRyxPQUFPLENBQUM7YUFDZjtTQUNGO1FBRUQsT0FBTyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQ2pCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhpcyBvYmplY3QgY29udGFpbnMgdGhlIGNhY2hlIG9mIHRoZSB2YXJpb3VzIHJvdyBoZWlnaHRzIHRoYXQgYXJlIHByZXNlbnQgaW5zaWRlXG4gKiB0aGUgZGF0YSB0YWJsZS4gICBJdHMgYmFzZWQgb24gRmVud2ljayB0cmVlIGRhdGEgc3RydWN0dXJlIHRoYXQgaGVscHMgd2l0aFxuICogcXVlcnlpbmcgc3VtcyB0aGF0IGhhdmUgdGltZSBjb21wbGV4aXR5IG9mIGxvZyBuLlxuICpcbiAqIEZlbndpY2sgVHJlZSBDcmVkaXRzOiBodHRwOi8vcGV0ci1taXRyaWNoZXYuYmxvZ3Nwb3QuY29tLzIwMTMvMDUvZmVud2ljay10cmVlLXJhbmdlLXVwZGF0ZXMuaHRtbFxuICogaHR0cHM6Ly9naXRodWIuY29tL21pa29sYWx5c2Vua28vZmVud2ljay10cmVlXG4gKlxuICovXG5leHBvcnQgY2xhc3MgUm93SGVpZ2h0Q2FjaGUge1xuICAvKipcbiAgICogVHJlZSBBcnJheSBzdG9yZXMgdGhlIGN1bXVsYXRpdmUgaW5mb3JtYXRpb24gb2YgdGhlIHJvdyBoZWlnaHRzIHRvIHBlcmZvcm0gZWZmaWNpZW50XG4gICAqIHJhbmdlIHF1ZXJpZXMgYW5kIHVwZGF0ZXMuICBDdXJyZW50bHkgdGhlIHRyZWUgaXMgaW5pdGlhbGl6ZWQgdG8gdGhlIGJhc2Ugcm93XG4gICAqIGhlaWdodCBpbnN0ZWFkIG9mIHRoZSBkZXRhaWwgcm93IGhlaWdodC5cbiAgICovXG4gIHByaXZhdGUgdHJlZUFycmF5OiBudW1iZXJbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBDbGVhciB0aGUgVHJlZSBhcnJheS5cbiAgICovXG4gIGNsZWFyQ2FjaGUoKTogdm9pZCB7XG4gICAgdGhpcy50cmVlQXJyYXkgPSBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIHRoZSBGZW53aWNrIHRyZWUgd2l0aCByb3cgSGVpZ2h0cy5cbiAgICpcbiAgICogQHBhcmFtIHJvd3MgVGhlIGFycmF5IG9mIHJvd3Mgd2hpY2ggY29udGFpbiB0aGUgZXhwYW5kZWQgc3RhdHVzLlxuICAgKiBAcGFyYW0gcm93SGVpZ2h0IFRoZSByb3cgaGVpZ2h0LlxuICAgKiBAcGFyYW0gZGV0YWlsUm93SGVpZ2h0IFRoZSBkZXRhaWwgcm93IGhlaWdodC5cbiAgICovXG4gIGluaXRDYWNoZShkZXRhaWxzOiBhbnkpOiB2b2lkIHtcbiAgICBjb25zdCB7IHJvd3MsIHJvd0hlaWdodCwgZGV0YWlsUm93SGVpZ2h0LCBleHRlcm5hbFZpcnR1YWwsIHJvd0NvdW50LCByb3dJbmRleGVzLCByb3dFeHBhbnNpb25zIH0gPSBkZXRhaWxzO1xuICAgIGNvbnN0IGlzRm4gPSB0eXBlb2Ygcm93SGVpZ2h0ID09PSAnZnVuY3Rpb24nO1xuICAgIGNvbnN0IGlzRGV0YWlsRm4gPSB0eXBlb2YgZGV0YWlsUm93SGVpZ2h0ID09PSAnZnVuY3Rpb24nO1xuXG4gICAgaWYgKCFpc0ZuICYmIGlzTmFOKHJvd0hlaWdodCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUm93IEhlaWdodCBjYWNoZSBpbml0aWFsaXphdGlvbiBmYWlsZWQuIFBsZWFzZSBlbnN1cmUgdGhhdCAncm93SGVpZ2h0JyBpcyBhXG4gICAgICAgIHZhbGlkIG51bWJlciBvciBmdW5jdGlvbiB2YWx1ZTogKCR7cm93SGVpZ2h0fSkgd2hlbiAnc2Nyb2xsYmFyVicgaXMgZW5hYmxlZC5gKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgdGhpcyBhZGRpdGlvbmFsIGd1YXJkIGluIGNhc2UgZGV0YWlsUm93SGVpZ2h0IGlzIHNldCB0byAnYXV0bycgYXMgaXQgd29udCB3b3JrLlxuICAgIGlmICghaXNEZXRhaWxGbiAmJiBpc05hTihkZXRhaWxSb3dIZWlnaHQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFJvdyBIZWlnaHQgY2FjaGUgaW5pdGlhbGl6YXRpb24gZmFpbGVkLiBQbGVhc2UgZW5zdXJlIHRoYXQgJ2RldGFpbFJvd0hlaWdodCcgaXMgYVxuICAgICAgICB2YWxpZCBudW1iZXIgb3IgZnVuY3Rpb24gdmFsdWU6ICgke2RldGFpbFJvd0hlaWdodH0pIHdoZW4gJ3Njcm9sbGJhclYnIGlzIGVuYWJsZWQuYCk7XG4gICAgfVxuXG4gICAgY29uc3QgbiA9IGV4dGVybmFsVmlydHVhbCA/IHJvd0NvdW50IDogcm93cy5sZW5ndGg7XG4gICAgdGhpcy50cmVlQXJyYXkgPSBuZXcgQXJyYXkobik7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgdGhpcy50cmVlQXJyYXlbaV0gPSAwO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBjb25zdCByb3cgPSByb3dzW2ldO1xuICAgICAgbGV0IGN1cnJlbnRSb3dIZWlnaHQgPSByb3dIZWlnaHQ7XG4gICAgICBpZiAoaXNGbikge1xuICAgICAgICBjdXJyZW50Um93SGVpZ2h0ID0gcm93SGVpZ2h0KHJvdyk7XG4gICAgICB9XG5cbiAgICAgIC8vIEFkZCB0aGUgZGV0YWlsIHJvdyBoZWlnaHQgdG8gdGhlIGFscmVhZHkgZXhwYW5kZWQgcm93cy5cbiAgICAgIC8vIFRoaXMgaXMgdXNlZnVsIGZvciB0aGUgdGFibGUgdGhhdCBnb2VzIHRocm91Z2ggYSBmaWx0ZXIgb3Igc29ydC5cbiAgICAgIGNvbnN0IGV4cGFuZGVkID0gcm93RXhwYW5zaW9ucy5oYXMocm93KTtcbiAgICAgIGlmIChyb3cgJiYgZXhwYW5kZWQpIHtcbiAgICAgICAgaWYgKGlzRGV0YWlsRm4pIHtcbiAgICAgICAgICBjb25zdCBpbmRleCA9IHJvd0luZGV4ZXMuZ2V0KHJvdyk7XG4gICAgICAgICAgY3VycmVudFJvd0hlaWdodCArPSBkZXRhaWxSb3dIZWlnaHQocm93LCBpbmRleCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3VycmVudFJvd0hlaWdodCArPSBkZXRhaWxSb3dIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy51cGRhdGUoaSwgY3VycmVudFJvd0hlaWdodCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIHRoZSBTY3JvbGxZIHBvc2l0aW9uIGkuZS4gc3VtLCBwcm92aWRlIHRoZSByb3dJbmRleFxuICAgKiB0aGF0IGlzIHByZXNlbnQgaW4gdGhlIGN1cnJlbnQgdmlldyBwb3J0LiAgQmVsb3cgaGFuZGxlcyBlZGdlIGNhc2VzLlxuICAgKi9cbiAgZ2V0Um93SW5kZXgoc2Nyb2xsWTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoc2Nyb2xsWSA9PT0gMCkgcmV0dXJuIDA7XG4gICAgcmV0dXJuIHRoaXMuY2FsY1Jvd0luZGV4KHNjcm9sbFkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZW4gYSByb3cgaXMgZXhwYW5kZWQgb3Igcm93SGVpZ2h0IGlzIGNoYW5nZWQsIHVwZGF0ZSB0aGUgaGVpZ2h0LiAgVGhpcyBjYW5cbiAgICogYmUgdXRpbGl6ZWQgaW4gZnV0dXJlIHdoZW4gQW5ndWxhciBEYXRhIHRhYmxlIHN1cHBvcnRzIGR5bmFtaWMgcm93IGhlaWdodHMuXG4gICAqL1xuICB1cGRhdGUoYXRSb3dJbmRleDogbnVtYmVyLCBieVJvd0hlaWdodDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnRyZWVBcnJheS5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVXBkYXRlIGF0IGluZGV4ICR7YXRSb3dJbmRleH0gd2l0aCB2YWx1ZSAke2J5Um93SGVpZ2h0fSBmYWlsZWQ6XG4gICAgICAgIFJvdyBIZWlnaHQgY2FjaGUgbm90IGluaXRpYWxpemVkLmApO1xuICAgIH1cblxuICAgIGNvbnN0IG4gPSB0aGlzLnRyZWVBcnJheS5sZW5ndGg7XG4gICAgYXRSb3dJbmRleCB8PSAwO1xuXG4gICAgd2hpbGUgKGF0Um93SW5kZXggPCBuKSB7XG4gICAgICB0aGlzLnRyZWVBcnJheVthdFJvd0luZGV4XSArPSBieVJvd0hlaWdodDtcbiAgICAgIGF0Um93SW5kZXggfD0gYXRSb3dJbmRleCArIDE7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJhbmdlIFN1bSBxdWVyeSBmcm9tIDEgdG8gdGhlIHJvd0luZGV4XG4gICAqL1xuICBxdWVyeShhdEluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmICghdGhpcy50cmVlQXJyYXkubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHF1ZXJ5IGF0IGluZGV4ICR7YXRJbmRleH0gZmFpbGVkOiBGZW53aWNrIHRyZWUgYXJyYXkgbm90IGluaXRpYWxpemVkLmApO1xuICAgIH1cblxuICAgIGxldCBzdW0gPSAwO1xuICAgIGF0SW5kZXggfD0gMDtcblxuICAgIHdoaWxlIChhdEluZGV4ID49IDApIHtcbiAgICAgIHN1bSArPSB0aGlzLnRyZWVBcnJheVthdEluZGV4XTtcbiAgICAgIGF0SW5kZXggPSAoYXRJbmRleCAmIChhdEluZGV4ICsgMSkpIC0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3VtO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmQgdGhlIHRvdGFsIGhlaWdodCBiZXR3ZWVuIDIgcm93IGluZGV4ZXNcbiAgICovXG4gIHF1ZXJ5QmV0d2VlbihhdEluZGV4QTogbnVtYmVyLCBhdEluZGV4QjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeShhdEluZGV4QikgLSB0aGlzLnF1ZXJ5KGF0SW5kZXhBIC0gMSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gdGhlIFNjcm9sbFkgcG9zaXRpb24gaS5lLiBzdW0sIHByb3ZpZGUgdGhlIHJvd0luZGV4XG4gICAqIHRoYXQgaXMgcHJlc2VudCBpbiB0aGUgY3VycmVudCB2aWV3IHBvcnQuXG4gICAqL1xuICBwcml2YXRlIGNhbGNSb3dJbmRleChzdW06IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKCF0aGlzLnRyZWVBcnJheS5sZW5ndGgpIHJldHVybiAwO1xuXG4gICAgbGV0IHBvcyA9IC0xO1xuICAgIGNvbnN0IGRhdGFMZW5ndGggPSB0aGlzLnRyZWVBcnJheS5sZW5ndGg7XG5cbiAgICAvLyBHZXQgdGhlIGhpZ2hlc3QgYml0IGZvciB0aGUgYmxvY2sgc2l6ZS5cbiAgICBjb25zdCBoaWdoZXN0Qml0ID0gTWF0aC5wb3coMiwgZGF0YUxlbmd0aC50b1N0cmluZygyKS5sZW5ndGggLSAxKTtcblxuICAgIGZvciAobGV0IGJsb2NrU2l6ZSA9IGhpZ2hlc3RCaXQ7IGJsb2NrU2l6ZSAhPT0gMDsgYmxvY2tTaXplID4+PSAxKSB7XG4gICAgICBjb25zdCBuZXh0UG9zID0gcG9zICsgYmxvY2tTaXplO1xuICAgICAgaWYgKG5leHRQb3MgPCBkYXRhTGVuZ3RoICYmIHN1bSA+PSB0aGlzLnRyZWVBcnJheVtuZXh0UG9zXSkge1xuICAgICAgICBzdW0gLT0gdGhpcy50cmVlQXJyYXlbbmV4dFBvc107XG4gICAgICAgIHBvcyA9IG5leHRQb3M7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvcyArIDE7XG4gIH1cbn1cbiJdfQ==