From 34b4a2c4e5905a2184b2906081353050ab231fb2 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sat, 13 Aug 2016 23:22:13 +0300 Subject: [PATCH] Fix 1-pixel offset rounding problems --- stickyheaders.js | 59 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/stickyheaders.js b/stickyheaders.js index 72f8064..3ed9adc 100644 --- a/stickyheaders.js +++ b/stickyheaders.js @@ -1,7 +1,7 @@ // Simple Sticky Header and Column implementation for HTML tables // (c) Vitaliy Filippov 2016 // License: MPL 2.0+ -// Version: 2016-08-12 +// Version: 2016-08-13 // USAGE: // makeStickyHeaders(table): add sticky header and footer to table @@ -27,9 +27,23 @@ // WARNING 5: make sure you have no CSS rules that will differ on the original header row/column and cloned one, // and that min/max width/height rules apply to the second row/column, not the first header one. +(function() { + var _scri = 0; -function makeStickyHeaders(table) +function getOffsetRect(e) +{ + var b = e.getBoundingClientRect(); + var r = { + left: Math.round(b.left), + top: Math.round(b.top), + }; + r.width = Math.round(b.right)-r.left; + r.height = Math.round(b.bottom)-r.top; + return r; +} + +window.makeStickyHeaders = function(table) { if (!table._scrstyle) { @@ -48,11 +62,13 @@ function makeStickyHeaders(table) sr.children[0].style.display = 'block'; sr.children[0].style.position = 'absolute'; sr.children[0].style.padding = '0'; + var pb = getOffsetRect(rs[0]); for (var i = 0; i < rs[0].children.length; i++) { var e = rs[0].children[i]; - w[i] = e.offsetWidth; - l[i] = e.offsetLeft; + var b = getOffsetRect(e); + w[i] = b.width; + l[i] = b.left-pb.left; } table._widths = w; table._sizerow = sr; @@ -99,7 +115,7 @@ function makeStickyHeaders(table) // 3) remember all heights var hs = []; for (var i = rs.length-1; i >= 1; i--) - hs[i] = rs[i].offsetHeight; + hs[i] = getOffsetRect(rs[i]).height; // 4) make other changes for (var i = rs.length-1; i >= 1; i--) { @@ -111,7 +127,7 @@ function makeStickyHeaders(table) e.style.height = hs[i]+'px'; e.style.width = w[0]+'px'; } - var row0top = rs[0].offsetTop; + var row0top = getOffsetRect(rs[0]).top; addListener(table.parentNode, 'scroll', function(e) { var l = this.scrollLeft, t = this.scrollTop; @@ -121,7 +137,7 @@ function makeStickyHeaders(table) } // check if row(s) are not yet initialised and fix them -function initStickyRows(table, trs, nocols) +window.initStickyRows = function(table, trs, nocols) { var ntrs = []; for (var i = 0; i < trs.length; i++) @@ -132,7 +148,7 @@ function initStickyRows(table, trs, nocols) } // handle non-header row(s) change with O(1) reflow count -function fixStickyRows(table, trs, nocols) +window.fixStickyRows = function(table, trs, nocols) { // (1) make some changes var e, d; @@ -167,12 +183,13 @@ function fixStickyRows(table, trs, nocols) } // (2) caused by offsetWidth/offsetHeight // (3) remember sizes - var w = [], h = []; + var w = [], h = [], b; for (var i = 0; i < trs.length; i++) { e = trs[i].children[1]; - w[i] = e.offsetWidth; - h[i] = e.offsetHeight; + b = getOffsetRect(e); + w[i] = b.width; + h[i] = b.height; } // (4) apply sizes for (var i = 0; i < trs.length; i++) @@ -185,14 +202,14 @@ function fixStickyRows(table, trs, nocols) fixStickyColumnSizes(table); } -function fixStickyColumnSizes(table, force) +window.fixStickyColumnSizes = function(table, force) { // check&fix column sizes var changed = false, resizeFixed = false; for (var i = 1; i < table._sizerow.children.length; i++) { var ne = table._sizerow.children[i]; - var nw = ne.offsetWidth; + var nw = getOffsetRect(ne).width; var cw = table._widths[i-1]; if (nw != cw || force) { @@ -205,13 +222,13 @@ function fixStickyColumnSizes(table, force) if (changed) { // reposition fixed header - var w = [], h = [], l = [], b; + var w = [], h = [], l = [], b, pb = getOffsetRect(table._sizerow); for (var i = 0; i < table._sizerow.children.length; i++) { - b = table._sizerow.children[i]; - w[i] = b.offsetWidth; - h[i] = b.offsetHeight; - l[i] = b.offsetLeft; + b = getOffsetRect(table._sizerow.children[i]); + w[i] = b.width; + h[i] = b.height; + l[i] = b.left-pb.left; } b = table.rows[0].children[0]; b.style.width = w[1]+'px'; @@ -228,7 +245,7 @@ function fixStickyColumnSizes(table, force) // resize fixed column var h = []; for (var i = 0; i < table.rows.length; i++) - h[i] = table.rows[i].children[1].offsetHeight; + h[i] = getOffsetRect(table.rows[i].children[1]).height; for (var i = 0; i < table.rows.length; i++) { if (i != 1) @@ -242,7 +259,7 @@ function fixStickyColumnSizes(table, force) } // handle header row change -function fixStickyHeader(table, nocols) +window.fixStickyHeader = function(table, nocols) { var tr = table.rows[0]; var sr = table._sizerow; @@ -293,3 +310,5 @@ function fixStickyHeader(table, nocols) if (!nocols) fixStickyColumnSizes(table); } + +})();