UNPKG

@randstad-design/orbit-multitheme

Version:

multitheme Front-end code based on Randstad Human Forward components

175 lines (148 loc) 4.97 kB
import ElementHelpers from '../helpers/element-helpers'; import scrollToElement from '../helpers/scrollToElement'; /** * scroll.js * scroll script that adds a gradient and handles anchors */ /** * Declare constants */ const attributeBase = 'data-rs-scroll'; export class Scroll { constructor(element) { this.element = element; this.list = ElementHelpers.getElementsByAttribute(this.attributes.list); this.link = ElementHelpers.getElementsByAttribute(this.attributes.link); this.addEventHandlers(); } /** * Declare attribute constants */ get attributes() { return { list: attributeBase + '-list', link: attributeBase + '-link' }; } /** * Add event handlers */ addEventHandlers() { this.addGradientToScrollingList(); this.addAndRemoveGradientOnScroll(); this.handleScrollOnClick(); this.addAndRemoveDividerOnScroll(); this.addDividerToScrollingList(); } /** * Adds a gradient when it is possible to scroll, by comparing offset height with scroll height */ addGradientToScrollingList() { this.element.addEventListener('click', function () { const list = this.nextElementSibling; const offsetHeight = list.offsetHeight; const scrollHeight = list.scrollHeight; const scrollTop = list.scrollTop; const isScrollable = scrollHeight > offsetHeight; const isScrolledToBottom = scrollHeight - offsetHeight - scrollTop < 1; if (isScrollable && !isScrolledToBottom) { if (list.classList.contains('scroll-gradient')) { list.classList.remove('scroll-gradient'); } else { list.classList.add('scroll-gradient'); } } else { list.classList.remove('scroll-gradient'); } }); } /** * removes gradient when scrolled all the way to the bottom * adds gradient when scrolled to the top */ addAndRemoveGradientOnScroll() { this.list.forEach((item) => { item.addEventListener('scroll', () => { const list = item; const scrollTop = list.scrollTop; const scrollHeight = list.scrollHeight; const offsetHeight = list.offsetHeight; const isScrollable = scrollHeight > offsetHeight; const isScrolledToBottom = scrollHeight - offsetHeight - scrollTop < 1; if (isScrolledToBottom && isScrollable) { list.classList.remove('scroll-gradient'); } else { list.classList.add('scroll-gradient'); } }); }); } /** * adds divider when scrolled more than 1px from top * removes the divider when scrolled to top */ addAndRemoveDividerOnScroll() { this.list.forEach((item) => { const element = item.previousElementSibling; item.addEventListener('scroll', () => { const list = item; const scrollTop = list.scrollTop; const scrollHeight = list.scrollHeight; const offsetHeight = list.offsetHeight; const isScrollable = scrollHeight > offsetHeight; if (isScrollable && scrollTop > 1) { element.classList.add('scroll-divider'); } else { element.classList.remove('scroll-divider'); } }); }); } /** * Removes the divider when closing the element */ addDividerToScrollingList() { this.element.addEventListener('click', function () { if (this.classList.contains('scroll-divider')) { this.classList.remove('scroll-divider'); } }); } /** * scrolls the screen to the id of the content defined in the href * uses scrolltoelement helper * sets and removes 'is-active state' */ handleScrollOnClick() { this.link.forEach((item) => { const _this = this; item.addEventListener('click', function () { const link = this.querySelector('a'); const href = link.getAttribute('href').substring(1); const elem = document.getElementById(href); const navHeight = _this.element.offsetHeight; let scrollExtraOffset = ElementHelpers.isDesktop() ? null : -navHeight; const stickyClass = _this.element.parentElement.dataset.rsSticky; const parentContainsStickyClass = _this.element.parentElement.classList.contains(stickyClass); const parentHeight = _this.element.parentElement.offsetHeight; // If the parentcontainer is not sticky it needs to add an extra space to the scroll, because while scrolling down // the navigation becomes absolute and the height will be taken out of the DOM if (!parentContainsStickyClass) { scrollExtraOffset = -parentHeight; } scrollToElement(elem, 500, scrollExtraOffset); _this.link.forEach((item) => { item.classList.remove('is-active'); }); this.classList.add('is-active'); }); }); } /** * Get selector */ static getSelector() { return `[${attributeBase}]`; } }