UNPKG

@randstad-design/orbit-multitheme

Version:

multitheme Front-end code based on Randstad Human Forward components

186 lines (167 loc) 6.58 kB
/** * import dependencies */ import ElementHelpers from '../helpers/element-helpers'; import smoothscroll from 'smoothscroll-polyfill'; /** * Declare global vars */ const attributeBase = 'data-rs-tab-bar'; export class TabBar { constructor(element) { smoothscroll.polyfill(); this.element = element; this.items = ElementHelpers.getElementsByAttributeWithinElement(this.element, this.attributes.item); this.setVariables(); this.setFadeElements(); this.addEventListeners(); this.toggleFadeElements(); this.scrollToActive(); } /** * Declare class constants */ get classes() { return { fadeElement: 'fade-element', fadeElementRight: 'fade-element--right', fadeElementLeft: 'fade-element--left', icon: 'icon', iconLeft: 'icon__left', iconRight: 'icon__right', hide: 'hide', active: 'active' } } /** * Declare attribute constants */ get attributes() { return { item: `${attributeBase}-item`, iconLeft: `${attributeBase}-icon-left`, iconRight: `${attributeBase}-icon-right`, fadeElementLeft: `${attributeBase}-fade-element-left`, fadeElementRight: `${attributeBase}-fade-element-right` } } /** * Declare HTML variables * SVG chrevron templates */ setVariables() { this.chevronRight = `<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path d="M7,2 C7.256,2 7.512,2.098 7.707,2.293 L14.707,9.293 C15.098,9.684 15.098,10.316 14.707,10.707 L7.707,17.707 C7.316,18.098 6.684,18.098 6.293,17.707 C5.902,17.316 5.902,16.684 6.293,16.293 L12.586,10 L6.293,3.707 C5.902,3.316 5.902,2.684 6.293,2.293 C6.488,2.098 6.744,2 7,2"/> </svg>`; this.chevronLeft = `<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path d="M13,18 C12.744,18 12.488,17.902 12.293,17.707 L5.293,10.707 C4.902,10.316 4.902,9.684 5.293,9.293 L12.293,2.293 C12.684,1.902 13.316,1.902 13.707,2.293 C14.098,2.684 14.098,3.316 13.707,3.707 L7.414,10 L13.707,16.293 C14.098,16.684 14.098,17.316 13.707,17.707 C13.512,17.902 13.256,18 13,18"/> </svg>`; this.fadeLeft = `<div class="${this.classes.fadeElement} ${this.classes.fadeElementLeft} ${this.classes.hide}" ${this.attributes.fadeElementLeft}><div ${this.attributes.iconLeft} class="${this.classes.icon} ${this.classes.iconLeft}">${this.chevronLeft}</div></div>`; this.fadeRight = `<div class="${this.classes.fadeElement} ${this.classes.fadeElementRight} ${this.classes.hide}" ${this.attributes.fadeElementRight}><div ${this.attributes.iconRight} class="${this.classes.icon} ${this.classes.iconRight}">${this.chevronRight}</div></div>`; } /** * insert fade elements at start and end of list items */ setFadeElements() { this.items.forEach((item, index, array) => { if (index === 1) { item.insertAdjacentHTML('beforebegin', this.fadeLeft); } if (index === array.length - 1) { item.insertAdjacentHTML('afterend', this.fadeRight); } }); } /** * add event listeners to all Tab-bar elements */ addEventListeners() { this.iconLeft = ElementHelpers.getElementByAttributeWithinElement(this.element, this.attributes.iconLeft); this.iconRight = ElementHelpers.getElementByAttributeWithinElement(this.element, this.attributes.iconRight); // scroll left on click this.iconLeft.addEventListener('click', () => { this.element.scrollBy({left: -(this.element.clientWidth / 2), behavior: 'smooth'}) }); // scroll right on click this.iconRight.addEventListener('click', () => { this.element.scrollBy({left: (this.element.clientWidth / 2), behavior: 'smooth'}) }); //reset position fadeElement/chevron on scroll this.element.addEventListener('scroll', () => { this.toggleFadeElements(); }); //reset position fadeElement/chevron on resize window.addEventListener('resize', () => { this.toggleFadeElements(); this.scrollToActive(); }); //loop items and add click event to call setActiveClass function this.items.forEach(item => { item.addEventListener('click', (event) => { event.preventDefault; this.setActiveClass(event); }); }); } /** * Set or remove active state on list item */ setActiveClass(event) { this.items.forEach(item => { item.classList.remove(this.classes.active); }); event.currentTarget.classList.add(this.classes.active); this.scrollToActive(); } /** * on init and resize, scroll to active item */ scrollToActive() { this.activeElement = ElementHelpers.getElementByClassWithinElement(this.element, this.classes.active); const rectTabBar = this.element.getBoundingClientRect(); const rectActiveTab = this.activeElement.getBoundingClientRect(); const viewportWidth = window.innerWidth; const inScreenSize = viewportWidth - (rectTabBar.left * 2); if ((rectActiveTab.left + (this.activeElement.clientWidth) > inScreenSize)) { this.element.scrollBy({behavior: 'smooth', left: (rectActiveTab.left - (rectTabBar.left * 2))}); } else if (rectActiveTab.left < (this.activeElement.clientWidth + 50)) { this.element.scrollBy({behavior: 'smooth', left: (rectActiveTab.left - (inScreenSize / 2))}); } } /** * Hide or show the Fade elements and position them */ toggleFadeElements() { this.fadeElementRight = ElementHelpers.getElementByAttributeWithinElement(this.element, this.attributes.fadeElementRight); this.fadeElementLeft = ElementHelpers.getElementByAttributeWithinElement(this.element, this.attributes.fadeElementLeft); //calculate maximum scroll left let maxScrollLeft = this.element.scrollWidth - this.element.clientWidth; //calculate the position for the chevrons this.screenCenter = window.innerWidth / 2; this.tabBarWidth = this.element.clientWidth; this.positionLeft = this.screenCenter - (this.tabBarWidth / 2); this.positionRight = this.screenCenter + (this.tabBarWidth / 2); // hide/show fade element right if (this.element.scrollLeft > maxScrollLeft - 20) { this.fadeElementRight.classList.add(this.classes.hide); } else { this.fadeElementRight.classList.remove(this.classes.hide); // minus 25px for the right-fadeElement width this.fadeElementRight.style.left = `${this.positionRight - 25}px`; } // hide/show fade element left if (this.element.scrollLeft > 10) { this.fadeElementLeft.classList.remove(this.classes.hide); // minus 25px for the left-fadeElement width this.fadeElementLeft.style.left = `${this.positionLeft - 25}px`; } else { this.fadeElementLeft.classList.add(this.classes.hide); } } /** * Get selector */ static getSelector() { return '[' + attributeBase + ']'; } }