const TIMEOUT = 150 class MegaDropdown { constructor(element, options = {}) { this._onHover = options.trigger === 'hover' || element.getAttribute('data-trigger') === 'hover' this._container = MegaDropdown._findParent(element, 'mega-dropdown') if (!this._container) return this._menu = this._container.querySelector('.dropdown-toggle ~ .dropdown-menu') if (!this._menu) return element.setAttribute('aria-expanded', 'false') this._el = element this._bindEvents() } open() { if (this._timeout) { clearTimeout(this._timeout) this._timeout = null } if (this._focusTimeout) { clearTimeout(this._focusTimeout) this._focusTimeout = null } if (this._el.getAttribute('aria-expanded') !== 'true') { this._triggerEvent('show') this._container.classList.add('show') this._menu.classList.add('show') this._el.setAttribute('aria-expanded', 'true') this._el.focus() this._triggerEvent('shown') } } close(force) { if (this._timeout) { clearTimeout(this._timeout) this._timeout = null } if (this._focusTimeout) { clearTimeout(this._focusTimeout) this._focusTimeout = null } if (this._onHover && !force) { this._timeout = setTimeout(() => { if (this._timeout) { clearTimeout(this._timeout) this._timeout = null } this._close() }, TIMEOUT) } else { this._close() } } toggle() { // eslint-disable-next-line no-unused-expressions this._el.getAttribute('aria-expanded') === 'true' ? this.close(true) : this.open() } destroy() { this._unbindEvents() this._el = null if (this._timeout) { clearTimeout(this._timeout) this._timeout = null } if (this._focusTimeout) { clearTimeout(this._focusTimeout) this._focusTimeout = null } } _close() { if (this._el.getAttribute('aria-expanded') === 'true') { this._triggerEvent('hide') this._container.classList.remove('show') this._menu.classList.remove('show') this._el.setAttribute('aria-expanded', 'false') this._triggerEvent('hidden') } } _bindEvents() { this._elClickEvnt = e => { e.preventDefault() this.toggle() } this._el.addEventListener('click', this._elClickEvnt) this._bodyClickEvnt = e => { if (!this._container.contains(e.target) && this._container.classList.contains('show')) { this.close(true) } } document.body.addEventListener('click', this._bodyClickEvnt, true) this._menuClickEvnt = e => { if (e.target.classList.contains('mega-dropdown-link')) { this.close(true) } } this._menu.addEventListener('click', this._menuClickEvnt, true) this._focusoutEvnt = () => { if (this._focusTimeout) { clearTimeout(this._focusTimeout) this._focusTimeout = null } if (this._el.getAttribute('aria-expanded') !== 'true') return this._focusTimeout = setTimeout(() => { if ( document.activeElement.tagName.toUpperCase() !== 'BODY' && MegaDropdown._findParent(document.activeElement, 'mega-dropdown') !== this._container ) { this.close(true) } }, 100) } this._container.addEventListener('focusout', this._focusoutEvnt, true) if (this._onHover) { this._enterEvnt = () => { if (window.getComputedStyle(this._menu, null).getPropertyValue('position') === 'static') return this.open() } this._leaveEvnt = () => { if (window.getComputedStyle(this._menu, null).getPropertyValue('position') === 'static') return this.close() } this._el.addEventListener('mouseenter', this._enterEvnt) this._menu.addEventListener('mouseenter', this._enterEvnt) this._el.addEventListener('mouseleave', this._leaveEvnt) this._menu.addEventListener('mouseleave', this._leaveEvnt) } } _unbindEvents() { if (this._elClickEvnt) { this._el.removeEventListener('click', this._elClickEvnt) this._elClickEvnt = null } if (this._bodyClickEvnt) { document.body.removeEventListener('click', this._bodyClickEvnt, true) this._bodyClickEvnt = null } if (this._menuClickEvnt) { this._menu.removeEventListener('click', this._menuClickEvnt, true) this._menuClickEvnt = null } if (this._focusoutEvnt) { this._container.removeEventListener('focusout', this._focusoutEvnt, true) this._focusoutEvnt = null } if (this._enterEvnt) { this._el.removeEventListener('mouseenter', this._enterEvnt) this._menu.removeEventListener('mouseenter', this._enterEvnt) this._enterEvnt = null } if (this._leaveEvnt) { this._el.removeEventListener('mouseleave', this._leaveEvnt) this._menu.removeEventListener('mouseleave', this._leaveEvnt) this._leaveEvnt = null } } static _findParent(el, cls) { if (el.tagName.toUpperCase() === 'BODY') return null el = el.parentNode while (el.tagName.toUpperCase() !== 'BODY' && !el.classList.contains(cls)) { el = el.parentNode } return el.tagName.toUpperCase() !== 'BODY' ? el : null } _triggerEvent(event) { if (document.createEvent) { let customEvent if (typeof Event === 'function') { customEvent = new Event(event) } else { customEvent = document.createEvent('Event') customEvent.initEvent(event, false, true) } this._container.dispatchEvent(customEvent) } else { this._container.fireEvent(`on${event}`, document.createEventObject()) } } } window.MegaDropdown = MegaDropdown export { MegaDropdown }