156 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * @file
 | 
						|
 *
 | 
						|
 * Sidebar component.
 | 
						|
 *
 | 
						|
 * Only few common things. Like close all popovers when one is opened.
 | 
						|
 *
 | 
						|
 * @type {Drupal~behavior}
 | 
						|
 *
 | 
						|
 * @prop {Drupal~behaviorAttach} attach
 | 
						|
 *   Attaches the behavior to the `.admin-toolbar` element.
 | 
						|
 */
 | 
						|
 | 
						|
(
 | 
						|
  (Drupal, once) => {
 | 
						|
    /**
 | 
						|
     * Drupal behaviors object.
 | 
						|
     *
 | 
						|
     * @type {Drupal~behaviors}
 | 
						|
     */
 | 
						|
 | 
						|
    Drupal.behaviors.navigation = {
 | 
						|
      attach(context) {
 | 
						|
        /**
 | 
						|
         * Sidebar element with the `.admin-toolbar` class.
 | 
						|
         *
 | 
						|
         * @type {HTMLElement}
 | 
						|
         */
 | 
						|
        once('navigation', '.admin-toolbar', context).forEach((sidebar) => {
 | 
						|
          const backButton = sidebar.querySelector(
 | 
						|
            '[data-toolbar-back-control]',
 | 
						|
          );
 | 
						|
          if (!backButton) {
 | 
						|
            // We're in layout editing mode and the .admin-toolbar we have in
 | 
						|
            // scope here is the empty one that only exists to leave space for
 | 
						|
            // the one added by layout builder. We need to use an empty
 | 
						|
            // .admin-toolbar element because the css uses the adjacent
 | 
						|
            // sibling selector.
 | 
						|
            // @see \navigation_page_top();
 | 
						|
            return;
 | 
						|
          }
 | 
						|
 | 
						|
          /**
 | 
						|
           * All menu triggers.
 | 
						|
           *
 | 
						|
           * @type {NodeList}
 | 
						|
           */
 | 
						|
          const buttons = sidebar.querySelectorAll(
 | 
						|
            '[data-toolbar-menu-trigger]',
 | 
						|
          );
 | 
						|
 | 
						|
          /**
 | 
						|
           * All popovers and tooltip triggers.
 | 
						|
           *
 | 
						|
           * @type {NodeList}
 | 
						|
           */
 | 
						|
          // const popovers = sidebar.querySelectorAll('[data-toolbar-popover]');
 | 
						|
 | 
						|
          /**
 | 
						|
           * NodeList of all tooltip elements.
 | 
						|
           *
 | 
						|
           * @type {NodeList}
 | 
						|
           */
 | 
						|
          const tooltips = sidebar.querySelectorAll('[data-drupal-tooltip]');
 | 
						|
 | 
						|
          const closeButtons = () => {
 | 
						|
            buttons.forEach((button) => {
 | 
						|
              button.dispatchEvent(
 | 
						|
                new CustomEvent('toolbar-menu-set-toggle', {
 | 
						|
                  detail: {
 | 
						|
                    state: false,
 | 
						|
                  },
 | 
						|
                }),
 | 
						|
              );
 | 
						|
            });
 | 
						|
          };
 | 
						|
 | 
						|
          const closePopovers = (current = false) => {
 | 
						|
            // TODO: Find way to use popovers variable.
 | 
						|
            // This change needed because BigPipe replaces user popover.
 | 
						|
            sidebar
 | 
						|
              .querySelectorAll('[data-toolbar-popover]')
 | 
						|
              .forEach((popover) => {
 | 
						|
                if (
 | 
						|
                  current &&
 | 
						|
                  current instanceof Element &&
 | 
						|
                  popover.isEqualNode(current)
 | 
						|
                ) {
 | 
						|
                  return;
 | 
						|
                }
 | 
						|
                popover.dispatchEvent(
 | 
						|
                  new CustomEvent('toolbar-popover-close', {}),
 | 
						|
                );
 | 
						|
              });
 | 
						|
          };
 | 
						|
 | 
						|
          // Add click event listeners to all buttons and then contains the callback
 | 
						|
          // to expand / collapse the button's menus.
 | 
						|
          sidebar.addEventListener('click', (e) => {
 | 
						|
            if (e.target.matches('button, button *')) {
 | 
						|
              e.target.closest('button').focus();
 | 
						|
            }
 | 
						|
          });
 | 
						|
 | 
						|
          // We want to close all popovers when we close sidebar.
 | 
						|
          sidebar.addEventListener('toggle-admin-toolbar-content', (e) => {
 | 
						|
            if (!e.detail.state) {
 | 
						|
              closePopovers();
 | 
						|
            }
 | 
						|
          });
 | 
						|
 | 
						|
          // When any popover opened we close all others.
 | 
						|
          sidebar.addEventListener('toolbar-popover-toggled', (e) => {
 | 
						|
            if (e.detail.state) {
 | 
						|
              closeButtons();
 | 
						|
              closePopovers(e.target);
 | 
						|
            }
 | 
						|
          });
 | 
						|
 | 
						|
          // When any menu opened we close all others.
 | 
						|
          sidebar.addEventListener('toolbar-menu-toggled', (e) => {
 | 
						|
            if (e.detail.state) {
 | 
						|
              // We want to close buttons on when new opened only if they are on same level.
 | 
						|
              const targetLevel = e.detail.level;
 | 
						|
              buttons.forEach((button) => {
 | 
						|
                const buttonLevel = button.dataset.toolbarMenuTrigger;
 | 
						|
                if (
 | 
						|
                  !button.isEqualNode(e.target) &&
 | 
						|
                  +buttonLevel === +targetLevel
 | 
						|
                ) {
 | 
						|
                  button.dispatchEvent(
 | 
						|
                    new CustomEvent('toolbar-menu-set-toggle', {
 | 
						|
                      detail: {
 | 
						|
                        state: false,
 | 
						|
                      },
 | 
						|
                    }),
 | 
						|
                  );
 | 
						|
                }
 | 
						|
              });
 | 
						|
            }
 | 
						|
          });
 | 
						|
          backButton.addEventListener('click', closePopovers);
 | 
						|
 | 
						|
          // Tooltips triggered on hover and focus so add an extra event listener
 | 
						|
          // to close all popovers.
 | 
						|
          tooltips.forEach((tooltip) => {
 | 
						|
            ['mouseover', 'focus'].forEach((e) => {
 | 
						|
              tooltip.addEventListener(e, closePopovers);
 | 
						|
            });
 | 
						|
          });
 | 
						|
        });
 | 
						|
      },
 | 
						|
    };
 | 
						|
  }
 | 
						|
)(Drupal, once);
 |