182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Common JS managing behavior of admin-toolbar.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Init Toolbar triggers.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * One trigger is button in Toolbar.
							 | 
						||
| 
								 | 
							
								 * Another button in control panel on mobile.
							 | 
						||
| 
								 | 
							
								 * Third is mobile shadow.
							 | 
						||
| 
								 | 
							
								 * Fourth is close sidebar button on mobile.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @type {Drupal~behavior}
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @prop {Drupal~behaviorAttach} attach
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(
							 | 
						||
| 
								 | 
							
								  (Drupal, once) => {
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constant representing the event name for toggling the admin toolbar state.
							 | 
						||
| 
								 | 
							
								     * @type {string}
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    const HTML_TRIGGER_EVENT = 'toggle-admin-toolbar';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constant representing the event name for toggling the admin toolbar content.
							 | 
						||
| 
								 | 
							
								     * @type {string}
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    const SIDEBAR_CONTENT_EVENT = 'toggle-admin-toolbar-content';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (
							 | 
						||
| 
								 | 
							
								      once('admin-toolbar-document-triggers-listener', document.documentElement)
							 | 
						||
| 
								 | 
							
								        .length
							 | 
						||
| 
								 | 
							
								    ) {
							 | 
						||
| 
								 | 
							
								      const doc = document.documentElement;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // This is special attribute which added to apply css
							 | 
						||
| 
								 | 
							
								      // with animations and avoid layout shift.
							 | 
						||
| 
								 | 
							
								      setTimeout(() => {
							 | 
						||
| 
								 | 
							
								        doc.setAttribute('data-admin-toolbar-transitions', true);
							 | 
						||
| 
								 | 
							
								      }, 100);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      doc.addEventListener(HTML_TRIGGER_EVENT, (e) => {
							 | 
						||
| 
								 | 
							
								        // Prevents multiple triggering while transitioning.
							 | 
						||
| 
								 | 
							
								        const newState = e.detail.state;
							 | 
						||
| 
								 | 
							
								        const isUserInput = e.detail.manual;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        document.documentElement.setAttribute(
							 | 
						||
| 
								 | 
							
								          'data-admin-toolbar',
							 | 
						||
| 
								 | 
							
								          newState ? 'expanded' : 'collapsed',
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Set [data-admin-toolbar-body-scroll='locked']
							 | 
						||
| 
								 | 
							
								        // See css/components/body-scroll-lock.pcss.css.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        document.documentElement.setAttribute(
							 | 
						||
| 
								 | 
							
								          'data-admin-toolbar-body-scroll',
							 | 
						||
| 
								 | 
							
								          newState ? 'locked' : 'unlocked',
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        doc.querySelector('.admin-toolbar')?.dispatchEvent(
							 | 
						||
| 
								 | 
							
								          new CustomEvent(SIDEBAR_CONTENT_EVENT, {
							 | 
						||
| 
								 | 
							
								            detail: {
							 | 
						||
| 
								 | 
							
								              state: newState,
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								          }),
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isUserInput) {
							 | 
						||
| 
								 | 
							
								          document.documentElement.setAttribute(
							 | 
						||
| 
								 | 
							
								            'data-admin-toolbar-animating',
							 | 
						||
| 
								 | 
							
								            true,
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        setTimeout(() => {
							 | 
						||
| 
								 | 
							
								          document.documentElement.removeAttribute(
							 | 
						||
| 
								 | 
							
								            'data-admin-toolbar-animating',
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								        }, 200);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Drupal.displace(true);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Initialize Drupal.displace()
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * We add the displace attribute to a separate full width element because we
							 | 
						||
| 
								 | 
							
								     * don't want this element to have transitions. Note that this element and the
							 | 
						||
| 
								 | 
							
								     * navbar share the same exact width.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param {HTMLElement} el - The admin toolbar wrapper.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    const initDisplace = (el) => {
							 | 
						||
| 
								 | 
							
								      const displaceElement = el.querySelector(
							 | 
						||
| 
								 | 
							
								        '.admin-toolbar__displace-placeholder',
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								      const edge = document.documentElement.dir === 'rtl' ? 'right' : 'left';
							 | 
						||
| 
								 | 
							
								      displaceElement?.setAttribute(`data-offset-${edge}`, '');
							 | 
						||
| 
								 | 
							
								      Drupal.displace(true);
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Any triggers on page. Inside or outside sidebar.
							 | 
						||
| 
								 | 
							
								    // For now button in sidebar + mobile header and background.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Drupal.behaviors.navigationProcessToolbarTriggers = {
							 | 
						||
| 
								 | 
							
								      attach: (context) => {
							 | 
						||
| 
								 | 
							
								        once('navigation-displace', '.admin-toolbar', context).forEach(
							 | 
						||
| 
								 | 
							
								          initDisplace,
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const triggers = once(
							 | 
						||
| 
								 | 
							
								          'admin-toolbar-trigger',
							 | 
						||
| 
								 | 
							
								          '[aria-controls="admin-toolbar"]',
							 | 
						||
| 
								 | 
							
								          context,
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Updates the state of all trigger elements based on the provided state.
							 | 
						||
| 
								 | 
							
								         *
							 | 
						||
| 
								 | 
							
								         * @param {boolean} toState The new state of the sidebar.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        const toggleTriggers = (toState) => {
							 | 
						||
| 
								 | 
							
								          triggers.forEach((trigger) => {
							 | 
						||
| 
								 | 
							
								            trigger.setAttribute('aria-expanded', toState);
							 | 
						||
| 
								 | 
							
								            const text =
							 | 
						||
| 
								 | 
							
								              trigger.querySelector('[data-toolbar-text]') ||
							 | 
						||
| 
								 | 
							
								              trigger.querySelector('[data-toolbar-action]');
							 | 
						||
| 
								 | 
							
								            if (text) {
							 | 
						||
| 
								 | 
							
								              text.textContent = toState
							 | 
						||
| 
								 | 
							
								                ? Drupal.t('Collapse sidebar')
							 | 
						||
| 
								 | 
							
								                : Drupal.t('Expand sidebar');
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								          localStorage.setItem('Drupal.navigation.sidebarExpanded', toState);
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (triggers.length) {
							 | 
						||
| 
								 | 
							
								          let firstState =
							 | 
						||
| 
								 | 
							
								            localStorage.getItem('Drupal.navigation.sidebarExpanded') !==
							 | 
						||
| 
								 | 
							
								            'false';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // We need to display closed sidebar on init on mobile.
							 | 
						||
| 
								 | 
							
								          if (window.matchMedia('(max-width: 1023px)').matches) {
							 | 
						||
| 
								 | 
							
								            firstState = false;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // Set values on load.
							 | 
						||
| 
								 | 
							
								          toggleTriggers(firstState);
							 | 
						||
| 
								 | 
							
								          document.documentElement.dispatchEvent(
							 | 
						||
| 
								 | 
							
								            new CustomEvent(HTML_TRIGGER_EVENT, {
							 | 
						||
| 
								 | 
							
								              bubbles: true,
							 | 
						||
| 
								 | 
							
								              detail: {
							 | 
						||
| 
								 | 
							
								                state: firstState,
							 | 
						||
| 
								 | 
							
								                manual: false,
							 | 
						||
| 
								 | 
							
								              },
							 | 
						||
| 
								 | 
							
								            }),
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          triggers.forEach((trigger) => {
							 | 
						||
| 
								 | 
							
								            trigger.addEventListener('click', (e) => {
							 | 
						||
| 
								 | 
							
								              const state =
							 | 
						||
| 
								 | 
							
								                e.currentTarget.getAttribute('aria-expanded') === 'false';
							 | 
						||
| 
								 | 
							
								              trigger.dispatchEvent(
							 | 
						||
| 
								 | 
							
								                new CustomEvent(HTML_TRIGGER_EVENT, {
							 | 
						||
| 
								 | 
							
								                  bubbles: true,
							 | 
						||
| 
								 | 
							
								                  detail: {
							 | 
						||
| 
								 | 
							
								                    state,
							 | 
						||
| 
								 | 
							
								                    manual: true,
							 | 
						||
| 
								 | 
							
								                  },
							 | 
						||
| 
								 | 
							
								                }),
							 | 
						||
| 
								 | 
							
								              );
							 | 
						||
| 
								 | 
							
								              toggleTriggers(state);
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								)(Drupal, once);
							 |