diff options
author | Clement Ho <clemmakesapps@gmail.com> | 2018-06-01 16:41:50 +0000 |
---|---|---|
committer | Clement Ho <clemmakesapps@gmail.com> | 2018-06-01 16:41:50 +0000 |
commit | 30bc82f68b6de69a2e456286888824fa0221d4a7 (patch) | |
tree | 32597a02aa74ed80a3370c3f08dda12d152c5b68 | |
parent | abe98d44e8902a3f721c0f17cc20dc55bcb2d2f6 (diff) | |
download | gitlab-ce-30bc82f68b6de69a2e456286888824fa0221d4a7.tar.gz |
Revert "Merge branch '46833-sticky-polyfill' into 'master'"
This reverts merge request !19304
-rw-r--r-- | app/assets/javascripts/init_changes_dropdown.js | 6 | ||||
-rw-r--r-- | app/assets/javascripts/job.js | 7 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/sticky.js | 39 | ||||
-rw-r--r-- | spec/javascripts/lib/utils/sticky_spec.js | 79 |
4 files changed, 128 insertions, 3 deletions
diff --git a/app/assets/javascripts/init_changes_dropdown.js b/app/assets/javascripts/init_changes_dropdown.js index a9f4829f980..09cca1dc7d9 100644 --- a/app/assets/javascripts/init_changes_dropdown.js +++ b/app/assets/javascripts/init_changes_dropdown.js @@ -1,8 +1,8 @@ import $ from 'jquery'; -import StickyFill from 'stickyfilljs'; +import stickyMonitor from './lib/utils/sticky'; -export default () => { - StickyFill.add(document.querySelector('.js-diff-files-changed')); +export default (stickyTop) => { + stickyMonitor(document.querySelector('.js-diff-files-changed'), stickyTop); $('.js-diff-stats-dropdown').glDropdown({ filterable: true, diff --git a/app/assets/javascripts/job.js b/app/assets/javascripts/job.js index 8dfe8aae5b5..611e8200b4d 100644 --- a/app/assets/javascripts/job.js +++ b/app/assets/javascripts/job.js @@ -80,6 +80,13 @@ export default class Job { } initAffixTopArea() { + /** + If the browser does not support position sticky, it returns the position as static. + If the browser does support sticky, then we allow the browser to handle it, if not + then we use a polyfill + */ + if (this.$topBar.css('position') !== 'static') return; + StickyFill.add(this.$topBar); } diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js new file mode 100644 index 00000000000..098afcfa1b4 --- /dev/null +++ b/app/assets/javascripts/lib/utils/sticky.js @@ -0,0 +1,39 @@ +export const createPlaceholder = () => { + const placeholder = document.createElement('div'); + placeholder.classList.add('sticky-placeholder'); + + return placeholder; +}; + +export const isSticky = (el, scrollY, stickyTop, insertPlaceholder) => { + const top = Math.floor(el.offsetTop - scrollY); + + if (top <= stickyTop && !el.classList.contains('is-stuck')) { + const placeholder = insertPlaceholder ? createPlaceholder() : null; + const heightBefore = el.offsetHeight; + + el.classList.add('is-stuck'); + + if (insertPlaceholder) { + el.parentNode.insertBefore(placeholder, el.nextElementSibling); + + placeholder.style.height = `${heightBefore - el.offsetHeight}px`; + } + } else if (top > stickyTop && el.classList.contains('is-stuck')) { + el.classList.remove('is-stuck'); + + if (insertPlaceholder && el.nextElementSibling && el.nextElementSibling.classList.contains('sticky-placeholder')) { + el.nextElementSibling.remove(); + } + } +}; + +export default (el, stickyTop, insertPlaceholder = true) => { + if (!el) return; + + if (typeof CSS === 'undefined' || !(CSS.supports('(position: -webkit-sticky) or (position: sticky)'))) return; + + document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop, insertPlaceholder), { + passive: true, + }); +}; diff --git a/spec/javascripts/lib/utils/sticky_spec.js b/spec/javascripts/lib/utils/sticky_spec.js new file mode 100644 index 00000000000..b87c836654d --- /dev/null +++ b/spec/javascripts/lib/utils/sticky_spec.js @@ -0,0 +1,79 @@ +import { isSticky } from '~/lib/utils/sticky'; + +describe('sticky', () => { + let el; + + beforeEach(() => { + document.body.innerHTML += ` + <div class="parent"> + <div id="js-sticky"></div> + </div> + `; + + el = document.getElementById('js-sticky'); + }); + + afterEach(() => { + el.parentNode.remove(); + }); + + describe('when stuck', () => { + it('does not remove is-stuck class', () => { + isSticky(el, 0, el.offsetTop); + isSticky(el, 0, el.offsetTop); + + expect( + el.classList.contains('is-stuck'), + ).toBeTruthy(); + }); + + it('adds is-stuck class', () => { + isSticky(el, 0, el.offsetTop); + + expect( + el.classList.contains('is-stuck'), + ).toBeTruthy(); + }); + + it('inserts placeholder element', () => { + isSticky(el, 0, el.offsetTop, true); + + expect( + document.querySelector('.sticky-placeholder'), + ).not.toBeNull(); + }); + }); + + describe('when not stuck', () => { + it('removes is-stuck class', () => { + spyOn(el.classList, 'remove').and.callThrough(); + + isSticky(el, 0, el.offsetTop); + isSticky(el, 0, 0); + + expect( + el.classList.remove, + ).toHaveBeenCalledWith('is-stuck'); + expect( + el.classList.contains('is-stuck'), + ).toBeFalsy(); + }); + + it('does not add is-stuck class', () => { + isSticky(el, 0, 0); + + expect( + el.classList.contains('is-stuck'), + ).toBeFalsy(); + }); + + it('removes placeholder', () => { + isSticky(el, 0, el.offsetTop, true); + isSticky(el, 0, 0, true); + + expect( + document.querySelector('.sticky-placeholder'), + ).toBeNull(); + }); + }); +}); |