@randstad-design/orbit-multitheme
Version:
multitheme Front-end code based on Randstad Human Forward components
186 lines (167 loc) • 6.58 kB
JavaScript
/**
* 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 + ']';
}
}