From 70488eeb8eed4df24bf733763beea84256cf3853 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 5 Jul 2017 18:20:27 +0300 Subject: [PATCH] fix underscroll & overscroll, but scroll is still jumping --- treegrid.js | 102 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 33 deletions(-) diff --git a/treegrid.js b/treegrid.js index 0967f0c..f080e87 100644 --- a/treegrid.js +++ b/treegrid.js @@ -176,6 +176,7 @@ function TreeGrid(options) addListener(this.wrapper||this.table, 'mouseout', function(ev) { self.nodeOnHover(false, ev); }); this.setHeader(options.header); this.nodeCount = 0; + this.placeholders = {}; new TreeGridNode({ children: options.items }, this, null, 0); } @@ -369,23 +370,32 @@ TreeGrid.prototype._syncStart = function(nodes) } } -TreeGrid.prototype._addPlaceholder = function(elems) +TreeGrid.prototype._setPlaceholder = function(name, height) { - if (elems <= 0) - return; - var height = elems*this.minItemHeight; - var tr = document.createElement('tr'), col_tr; - tr.is_placeholder = true; - tr.appendChild(document.createElement('td')); - tr.style.height = height+'px'; + this.placeholders[name][0].style.height = height+'px'; + this.placeholders[name][0].style.display = height > 0 ? '' : 'none'; if (this.fixedColBody) { - col_tr = document.createElement('tr'); - col_tr.is_placeholder = true; - col_tr.appendChild(document.createElement('td')); - col_tr.style.height = height+'px'; + this.placeholders[name][1].style.height = height+'px'; + this.placeholders[name][1].style.display = height > 0 ? '' : 'none'; } - this._syncStartNode(tr, col_tr); +} + +TreeGrid.prototype._addPlaceholder = function(name, height) +{ + if (!this.placeholders[name]) + { + this.placeholders[name] = []; + for (var i = 0; i < (this.fixedColBody ? 2 : 1); i++) + { + this.placeholders[name][i] = document.createElement('tr'); + this.placeholders[name][i].is_placeholder = true; + this.placeholders[name][i].appendChild(document.createElement('td')); + } + } + if (height !== undefined) + this._setPlaceholder(name, height); + this._syncStartNode(this.placeholders[name][0], this.placeholders[name][1]); } TreeGrid.prototype._finishSync = function() @@ -423,36 +433,45 @@ TreeGrid.prototype._finishSync = function() TreeGrid.prototype._findVisibleNodeOffset = function(nodes, offsetHeight) { - var h = 0, nh = 0, h1, h2; + var h = 0, nh, h1, h2, r = 0, notfound = true; for (var i = nodes.length-1; i >= 0; i--) { - nh = 0; - if (this.fixedColBody) - { - for (var j = 0; j < nodes[i].tr.length; j++) - { - h1 = nodes[i].tr[j].offsetHeight||0; - h2 = nodes[i].col_tr[j].offsetHeight||0; - nh += h1 < h2 ? h2 : h1; - } - } - else - for (var j = 0; j < nodes[i].tr.length; j++) - nh += nodes[i].tr[j].offsetHeight||0; + nh = getNodeHeight(nodes[i]); h += nh; - if (h >= offsetHeight) + if (notfound && h >= offsetHeight) { - return i + (h-offsetHeight)/nh; + notfound = false; + r = i + (h-offsetHeight)/nh; } } - return 0; + this.endItemHeight = h; + return r; +} + +function getNodeHeight(node) +{ + var nh = 0; + if (node.col_tr) + { + for (var j = 0; j < node.tr.length; j++) + { + h1 = node.tr[j].offsetHeight||0; + h2 = node.col_tr[j].offsetHeight||0; + nh += h1 < h2 ? h2 : h1; + } + } + else + for (var j = 0; j < node.tr.length; j++) + nh += node.tr[j].offsetHeight||0; + return nh; } TreeGrid.prototype.syncView = function() { if (!this.table.offsetParent) return; - var scrollPos = this.tableWrapper.scrollTop / (this.tableWrapper.scrollHeight - this.tableWrapper.offsetHeight + 1); + var scrollPos = this.tableWrapper.scrollHeight > this.tableWrapper.offsetHeight ? + this.tableWrapper.scrollTop / (this.tableWrapper.scrollHeight - this.tableWrapper.offsetHeight) : 0; var offsetHeight = this.wrapper.offsetHeight - this.thead.offsetHeight; var visibleItems = Math.ceil(offsetHeight/this.minItemHeight); var endStart = this.nodeCount - visibleItems; @@ -470,10 +489,17 @@ TreeGrid.prototype.syncView = function() var firstVisible = scrollPos*lastFirst; var rangeStart = Math.floor(firstVisible); var rangeCount = visibleItems; - this._addPlaceholder(rangeStart); + this._addPlaceholder('top'); + var firstItemHeight; if (rangeStart >= endStart) { // Nothing more to render + firstItemHeight = 0; + for (var i = rangeStart-1; i >= endStart; i--) + { + firstItemHeight += getNodeHeight(lastNodes[i-endStart]); + } + firstItemHeight += getNodeHeight(lastNodes[rangeStart-endStart])*(firstVisible-rangeStart); } else { @@ -486,12 +512,15 @@ TreeGrid.prototype.syncView = function() this._syncStart(visibleNodes); if (endStart > rangeStart+rangeCount) { - this._addPlaceholder(endStart-rangeStart-rangeCount); + this._addPlaceholder('mid', 0); } + firstItemHeight = getNodeHeight(visibleNodes[0])*(firstVisible-rangeStart); } + this._setPlaceholder('top', this.tableWrapper.scrollTop-firstItemHeight); } this._finishSync(); // Then sync row sizes for fixed column to work properly + var total = 0; if (this.stickyHeaders) { if (this.fixedCol.offsetWidth) @@ -508,12 +537,19 @@ TreeGrid.prototype.syncView = function() { if (h[i] && !this.tbody.rows[i].is_placeholder) { + total += h[i]; this.tbody.rows[i].style.height = h[i]+'px'; this.fixedColBody.rows[i].style.height = h[i]+'px'; } } this.syncStickyRow(); } + if (endStart > 0) + { + var avgItemHeight = this.endItemHeight / lastNodes.length; + avgItemHeight = (avgItemHeight < this.minItemHeight ? this.minItemHeight : avgItemHeight); + this._setPlaceholder('mid', this.nodeCount*avgItemHeight - total - (this.tableWrapper.scrollTop-firstItemHeight)); + } } TreeGrid.prototype.nodeOnHover = function(hover, ev)