diff --git a/js/jquery.stickytableheaders.js b/js/jquery.stickytableheaders.js index 3cffd91..7475db3 100644 --- a/js/jquery.stickytableheaders.js +++ b/js/jquery.stickytableheaders.js @@ -8,7 +8,11 @@ id = 0, defaults = { fixedOffset: 0, - leftOffset: 0, + leftOffset: 0, + setStylesOnce: true, + cacheHeights: true, + flushHeightAfter: 0, + flushHeightEvery: 5000, scrollableArea: window }; @@ -18,9 +22,12 @@ var base = this; // Access to jQuery and DOM versions of element - base.$el = $(el); - base.el = el; - base.id = id++; + base.$el = $(el); + base.$els = []; + base.el = el; + base.id = id++; + + base.heights = []; base.$window = $(window); base.$document = $(document); @@ -38,9 +45,18 @@ base.leftOffset = null; base.topOffset = null; + base.resetHeights = function() { + base.$el.each(function (idx, elem) { + base.heights[idx] = {table : null, cHeader : null}; + }); + } + + base.delayedReset = $.noop; + base.init = function () { - base.$el.each(function () { + base.$el.each(function (idx, elem) { var $this = $(this); + base.$els[idx] = $this; // remove padding on to fix issue #7 $this.css('padding', 0); @@ -65,8 +81,24 @@ base.setOptions(options); base.updateWidth(); - base.toggleHeaders(); + base.toggleHeaders({type:'init'}); base.bind(); + + if (base.options.cacheHeights && base.options.flushHeightAfter) + setTimeout(base.resetHeights, base.options.flushHeightAfter); + if (base.options.cacheHeights && base.options.flushHeightEvery) + base.delayedReset = (function(func, every) { + var timeout = 0; + return function() { + if (timeout) + return false; + + var res = func(); + timeout = setTimeout(function(){ timeout = 0; }, every); + return res; + } + })(base.resetHeights, base.options.flushHeightEvery); + }; base.destroy = function (){ @@ -110,10 +142,23 @@ base.$scrollableArea.off('.' + name, base.updateWidth); }; - base.toggleHeaders = function () { + base.getCached = function($elem, what, idx, key) + { + if (base[what + 's'][idx][key]) + return base[what + 's'][idx][key]; + else + return base[what + 's'][idx][key] = $elem[what](); + } + + base.toggleHeaders = function (ev) { + if ('scroll' == ev.type) + base.delayedReset(); + else + base.resetHeights(); + if (base.$el) { - base.$el.each(function () { - var $this = $(this), + base.$el.each(function (idx, elem) { + var $this = base.$els[idx], newLeft, newTopOffset = base.isWindowScrolling ? ( isNaN(base.options.fixedOffset) ? @@ -130,25 +175,44 @@ scrollTop > offset.top : newTopOffset > offset.top, notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) < - (offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset)); - + ( + offset.top + + ( + base.options.cacheHeights && ev /* Filling cache only when scrolling */ ? + + base.getCached($this, 'height', idx, 'table') : + $this.height() + ) - + ( + base.options.cacheHeights && ev ? + base.getCached(base.$clonedHeader, 'height', idx, 'cHeader') : + base.$clonedHeader.height() + ) - + (base.isWindowScrolling ? 0 : newTopOffset) + ); if (scrolledPastTop && notScrolledPastBottom) { newLeft = offset.left - scrollLeft + base.options.leftOffset; - base.$originalHeader.css({ - 'position': 'fixed', - 'margin-top': 0, - 'left': newLeft, - 'z-index': 3 // #18: opacity bug - }); - base.leftOffset = newLeft; - base.topOffset = newTopOffset; - base.$clonedHeader.css('display', ''); + var doSet = !base.options.setStylesOnce || !base.isSticky || newLeft != base.leftOffset; + if (doSet) { + + base.$originalHeader.css({ + 'position': 'fixed', + 'margin-top': 0, + 'left': newLeft, + 'z-index': 3 // #18: opacity bug + }); + base.leftOffset = newLeft; + base.topOffset = newTopOffset; + base.$clonedHeader.css('display', ''); + } if (!base.isSticky) { base.isSticky = true; // make sure the width is correct: the user might have resized the browser while in static mode base.updateWidth(); } - base.setPositionValues(); + if (doSet) { + base.setPositionValues(); + } } else if (base.isSticky) { base.$originalHeader.css('position', 'static'); base.$clonedHeader.css('display', 'none'); @@ -253,7 +317,7 @@ base.unbind(); base.bind(); base.updateWidth(); - base.toggleHeaders(); + base.toggleHeaders({type:'update'}); }; // Run initializer