@randstad-design/orbit-multitheme
Version:
multitheme Front-end code based on Randstad Human Forward components
205 lines (185 loc) • 5.68 kB
JavaScript
/**
* navigation.js
*/
import ElementHelpers from '../helpers/element-helpers';
/**
* Declare constants
*/
const attributeBase = 'data-rs-navigation';
export class Navigation {
constructor(element) {
this.element = element;
this.menuIcon = ElementHelpers.getElementByAttribute(
this.attributes.menuIcon
);
this.modalMain = ElementHelpers.getElementByAttributeWithinElement(
this.element,
this.attributes.modalMain
);
this.collapsibles = ElementHelpers.getElementsByAttributeWithinElement(
this.element,
this.attributes.collapsible
);
this.toggables = ElementHelpers.getElementsByAttributeWithinElement(
this.element,
this.attributes.toggable
);
this.modalHeader = ElementHelpers.getElementByAttributeWithinElement(
this.element,
this.attributes.modalHeader
);
this.menuLabelsAttribute = ElementHelpers.getElementByAttribute(
this.attributes.menuLabels
);
this.menuLabels = this.menuLabelsAttribute.getAttribute(
this.attributes.menuLabels
);
this.scrollPos = 0;
this.addEventHandlers();
}
/**
* Declare classes
*/
get classes() {
return {
hidden: 'hidden',
modalOpen: 'modal-open',
modalNavOpen: 'modal-nav-open',
modalActive: 'modal--active',
modalHeaderDivider: 'modal__header--divider',
modalHeaderDividerIn: 'modal__header--divider-in',
modalHeaderDividerOut: 'modal__header--divider-out',
collapsibleTriggerExpanded: 'collapsible__trigger--expanded'
};
}
/**
* Declare attribute constants
*/
get attributes() {
return {
ariaExpanded: 'aria-expanded',
ariaHidden: 'aria-hidden',
collapsibleContent: 'data-rs-collapsible-content',
collapsible: 'data-rs-collapsible',
toggable: 'data-rs-toggable',
content: 'data-rs-collapsible-content',
headerDivider: `${attributeBase}-header-divider`,
menuIcon: `${attributeBase}-menu-icon`,
menuLabels: `${attributeBase}-menu-labels`,
modalMain: `${attributeBase}-modal-main`,
modalHeader: `${attributeBase}-modal-header`
};
}
get getMenuLabels() {
const defaultLabels = {
openMenu: 'open menu',
closeMenu: 'close menu'
};
const labels = this.menuLabels
? JSON.parse(this.menuLabels)
: defaultLabels;
return labels;
}
/**
* Add event handlers
*/
addEventHandlers() {
this.menuIcon.addEventListener('click', () => {
// close all menu items on mobile when menu is closed
if (
document
.querySelector('html')
.classList.contains(this.classes.modalOpen)
) {
this.setMenuAriaLabelToOpen();
setTimeout(() => {
this.closeCollapsible();
}, 500);
} else {
this.setMenuAriaLabelToClose();
}
// add classes to HTML
document
.querySelector('html')
.classList.toggle(`${this.classes.modalOpen}`);
document
.querySelector('html')
.classList.toggle(`${this.classes.modalNavOpen}`);
// add active classes to modal
this.element.classList.toggle(`${this.classes.modalActive}`);
// remove animated border classes on modal
const modalHeaderDivider =
ElementHelpers.getElementByAttributeWithinElement(
this.element,
this.attributes.headerDivider
);
if (modalHeaderDivider !== null) {
modalHeaderDivider.classList.remove(
`${this.classes.modalHeaderDividerIn}`
);
modalHeaderDivider.classList.remove(
`${this.classes.modalHeaderDividerOut}`
);
}
});
this.modalMain.addEventListener(
'scroll',
() => {
this.checkPosition();
},
{ passive: true }
);
}
setMenuAriaLabelToOpen() {
this.menuLabelsAttribute.setAttribute(
'aria-label',
this.getMenuLabels.openMenu
);
}
setMenuAriaLabelToClose() {
this.menuLabelsAttribute.setAttribute(
'aria-label',
this.getMenuLabels.closeMenu
);
}
closeCollapsible() {
this.collapsibles.forEach((element) => {
this.content = element.parentElement.querySelector(
`[${this.attributes.collapsibleContent}]`
);
element.classList.remove(this.classes.collapsibleTriggerExpanded);
element.setAttribute(this.attributes.ariaExpanded, 'false');
element.removeAttribute(this.attributes.expanded);
this.content.style.maxHeight = '0px';
this.content.setAttribute(this.attributes.content, '');
this.content.setAttribute(this.attributes.ariaHidden, 'true');
});
this.toggables.forEach((element) => {
element.classList.remove('icon__toggler--active');
});
}
/**
* Check position
*/
checkPosition() {
const modalMainY = this.modalMain.scrollTop;
if (modalMainY > this.scrollPos) {
this.modalHeader.classList.add(this.classes.modalHeaderDivider);
this.modalHeader.setAttribute(this.attributes.headerDivider, '');
this.modalHeader.classList.add(this.classes.modalHeaderDividerIn);
this.modalHeader.classList.remove(this.classes.modalHeaderDividerOut);
}
if (modalMainY === 0) {
this.modalHeader.classList.add(this.classes.modalHeaderDividerOut);
this.modalHeader.classList.remove(this.classes.modalHeaderDivider);
this.modalHeader.removeAttribute(this.attributes.headerDivider);
this.modalHeader.classList.remove(this.classes.modalHeaderDividerIn);
}
}
/**
* Get selector
*/
static getSelector() {
return `[${attributeBase}]`;
}
}