UNPKG

@randstad-design/orbit-multitheme

Version:

multitheme Front-end code based on Randstad Human Forward components

182 lines (159 loc) 4.29 kB
/** * popover.js */ import ElementHelpers from '../helpers/element-helpers'; import trapFocus from '../helpers/trapFocus'; /** * Declare constants */ const attributeBase = 'data-rs-popover'; export class Popover { constructor(element) { this.element = element; this.trigger = ElementHelpers.getElementByAttribute( this.attributes.trigger, this.element.getAttribute(attributeBase) ); this.overlay = ElementHelpers.getElementByAttribute( this.attributes.overlay ); this.disableOverlay = this.element.hasAttribute( this.attributes.disableOverlay ); this.popoverOpen; this.addEventHandlers(); this.isOpenByDefault(); this.keystroke = 0; } /** * Declare classes */ get classes() { return { popoverActive: 'popover--active', modalOverlayActive: 'modal__overlay--active', active: 'active' }; } /** * Declare attribute constants */ get attributes() { return { overlay: `${attributeBase}-overlay`, trigger: `${attributeBase}-trigger`, disableOverlay: `${attributeBase}-disable-overlay`, hidden: 'aria-hidden' }; } /** * Add event handlers */ addEventHandlers() { if (this.trigger) { this.trigger.addEventListener('click', () => { if (!this.popoverOpen) { this.openPopover(this.element); } else { this.closePopover(this.popoverOpen); } this.toggleActiveClassOnTrigger(); }); } if (this.overlay && !this.disableOverlay && this.popoverOpen) { this.overlay.addEventListener('click', () => { this.closePopover(this.popoverOpen); if (this.trigger) { this.toggleActiveClassOnTrigger(); } }); } else { window.addEventListener('click', (clickEvent) => { if (!this.popoverOpen) { return; } if ( (this.trigger && this.trigger.contains(clickEvent.target)) || this.popoverOpen.contains(clickEvent.target) ) { return; } this.closePopover(this.popoverOpen); if (this.trigger) { this.toggleActiveClassOnTrigger(); } }); } document.addEventListener('keydown', (keydownEvent) => { this.handleButtonKeys(keydownEvent); }); } isOpenByDefault() { return this.element.classList.contains(this.classes.popoverActive) ? (this.popoverOpen = this.element) : null; } openPopover(activePopover) { if (!activePopover) { return; } activePopover.classList.add(this.classes.popoverActive); activePopover.removeAttribute(this.attributes.hidden); if (this.overlay !== null && !this.disableOverlay) { this.overlay.classList.add(this.classes.modalOverlayActive); } this.popoverOpen = activePopover; } closePopover(activePopover) { if (!activePopover) { return; } activePopover.classList.remove(this.classes.popoverActive); activePopover.setAttribute(this.attributes.hidden, 'true'); if (this.overlay && !this.disableOverlay) { this.overlay.classList.remove(this.classes.modalOverlayActive); } this.popoverOpen = false; this.keystroke = 0; } /** * Toggle active class on trigger element */ toggleActiveClassOnTrigger() { if (this.trigger.classList.contains(this.classes.active)) { this.trigger.classList.remove(this.classes.active); } else { this.trigger.classList.add(this.classes.active); } } /** * Handle button keys - handle key presses escape * * @param {Event} event - event triggered */ handleButtonKeys(event) { if (event != null) { switch (ElementHelpers.getKeyCodeOnKeyDownEvent(event)) { case 'Tab': trapFocus(event, this.element, this.popoverOpen, this.keystroke); if (this.popoverOpen) { this.keystroke++; } break; case 'Escape': if (this.popoverOpen) { this.closePopover(this.popoverOpen); if (this.trigger) { this.trigger.focus(); } } } } } /** * Get selector */ static getSelector() { return `[${attributeBase}]`; } }