PageSourceSearch

https://www.saint-dizier.fr/wp-content/themes/saint-dizier/assets/js/a11y-mega-menu.js?ver=1.0.0

js saint-dizier.fr collected 2026-10-02 07:59:55 UTC 7,622 bytes, 214 lines download raw bytes

1const accessibleMenu = function (domNode) {
2    this.rootNode = domNode;
3    this.triggerNodes = [];
4    this.controlledNodes = [];
5    this.openIndex = null;
6    this.useArrowKeys = true;
7  };
8  
9  accessibleMenu.prototype.init = function () {
10    const buttons = this.rootNode.querySelectorAll('.nav-dropdown');
11    for (var i = 0; i < buttons.length; i++) {
12      const button = buttons[i];
13      const menu = button.parentNode.querySelector('.nav-submenu');
14      if (menu) {
15        // Save ref to button and controlled menu.
16        this.triggerNodes.push(button);
17        this.controlledNodes.push(menu);
18  
19        // Collapse menus.
20        button.setAttribute('aria-expanded', 'false');
21        this.toggleMenu(menu, false);
22  
23        // Attach event listeners.
24        menu.addEventListener('keydown', this.handleMenuKeyDown.bind(this));
25        button.addEventListener('click', this.handleButtonClick.bind(this));
26        button.addEventListener('keydown', this.handleButtonKeyDown.bind(this));
27      }
28    }
29
30    this.rootNode.addEventListener('focusout', this.handleBlur.bind(this));
31
32    // Show the menu help instructions when the first button is focused.
33    // const menuHelp = document.querySelector('.menu-help-instructions');
34    // if (buttons[0].getAttribute('aria-expanded') === 'false') {
35    //   buttons[0].addEventListener('focusin', () => {
36
37    //     window.setTimeout(() => {
38    //       menuHelp.classList.remove('sr-only');
39    //     }, 200);
40    //   });
41  
42    //   buttons[0].addEventListener('focusout', () => {
43    //     menuHelp.classList.add('sr-only');
44    //   });
45    // }
46  };
47  
48  accessibleMenu.prototype.toggleMenu = function (domNode, show) {
49    if (domNode) {
50      domNode.style.display = show ? 'flex' : 'none';
51      domNode.style.visibility = show ? 'visible' : 'hidden';
52      domNode.classList.toggle('menu-is-open', show);
53      if ( show && domNode.getAttribute('id') == 'id_menu_search' ) {
54        document.getElementById('menu-search').focus()
55        document.getElementById('menu-search').select()
56      }
57    }
58  };
59  
60  accessibleMenu.prototype.toggleExpand = function (index, expanded) {
61    // Close open menu, if applicable.
62    if (this.openIndex !== index) {
63      this.toggleExpand(this.openIndex, false);
64    }
65
66    // console.log( this.openIndex )
67    // const menus = document.querySelectorAll('.menu-is-open');
68    // for (var i = 0; i < menus.length; i++) {
69    //   menus[i].classList.remove('menu-is-open');
70
71    //   document.querySelector('.nav-toggle').classList.remove('active');
72    //   document.querySelector('.nav-toggle').setAttribute("aria-expanded", 'false');
73    // }
74  
75    // Handle menu at called index.
76    if (this.triggerNodes[index]) {
77      this.openIndex = expanded ? index : null;
78      this.triggerNodes[index].setAttribute('aria-expanded', expanded);
79      this.toggleMenu(this.controlledNodes[index], expanded);
80    }
81  };
82  
83  accessibleMenu.prototype.controlFocusByKey = function (keyboardEvent, nodeList, currentIndex) {
84    switch (keyboardEvent.key) {
85      case 'ArrowUp':
86      case 'ArrowLeft':
87        keyboardEvent.preventDefault();
88        if (currentIndex > -1) {
89          const prevIndex = Math.max(0, currentIndex - 1);
90          nodeList[prevIndex].focus();
91        }
92        break;
93      case 'ArrowDown':
94      case 'ArrowRight':
95        keyboardEvent.preventDefault();
96        if (currentIndex > -1) {
97          const nextIndex = Math.min(nodeList.length - 1, currentIndex + 1);
98          nodeList[nextIndex].focus();
99        }
100        break;
101      case 'Home':
102        keyboardEvent.preventDefault();
103        nodeList[0].focus();
104        break;
105      case 'End':
106        keyboardEvent.preventDefault();
107        nodeList[nodeList.length - 1].focus();
108        break;
109    }
110  };
111  
112  /* Event Handlers */
113  accessibleMenu.prototype.handleBlur = function (event) {
114    const menuContainsFocus = this.rootNode.contains(event.relatedTarget);
115    if (!menuContainsFocus && this.openIndex !== null) {
116      this.toggleExpand(this.openIndex, false);
117    }
118  };
119  
120  accessibleMenu.prototype.handleButtonKeyDown = function (event) {
121    const targetButtonIndex = this.triggerNodes.indexOf(document.activeElement);
122  
123    // Close the menu on the escape key.
124    if (event.key === 'Escape') {
125      this.toggleExpand(this.openIndex, false);
126    }
127  
128    // Move focus into the open menu if the current menu is open.
129    else if (this.useArrowKeys && this.openIndex === targetButtonIndex && event.key === 'ArrowDown') {
130      event.preventDefault();
131      this.controlledNodes[this.openIndex].querySelector('a').focus();
132    }
133  
134    // Handle arrow key navigation between top-level buttons, if set.
135    else if (this.useArrowKeys) {
136      this.controlFocusByKey(event, this.triggerNodes, targetButtonIndex);
137    }
138  };
139  
140  accessibleMenu.prototype.handleButtonClick = function (event) {
141    const button = event.target;
142    const buttonIndex = this.triggerNodes.indexOf(button);
143    const buttonExpanded = button.getAttribute('aria-expanded') === 'true';
144    this.toggleExpand(buttonIndex, !buttonExpanded);
145  };
146  
147  accessibleMenu.prototype.handleMenuKeyDown = function (event) {
148    if (this.openIndex === null) {
149      return;
150    }
151  
152    const menuLinks = Array.prototype.slice.call(this.controlledNodes[this.openIndex].querySelectorAll('a'));
153    const currentIndex = menuLinks.indexOf(document.activeElement);
154  
155    // Close the menu on the escape key.
156    if (event.key === 'Escape') {
157      this.triggerNodes[this.openIndex].focus();
158      this.toggleExpand(this.openIndex, false);
159    }
160  
161    // Handle arrow key navigation within menu links, if set.
162    else if (this.useArrowKeys) {
163      this.controlFocusByKey(event, menuLinks, currentIndex);
164    }
165  };
166  
167  // Switch on/off arrow key navigation.
168  accessibleMenu.prototype.updateKeyControls = function (useArrowKeys) {
169    this.useArrowKeys = useArrowKeys;
170  };
171  
172  // Initialize Menus.
173  window.addEventListener('load', function (event) {
174    const menus = document.querySelectorAll('[role="menubar"]');
175    const accessibleMenus = [];
176  
177    for (var i = 0; i < menus.length; i++) {
178      accessibleMenus[i] = new accessibleMenu(menus[i]);
179      accessibleMenus[i].init();
180    }
181
182    // Toggle Hamburger Button & Dropdown.
183    const hamburgerButtons = document.querySelectorAll('.nav-toggle');
184
185    for (let o = 0; o < hamburgerButtons.length; o++) {
186      hamburgerButtons[o].addEventListener ('click', function ( menu ) {
187
188        hamburgerButtons[o].classList.toggle('active');
189  
190        for (var i = 0; i < accessibleMenus.length; i++) {
191          console.log( hamburgerButtons[o].getAttribute('aria-controls') )
192          console.log( accessibleMenus[i].rootNode.getAttribute('id') )
193          console.log( accessibleMenus[i].openIndex )
194          if ( hamburgerButtons[o].getAttribute('aria-controls') == accessibleMenus[i].rootNode.getAttribute('id') ) {
195            accessibleMenus[i].toggleExpand( accessibleMenus[i].openIndex, false );
196
197            if ( hamburgerButtons[o].getAttribute('aria-expanded') === 'false') {
198              // Set aria attribute.
199              hamburgerButtons[o].setAttribute("aria-expanded", 'true');
200              //Apply toggle class to the first menu from arry.
201              accessibleMenus[i].rootNode.classList.add('menu-is-open');
202      
203      
204            } else {
205              hamburgerButtons[o].setAttribute("aria-expanded", 'false');
206              accessibleMenus[i].rootNode.classList.remove('menu-is-open');
207            }
208          }
209        }
210  
211      });
212    }
213  
214  }, false);

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.