1export default class AdicoMenu { 2 offerSlug = "visibilite"; 3 4 constructor(offerSlug = "visibilite") { 5 this.offerSlug = offerSlug; 6 } 7 8 /** 9 * Remplace les liens du premier niveau de menu par des boutons 10 * @param {String} firstUlMenuSelector - Sélecteur CSS du premier niveau de menu 11 */ 12 replaceFirstLinksByButtons(firstUlMenuSelector) { 13 const firstLevelMenu = document.querySelectorAll(firstUlMenuSelector + " > li > a"); 14 15 if (firstLevelMenu) { 16 Array.from(firstLevelMenu).forEach((link) => { 17 const parent = link.parentNode; 18 const text = link.innerText; 19 const hasSubmenu = parent.querySelector(".sub-menu"); 20 21 if (!hasSubmenu) { 22 return link.style.display = "block"; 23 } 24 25 const button = document.createElement("button"); 26 button.innerText = text; 27 button.ariaExpanded = false; 28 button.ariaHaspopup = false; 29 30 link.remove(); 31 if (parent.firstChild) { 32 parent.insertBefore(button, parent.firstChild); 33 } else { 34 parent.appendChild(button); 35 } 36 }) 37 } 38 } 39 40 /** 41 * Gère le toggle du menu mobile 42 * @param {Object} args - Objet contenant les paramètres des selecteurs CSS et de la classe CSS 43 * @param {String} args.menuSelector - Sélecteur CSS du menu 44 * @param {String} args.openSelector - Sélecteur CSS du bouton d'ouverture du menu 45 * @param {String} args.closeSelector - Sélecteur CSS du bouton de fermeture du menu 46 * @param {String} args.className - Classe CSS à ajouter au menu pour l'ouvrir 47 */ 48 toggleMobileMenu(args) { 49 const { 50 menuSelector, 51 openSelector, 52 closeSelector, 53 className, 54 icons 55 } = args; 56 57 const menu = document.querySelector(menuSelector); 58 const open = document.querySelector(openSelector); 59 const close = document.querySelector(closeSelector); 60 61 if (menu) { 62 let firstMenuEntry = menu.querySelector("li:first-child > button"); 63 if (!firstMenuEntry) firstMenuEntry = menu.querySelector("li:first-child > a"); 64 65 if (openSelector == closeSelector) { 66 open.ariaExpanded = false; 67 open.ariaHasPopup = false; 68 const openIcon = document.querySelector(icons.open); 69 const closeIcon = document.querySelector(icons.close); 70 71 open.addEventListener("click", () => { 72 menu.classList.toggle(className); 73 open.ariaExpanded = !JSON.parse(open.ariaExpanded); 74 open.ariaHasPopup = !JSON.parse(open.ariaHasPopup); 75 76 if (openIcon && closeIcon) { 77 if (JSON.parse(open.ariaExpanded)) { 78 openIcon.classList.add("d-none"); 79 closeIcon.classList.remove("d-none"); 80 } else { 81 openIcon.classList.remove("d-none"); 82 closeIcon.classList.add("d-none"); 83 } 84 } 85 86 open.ariaExpanded ? (open.ariaLabel = "Fermer le menu") : (open.ariaLabel = "Ouvrir le menu"); 87 open.classList.toggle("open") 88 89 if (firstMenuEntry) firstMenuEntry.focus(); 90 }); 91 } else { 92 open.addEventListener("click", () => { 93 menu.classList.add(className); 94 open.ariaLabel = "Ouvrir le menu"; 95 open.classList.add("open") 96 if (firstMenuEntry) firstMenuEntry.focus(); 97 }); 98 99 close.addEventListener("click", () => { 100 menu.classList.remove(className); 101 open.ariaLabel = "Fermer le menu"; 102 open.classList.remove("open") 103 }); 104 } 105 } 106 107 } 108 109 110 /** 111 * Gère la navigation au clavier 112 * @param {Object} args - Objet contenant les paramètres des selecteurs CSS et de la classe CSS 113 * @param {String} args.wpNavMenu - Si le menu est un menu WordPress (wp_nav_menu()) 114 * @param {String} args.replacedByButtons - Si les liens sont remplacés par des boutons 115 * @param {String} args.firstUlMenuSelector - Sélecteur CSS du menu 116 * @param {String} args.subMenuSelector - Sélecteur CSS du sous-menu (Optionel si wpNavMenu: true) 117 */ 118 keyboardNavigation(args) { 119 let { 120 wpNavMenu, 121 replacedByButtons, 122 firstUlMenuSelector, 123 subMenuSelector, 124 } = args; 125 126 let buttonElement = "button"; 127 if (!replacedByButtons) buttonElement = "a"; 128 129 if (!subMenuSelector) subMenuSelector = ".sub-menu"; 130 if (wpNavMenu) subMenuSelector = ".sub-menu"; 131 132 const selector = firstUlMenuSelector + " > li > " + buttonElement; 133 const firstLevel = document.querySelectorAll(selector); 134 135 if (!firstLevel) return; 136 137 Array.from(firstLevel).forEach(button => { 138 const parent = button.parentNode; 139 const subMenu = parent.querySelector(buttonElement + " + " + subMenuSelector); 140 141 if (subMenu) { 142 // Toggle le sous menu avec le clavier 143 button.addEventListener("keydown", (e) => { 144 if (e.key === " " || e.key === "Enter") { 145 e.preventDefault(); 146 button.ariaExpanded = !button.ariaExpanded; 147 button.ariaHaspopup = !button.ariaHaspopup; 148 button.ariaExpanded ? button.ariaLabel = "Fermer le sous-menu" : button.ariaLabel = "Ouvrir le sous-menu"; 149 subMenu.classList.toggle("open"); 150 } 151 }) 152 153 // Ferme le sous menu après le dernier élément 154 const lastLinkSelector = this.offerSlug == "visibilite" ? "li:last-child > a" : "li:last-child > .sub-menu > li:last-child > a"; 155 const lastLinks = subMenu.querySelectorAll(lastLinkSelector); 156 157 lastLinks.forEach(link => { 158 link.addEventListener("keydown", e => { 159 if (e.key === "Tab" && !e.shiftKey) { 160 e.preventDefault(); 161 subMenu.classList.remove("open"); 162 button.ariaExpanded = false;
163 button.ariaHaspopup = false; 164 button.ariaLabel = "Ouvrir le sous-menu"; 165 } 166 }) 167 }) 168 } 169 }) 170 171 } 172 173 flexibiliteSubMenuTitleRGAA(menuSelector) { 174 const subMenuTitle = document.querySelectorAll(menuSelector + " > li > .sub-menu > li > a:first-child"); 175 176 Array.from(subMenuTitle).forEach((title) => { 177 const parent = title.parentNode; 178 const p = document.createElement("p"); 179 p.innerText = title.innerText 180 181 if (parent.firstChild) { 182 title.remove(); 183 parent.insertBefore(p, parent.firstChild); 184 } 185 }); 186 187 } 188}
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.