david-s
8/13/2019 - 10:07 AM

Menu functionality with multiple menus - ES6 Classes

import {SubMenu} from './sub-menu.js';

/**
 * Menu Sub Level Reveal
 *
 */
export class Menu {
  /**
   * Constructor
   */
  constructor() {
    const triggers = document.querySelectorAll('.js-sub-nav-trigger');
    this.triggerList = [...triggers].map(trigger => new SubMenu(trigger, () => this.closeAllMenus()));
  }

  /**
   * Closes all menus
   */
  closeAllMenus() {
    this.triggerList.forEach(trigger => trigger.close());
  }
}
/**
 * The Sub Menu
 *
 */
export class SubMenu {
  /**
   * Constructor
   * @param {Element} element - Menu trigger
   * @param {function} closeAllMenus - Closes all the menus
   */
  constructor(element, closeAllMenus) { // In this example, the 'element' is the parent of the trigger and the menu
    this.triggerAnchor = element.querySelector('.main-nav__menu-anchor');
    this.subMenu = element.querySelector('.sub-menu');
    this.triggerActiveClass = 'main-nav__menu-anchor--active';
    this.menuActiveClass = 'sub-menu--active';
    this.triggerAnchor.addEventListener('click', event => this.toggle(event));
    this.activeState = false;
    this.closeAllMenus = closeAllMenus;
  }

  /**
   * Opens the sub menu
   *
   */
  open() {
    this.closeAllMenus();
    this.triggerAnchor.classList.add(this.triggerActiveClass);
    this.subMenu.classList.add(this.menuActiveClass);
    this.activeState = true;
  }

  /**
   * Closes the sub menu
   *
   */
  close() {
    this.triggerAnchor.classList.remove(this.triggerActiveClass);
    this.subMenu.classList.remove(this.menuActiveClass);
    this.activeState = false;
  }

  /**
   * Toggle the sub menu
   * @param {Event} event - Prevents the default action of the anchor
   */
  toggle(event) {
    event.preventDefault();
    if (this.activeState) {
      this.close();
    } else {
      this.open();
    }
  }
}