From d08bd53b182c9f52c959a4968a8d04ebaf50eec3 Mon Sep 17 00:00:00 2001 From: Gemma Leigh Date: Tue, 20 Sep 2016 17:27:07 +0100 Subject: [PATCH 1/3] Add three new functions to pass data to tests Add three new functions and update the stick at top when scrolling js to use these new functions, so they can be mocked in tests. --- .../govuk/stick-at-top-when-scrolling.js | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/javascripts/govuk/stick-at-top-when-scrolling.js b/javascripts/govuk/stick-at-top-when-scrolling.js index 2537a3ab..6852e705 100644 --- a/javascripts/govuk/stick-at-top-when-scrolling.js +++ b/javascripts/govuk/stick-at-top-when-scrolling.js @@ -9,6 +9,20 @@ _hasScrolled: false, _scrollTimeout: false, + getWindowDimensions: function() { + return { + height: $(global).height(), + width: $(global).width() + }; + }, + getWindowPositions: function() { + return { + scrollTop: $(global).scrollTop() + }; + }, + getElementOffset: function($el) { + return $el.offset() + }, init: function(){ var $els = $('.js-stick-at-top-when-scrolling'); @@ -43,14 +57,17 @@ if(sticky._hasScrolled === true){ sticky._hasScrolled = false; - var windowVerticalPosition = $(global).scrollTop(); + var windowVerticalPosition = sticky.getWindowPositions().scrollTop; + + var windowDimensions = sticky.getWindowDimensions(); + sticky.$els.each(function(i, el){ var $el = $(el), scrolledFrom = $el.data('scrolled-from'); if (scrolledFrom && windowVerticalPosition < scrolledFrom){ sticky.release($el); - } else if($(global).width() > 768 && windowVerticalPosition >= $el.offset().top) { + } else if(windowDimensions.width > 768 && windowVerticalPosition >= sticky.getElementOffset($el).top) { sticky.stick($el); } }); @@ -58,7 +75,7 @@ }, stick: function($el){ if (!$el.hasClass('content-fixed')) { - $el.data('scrolled-from', $el.offset().top); + $el.data('scrolled-from', sticky.getElementOffset($el).top); var height = Math.max($el.height(), 1); $el.before('
 
'); $el.css('width', $el.width() + "px").addClass('content-fixed'); From 04812cad9da710ffb9e85b09270700b16791fb0a Mon Sep 17 00:00:00 2001 From: Gemma Leigh Date: Tue, 20 Sep 2016 17:27:42 +0100 Subject: [PATCH 2/3] Ensure a sticky element is unstuck for smaller screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a checkResize function to check when the screen is resized and “unstick” a sticky element if the window width is smaller than “desktop” - less than or equal to 768px. --- .../govuk/stick-at-top-when-scrolling.js | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/javascripts/govuk/stick-at-top-when-scrolling.js b/javascripts/govuk/stick-at-top-when-scrolling.js index 6852e705..4ab565d4 100644 --- a/javascripts/govuk/stick-at-top-when-scrolling.js +++ b/javascripts/govuk/stick-at-top-when-scrolling.js @@ -8,6 +8,8 @@ var sticky = { _hasScrolled: false, _scrollTimeout: false, + _hasResized: false, + _resizeTimeout: false, getWindowDimensions: function() { return { @@ -33,7 +35,11 @@ $(global).scroll(sticky.onScroll); sticky._scrollTimeout = global.setInterval(sticky.checkScroll, 50); } - $(global).resize(sticky.onResize); + + if(sticky._resizeTimeout === false) { + $(global).resize(sticky.onResize); + sticky._resizeTimeout = global.setInterval(sticky.checkResize, 50); + } } if(GOVUK.stopScrollingAtFooter){ $els.each(function(i,el){ @@ -53,6 +59,9 @@ onScroll: function(){ sticky._hasScrolled = true; }, + onResize: function(){ + sticky._hasResized = true; + }, checkScroll: function(){ if(sticky._hasScrolled === true){ sticky._hasScrolled = false; @@ -73,6 +82,21 @@ }); } }, + checkResize: function() { + if(sticky._hasResized === true){ + sticky._hasResized = false; + + var windowDimensions = sticky.getWindowDimensions(); + + sticky.$els.each(function(i, el){ + var $el = $(el); + + if(windowDimensions.width <= 768) { + sticky.release($el); + } + }); + } + }, stick: function($el){ if (!$el.hasClass('content-fixed')) { $el.data('scrolled-from', sticky.getElementOffset($el).top); From 76c62bbb8eed6e5572fd05165e56d965ebe55cf0 Mon Sep 17 00:00:00 2001 From: Gemma Leigh Date: Tue, 20 Sep 2016 17:30:52 +0100 Subject: [PATCH 3/3] Update tests Re-order tests - when sticking and unsticking. Add mocks to test that sticking and unsticking works for smaller and larger screens, test that all three conditions in the checkScroll function stick/unstick. --- spec/unit/stick-at-top-when-scrolling.spec.js | 112 +++++++++++++++--- 1 file changed, 97 insertions(+), 15 deletions(-) diff --git a/spec/unit/stick-at-top-when-scrolling.spec.js b/spec/unit/stick-at-top-when-scrolling.spec.js index b89aeef2..fab0b591 100644 --- a/spec/unit/stick-at-top-when-scrolling.spec.js +++ b/spec/unit/stick-at-top-when-scrolling.spec.js @@ -13,27 +13,109 @@ describe("stick-at-top-when-scrolling", function(){ $stickyWrapper.remove(); }); - it('should add fixed class on stick', function(){ - expect(!$stickyElement.hasClass('content-fixed')).toBe(true); - GOVUK.stickAtTopWhenScrolling.stick($stickyElement); - expect($stickyElement.hasClass('content-fixed')).toBe(true); + describe('when stick is called', function(){ + + it('should add fixed class on stick', function(){ + expect(!$stickyElement.hasClass('content-fixed')).toBe(true); + GOVUK.stickAtTopWhenScrolling.stick($stickyElement); + expect($stickyElement.hasClass('content-fixed')).toBe(true); + }); + + it('should insert shim when sticking the element', function(){ + expect($('.shim').length).toBe(0); + GOVUK.stickAtTopWhenScrolling.stick($stickyElement); + expect($('.shim').length).toBe(1); + }); + + it('should insert shim with minimum height', function(){ + GOVUK.stickAtTopWhenScrolling.stick($stickyElement); + expect($('.shim').height()).toBe(1); + }); + }); - it('should remove fixed class on release', function(){ - $stickyElement.addClass('content-fixed'); - GOVUK.stickAtTopWhenScrolling.release($stickyElement); - expect(!$stickyElement.hasClass('content-fixed')).toBe(true); + describe('when release is called', function(){ + + it('should remove fixed class', function(){ + $stickyElement.addClass('content-fixed'); + GOVUK.stickAtTopWhenScrolling.release($stickyElement); + expect($stickyElement.hasClass('content-fixed')).toBe(false); + }); + + it('should remove the shim', function(){ + $stickyElement = $('
'); + GOVUK.stickAtTopWhenScrolling.release($stickyElement); + expect($('.shim').length).toBe(0); + }); + }); - it('should insert shim when sticking content', function(){ - expect($('.shim').length).toBe(0); - GOVUK.stickAtTopWhenScrolling.stick($stickyElement); - expect($('.shim').length).toBe(1); + describe('for larger screens (>768px)', function(){ + + beforeEach(function() { + GOVUK.stickAtTopWhenScrolling.getWindowPositions = function(){ + return { + scrollTop: 300 + }; + }; + GOVUK.stickAtTopWhenScrolling.getElementOffset = function(){ + return { + top: 300 + }; + }; + GOVUK.stickAtTopWhenScrolling.getWindowDimensions = function(){ + return { + height: 768, + width: 769 + }; + }; + GOVUK.stickAtTopWhenScrolling.$els = $stickyElement; + GOVUK.stickAtTopWhenScrolling._hasScrolled = true; + GOVUK.stickAtTopWhenScrolling.checkScroll(); + }); + + it('should stick, if the scroll position is past the element position', function(){ + expect($stickyElement.hasClass('content-fixed')).toBe(true); + }); + + it('should unstick, if the scroll position is less than the point at which scrolling started', function(){ + GOVUK.stickAtTopWhenScrolling.getWindowPositions = function() { + return { + scrollTop: 0 + }; + }; + GOVUK.stickAtTopWhenScrolling.$els = $stickyElement; + GOVUK.stickAtTopWhenScrolling._hasScrolled = true; + GOVUK.stickAtTopWhenScrolling.checkScroll(); + expect($stickyElement.hasClass('content-fixed')).toBe(false); + }); + }); - it('should insert shim with minimum height', function(){ - GOVUK.stickAtTopWhenScrolling.stick($stickyElement); - expect($('.shim').height()).toBe(1); + describe('for smaller screens (<=768px)', function(){ + + beforeEach(function() { + GOVUK.stickAtTopWhenScrolling.getWindowDimensions = function() { + return { + height: 768, + width: 767 + }; + }; + GOVUK.stickAtTopWhenScrolling.getElementOffset = function() { + return { + top: 300 + }; + }; + GOVUK.stickAtTopWhenScrolling.$els = $stickyElement; + GOVUK.stickAtTopWhenScrolling._hasScrolled = true; + GOVUK.stickAtTopWhenScrolling.checkScroll(); + }); + + it('should unstick the element', function(){ + expect($stickyElement.hasClass('content-fixed')).toBe(false); + }); + }); + });