From bfc9f24251c7fbf620a728c8cbaaf741a5f16b6b Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 12 Jul 2017 23:07:36 +0300 Subject: [PATCH] Fix headerHeight logic, implement scrollToNode usable with virtual-scroll --- treegrid.js | 65 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/treegrid.js b/treegrid.js index 79e0083..87e611d 100644 --- a/treegrid.js +++ b/treegrid.js @@ -284,13 +284,40 @@ function findSubNodes(node, start, count, result) return [ skipped, added ]; } -TreeGrid.prototype._findNodes = function(node, start, count) +TreeGrid.prototype._findNodes = function(start, count) { var result = []; - findSubNodes(node, start, count, result); + findSubNodes(this.root, start, count, result); return result; } +function findNodeIndex(node, target) +{ + var index = 0, result; + for (var i = 0; i < node.children.length; i++) + { + if (node.children[i] == target) + return [ index, true ]; + index++; + if (!node.children[i].collapsed) + { + result = findNodeIndex(node.children[i], target); + index += result[0]; + if (result[1]) + return [ index, true ]; + } + } + return [ index, false ]; +} + +TreeGrid.prototype._findNodeIndex = function(node) +{ + var result = findNodeIndex(this.root, node); + if (!result[1]) + return -1; + return result[0]; +} + TreeGrid.prototype._renderNodes = function(nodes) { for (var i = 0; i < nodes.length; i++) @@ -512,7 +539,7 @@ TreeGrid.prototype.syncView = function() if (!this.table.offsetParent) return; var headerHeight = (this.stickyRow ? this.thead.getBoundingClientRect().height : 0); - var offsetHeight = this.tableWrapper.clientHeight - headerHeight; + var offsetHeight = this.tableWrapper.clientHeight; var scrollTop = this.tableWrapper.scrollTop; var visibleItems = Math.ceil(offsetHeight/this.minItemHeight); var endStart = this.nodeCount - visibleItems; @@ -520,25 +547,26 @@ TreeGrid.prototype.syncView = function() if (endStart < 0) endStart = 0; // Always render last items - var lastNodes = this._findNodes(this.root, endStart, this.nodeCount-endStart); + var lastNodes = this._findNodes(endStart, this.nodeCount-endStart); this._setPlaceholder('top', 0); this._beginSync(); this._renderNodes(lastNodes); this._syncEnd(lastNodes); + this.lastFirstNodeIndex = 0; if (endStart > 0) { // Calculate virtual scroll - var lastFirst = endStart+this._findVisibleNodeOffset(lastNodes, offsetHeight); + this.lastFirstNodeIndex = endStart+this._findVisibleNodeOffset(lastNodes, offsetHeight-headerHeight); var avgItemHeight = this.endItemHeight / lastNodes.length; avgItemHeight = (avgItemHeight < this.minItemHeight ? this.minItemHeight : avgItemHeight); - targetHeight = headerHeight + this.nodeCount*avgItemHeight; + targetHeight = this.nodeCount*avgItemHeight + headerHeight; if (this.stickyColumn) this.fixedColSizer.style.height = targetHeight+'px'; this.tableSizer.style.height = targetHeight+'px'; var scrollPos = targetHeight > offsetHeight ? scrollTop / (targetHeight - offsetHeight) : 0; if (scrollPos > 1) scrollPos = 1; - var firstVisible = scrollPos*lastFirst; + var firstVisible = scrollPos*this.lastFirstNodeIndex; var rangeStart = Math.floor(firstVisible); var rangeCount = visibleItems; this._addPlaceholder('top', 0); @@ -560,13 +588,13 @@ TreeGrid.prototype.syncView = function() { rangeCount = endStart-rangeStart; } - var visibleNodes = this._findNodes(this.root, rangeStart, rangeCount); + var visibleNodes = this._findNodes(rangeStart, rangeCount); this._renderNodes(visibleNodes); this._syncStart(visibleNodes); this._addPlaceholder('mid', 0); firstItemHeight = getNodeHeight(visibleNodes[0])*(firstVisible-rangeStart); } - this._setPlaceholder('top', scrollTop-firstItemHeight-headerHeight); + this._setPlaceholder('top', scrollTop - firstItemHeight); } else if (this.stickyColumn) { @@ -585,14 +613,29 @@ TreeGrid.prototype.syncView = function() this.syncStickyRow(); if (endStart > 0 && endStart > rangeStart+rangeCount) for (var i = 0; i < this.tbody.rows.length; i++) - total += (this.tbody.rows[i].getBoundingClientRect().height||0); + if (!this.tbody.rows[i].is_placeholder) + total += (this.tbody.rows[i].getBoundingClientRect().height||0); } if (endStart > 0 && endStart > rangeStart+rangeCount) { - this._setPlaceholder('mid', targetHeight - total - (scrollTop-firstItemHeight)); + this._setPlaceholder('mid', targetHeight - headerHeight - total - (scrollTop-firstItemHeight)); } } +TreeGrid.prototype.scrollToNode = function(node) +{ + // With virtual scrolling, we must reverse-engineer positioning to find the node + var nodeIndex = this._findNodeIndex(node); + if (nodeIndex < 0) + return false; + if (this.lastFirstNodeIndex > 0) + { + var offsetHeight = this.tableWrapper.clientHeight; + this.tableWrapper.scrollTop = nodeIndex/this.lastFirstNodeIndex * (this.tableWrapper.scrollHeight - offsetHeight); + } + return true; +} + TreeGrid.prototype.nodeOnHover = function(hover, ev) { ev = ev||window.event;