PageSourceSearch

https://www.elle.cz/js/modules/mobileNavigation.js

js elle.cz collected 2026-10-02 07:55:39 UTC 3,216 bytes, 124 lines download raw bytes

1import {setAriaExpanded, setElementHidden} from '../core/aria.js';
2
3const createMobileNavState = () => {
4  const root = document.querySelector('.mobile-nav');
5  if (!(root instanceof HTMLElement)) {
6    return null;
7  }
8
9  const toggleButton = root.querySelector('[data-mobile-menu-toggle]');
10  const panel = root.querySelector('[data-mobile-menu-panel]');
11  if (!(toggleButton instanceof HTMLButtonElement) || !(panel instanceof HTMLElement)) {
12    return null;
13  }
14
15  return {
16    root,
17    toggleButton,
18    panel,
19    closeButton: root.querySelector('[data-mobile-menu-close]'),
20    submenuToggles: Array.from(root.querySelectorAll('[data-mobile-submenu-toggle]'))
21  };
22};
23
24const closeAllMobileSubmenus = (state) => {
25  state.submenuToggles.forEach((toggle) => {
26    if (!(toggle instanceof HTMLButtonElement)) {
27      return;
28    }
29
30    const panelId = toggle.getAttribute('aria-controls');
31    if (!panelId) {
32      return;
33    }
34
35    const submenuPanel = state.root.querySelector(`#${panelId}`);
36    if (!(submenuPanel instanceof HTMLElement)) {
37      return;
38    }
39
40    toggle.classList.remove('is-open');
41    setAriaExpanded(toggle, false);
42    submenuPanel.classList.remove('is-open');
43    setElementHidden(submenuPanel, true);
44  });
45};
46
47const setMobileMenuOpenState = (state, isOpen) => {
48  state.root.classList.toggle('is-open', isOpen);
49  setAriaExpanded(state.toggleButton, isOpen);
50  setElementHidden(state.panel, !isOpen);
51
52  if (!isOpen) {
53    closeAllMobileSubmenus(state);
54  }
55};
56
57const bindMobileMenuToggleEvents = (state) => {
58  state.toggleButton.addEventListener('click', () => {
59    const isOpen = state.root.classList.contains('is-open');
60    setMobileMenuOpenState(state, !isOpen);
61  });
62
63  if (state.closeButton instanceof HTMLButtonElement) {
64    state.closeButton.addEventListener('click', () => {
65      setMobileMenuOpenState(state, false);
66    });
67  }
68};
69
70const bindMobileSubmenuEvents = (state) => {
71  state.submenuToggles.forEach((toggle) => {
72    if (!(toggle instanceof HTMLButtonElement)) {
73      return;
74    }
75
76    const panelId = toggle.getAttribute('aria-controls');
77    if (!panelId) {
78      return;
79    }
80
81    const submenuPanel = state.root.querySelector(`#${panelId}`);
82    if (!(submenuPanel instanceof HTMLElement)) {
83      return;
84    }
85
86    toggle.addEventListener('click', () => {
87      const shouldOpen = !toggle.classList.contains('is-open');
88      closeAllMobileSubmenus(state);
89      if (!shouldOpen) {
90        return;
91      }
92
93      toggle.classList.add('is-open');
94      setAriaExpanded(toggle, true);
95      submenuPanel.classList.add('is-open');
96      setElementHidden(submenuPanel, false);
97    });
98  });
99};
100
101const bindMobileGlobalEvents = (state) => {
102  document.addEventListener('keydown', (event) => {
103    if (event.key === 'Escape') {
104      setMobileMenuOpenState(state, false);
105    }
106  });
107
108  window.addEventListener('resize', () => {
109    if (window.innerWidth >= 1024) {
110      setMobileMenuOpenState(state, false);
111    }
112  });
113};
114
115export const initMobileNavigation = () => {
116  const state = createMobileNavState();
117  if (!state) {
118    return;
119  }
120
121  bindMobileMenuToggleEvents(state);
122  bindMobileSubmenuEvents(state);
123  bindMobileGlobalEvents(state);
124};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.