From 05c455250c63a7954311306d54419a90187a91bc Mon Sep 17 00:00:00 2001 From: Tom Byers Date: Wed, 23 Jan 2019 11:31:56 +0000 Subject: [PATCH] Fix calculation of in-page position When the screen resizes, the dimensions of our elements may change so we run `setElementDimensions` again to update our store of those values. This caused a bug with the stored position of stuck elements. When stuck, elements are 'fixed' so their position is relative to the window position. We need the value stored to be from the position in the document flow, not the 'fixed' value. This change means, when an element is stuck, we check its shim for the position instead. The shim occupies the space the element would do in the page so it makes sense to use it for this. --- .../stick-to-window-when-scrolling.js | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/stick-to-window-when-scrolling.js b/app/assets/javascripts/stick-to-window-when-scrolling.js index 16b1f5995..63914fce0 100644 --- a/app/assets/javascripts/stick-to-window-when-scrolling.js +++ b/app/assets/javascripts/stick-to-window-when-scrolling.js @@ -51,6 +51,18 @@ this._stopped = false; this._hasLoaded = false; this._canBeStuck = true; + this.verticalMargins = { + 'top': parseInt(this.$fixedEl.css('margin-top'), 10), + 'bottom': parseInt(this.$fixedEl.css('margin-bottom'), 10), + }; + }; + StickyElement.prototype._getShimCSS = function () { + return { + 'width': this.horizontalSpace + 'px', + 'height': this.height + 'px', + 'margin-top': this.verticalMargins.top + 'px', + 'margin-bottom': this.verticalMargins.bottom + 'px' + }; }; StickyElement.prototype.stickyClass = function () { return (this._sticky._initialPositionsSet) ? this._fixedClass : this._initialFixedClass; @@ -80,7 +92,8 @@ // When a sticky element is moved into the 'stuck' state, a shim is inserted into the // page to preserve the space the element occupies in the flow. StickyElement.prototype.addShim = function (position) { - this._$shim = $('
 
'); + this._$shim = $('
 
'); + this._$shim.css(this._getShimCSS()); this.$fixedEl[position](this._$shim); }; StickyElement.prototype.removeShim = function () { @@ -92,10 +105,7 @@ // Changes to the dimensions of a sticky element with a shim need to be passed on to the shim StickyElement.prototype.updateShim = function () { if (this._$shim) { - this._$shim.css({ - 'height': this.inPageVerticalSpace, - 'width': this.horizontalSpace - }); + this._$shim.css(this._getShimCSS()); } }; StickyElement.prototype.stop = function () { @@ -380,9 +390,13 @@ var $el = el.$fixedEl; var $img = $el.find('img'); var onload = function () { - el.inPageVerticalSpace = $el.outerHeight(true); el.height = $el.outerHeight(); - el.inPageEdgePosition = self.getInPageEdgePosition(el); + // if element has a shim, the shim's offset represents the element's in-page position + if (el._$shim) { + el.inPageEdgePosition = self.getInPageEdgePosition(el._$shim); + } else { + el.inPageEdgePosition = self.getInPageEdgePosition($el); + } callback(); }; @@ -557,8 +571,8 @@ return footer.offset().top - this.STOP_PADDING; }; // position of the bottom edge when in the page flow - stickAtTop.getInPageEdgePosition = function (el) { - return el.$fixedEl.offset().top; + stickAtTop.getInPageEdgePosition = function ($el) { + return $el.offset().top; }; stickAtTop.getScrolledFrom = function (el) { if (_mode === 'dialog') { @@ -638,8 +652,8 @@ return (header.offset().top + header.outerHeight()) + this.STOP_PADDING; }; // position of the bottom edge when in the page flow - stickAtBottom.getInPageEdgePosition = function (el) { - return el.$fixedEl.offset().top + el.height; + stickAtBottom.getInPageEdgePosition = function ($el) { + return $el.offset().top + $el.outerHeight(); }; stickAtBottom.getScrolledFrom = function (el) { if (_mode === 'dialog') {