1(function () { 2 if (window.__confNavInit) { 3 return; 4 } 5 window.__confNavInit = true; 6 7 var root = document.querySelector(".conf-nav"); 8 if (!root) { 9 return; 10 } 11 12 root.classList.add("conf-nav--js"); 13 14 var desktop = root.querySelector(".conf-nav__desktop"); 15 if (desktop) { 16 desktop.querySelectorAll(".conf-nav__panel").forEach(function (item) { 17 item.hidden = true; 18 }); 19 } 20 var mobileRoot = root.querySelector("[data-conf-root]"); 21 var burger = document.querySelector(".hamburger-icon"); 22 var desktopQuery = window.matchMedia("(min-width: 1201px)"); 23 24 function isDesktop() { 25 return desktopQuery.matches; 26 } 27 28 var closeTimer = null; 29 30 function cancelClose() { 31 if (closeTimer) { 32 window.clearTimeout(closeTimer); 33 closeTimer = null; 34 } 35 } 36 37 function scheduleClose() { 38 cancelClose(); 39 closeTimer = window.setTimeout(function () { 40 closeDesktop(false); 41 }, 140); 42 } 43 44 function syncScrollLock() { 45 var mobileOpen = root.classList.contains("menu_active"); 46 document.body.classList.toggle("conf-nav-open", mobileOpen); 47 if (burger) { 48 burger.setAttribute("aria-expanded", mobileOpen ? "true" : "false"); 49 burger.setAttribute("aria-label", mobileOpen ? "Close menu" : "Open menu"); 50 } 51 } 52 53 function placeMobileMenu() { 54 var header = document.querySelector("header.header.main_header"); 55 if (!header) { 56 return; 57 } 58 var bottom = Math.max(0, Math.round(header.getBoundingClientRect().bottom)); 59 root.style.top = bottom + "px"; 60 root.style.height = "calc(100dvh - " + bottom + "px)"; 61 } 62 63 function placePanel() { 64 if (!desktop || !isDesktop()) { 65 return; 66 } 67 var header = document.querySelector("header.header.main_header"); 68 var container = header ? header.querySelector(".header__container") : null; 69 var panels = desktop.querySelectorAll(".conf-nav__panel"); 70 var sticky = document.body.classList.contains("scrolled") && header; 71 if (sticky) { 72 var headerRect = header.getBoundingClientRect(); 73 var box = (container || header).getBoundingClientRect(); 74 var top = Math.round(headerRect.bottom) + "px"; 75 var stickyLeft = Math.round(box.left) + "px"; 76 var stickyWidth = Math.round(box.width) + "px"; 77 panels.forEach(function (item) { 78 item.style.position = "fixed"; 79 item.style.top = top; 80 item.style.left = stickyLeft; 81 item.style.width = stickyWidth; 82 item.style.right = "auto"; 83 }); 84 return; 85 } 86 var bar = desktop.querySelector(".conf-nav__bar"); 87 if (!bar) { 88 return; 89 } 90 var barRect = bar.getBoundingClientRect(); 91 var desktopRect = desktop.getBoundingClientRect(); 92 var left = Math.round(barRect.left - desktopRect.left) + "px"; 93 var width = Math.round(barRect.width) + "px"; 94 panels.forEach(function (item) { 95 item.style.position = ""; 96 item.style.top = ""; 97 item.style.right = "auto"; 98 item.style.left = left; 99 item.style.width = width; 100 }); 101 } 102 103 function openDesktopPanel(index) { 104 var match = null; 105 desktop.querySelectorAll(".conf-nav__panel").forEach(function (item) { 106 var selected = item.getAttribute("data-conf-section") === String(index); 107 item.hidden = !selected; 108 if (selected) { 109 match = item; 110 } 111 }); 112 return match; 113 } 114 115 function selectCategory(section, index) { 116 if (!section) { 117 return; 118 } 119 var buttons = section.querySelectorAll("[data-conf-category]"); 120 buttons.forEach(function (button) { 121 var selected = button.getAttribute("data-conf-category") === String(index); 122 button.setAttribute("aria-pressed", selected ? "true" : "false"); 123 }); 124 section.querySelectorAll("[data-conf-pane]").forEach(function (pane) { 125 pane.hidden = pane.getAttribute("data-conf-pane") !== String(index); 126 }); 127 } 128 129 function desktopIsOpen() { 130 return !!(desktop && desktop.querySelector(".conf-nav__panel:not([hidden])")); 131 } 132 133 function closeDesktop(restoreFocus) { 134 if (!desktopIsOpen()) { 135 return; 136 } 137 var openButton = desktop.querySelector('[data-conf-menu][aria-expanded="true"]'); 138 desktop.querySelectorAll(".conf-nav__panel").forEach(function (item) { 139 item.hidden = true; 140 }); 141 desktop.querySelectorAll("[data-conf-menu]").forEach(function (button) { 142 button.setAttribute("aria-expanded", "false"); 143 }); 144 syncScrollLock(); 145 if (restoreFocus && openButton) { 146 openButton.focus(); 147 } 148 } 149 150 function openDesktop(index, category) { 151 if (!desktop) { 152 return; 153 }
154 var match = openDesktopPanel(index); 155 if (!match) { 156 return; 157 } 158 closeMobile(false); 159 desktop.querySelectorAll("[data-conf-menu]").forEach(function (button) { 160 button.setAttribute("aria-expanded", button.getAttribute("data-conf-menu") === String(index) ? "true" : "false"); 161 }); 162 if (category !== null && category !== undefined && category !== "") { 163 selectCategory(match, category); 164 } 165 placePanel(); 166 syncScrollLock(); 167 } 168 169 function collapseGroups(section) { 170 if (!section) { 171 return; 172 } 173 section.querySelectorAll("[data-conf-group]").forEach(function (button) { 174 button.setAttribute("aria-expanded", "false"); 175 var symbol = button.querySelector(".conf-m__symbol"); 176 if (symbol) { 177 symbol.textContent = "+"; 178 } 179 var groupPanel = document.getElementById(button.getAttribute("aria-controls")); 180 if (groupPanel) { 181 groupPanel.hidden = true; 182 } 183 }); 184 } 185 186 function openGroup(section, index) { 187 if (!section) { 188 return; 189 } 190 section.querySelectorAll("[data-conf-group]").forEach(function (button) { 191 var selected = button.getAttribute("data-conf-group") === String(index); 192 button.setAttribute("aria-expanded", selected ? "true" : "false"); 193 var symbol = button.querySelector(".conf-m__symbol"); 194 if (symbol) { 195 symbol.textContent = selected ? "\u2212" : "+"; 196 } 197 var groupPanel = document.getElementById(button.getAttribute("aria-controls")); 198 if (groupPanel) { 199 groupPanel.hidden = !selected; 200 } 201 }); 202 } 203 204 function showMobileRoot(focusIndex) { 205 if (mobileRoot) { 206 mobileRoot.hidden = false; 207 } 208 root.querySelectorAll("[data-conf-msection]").forEach(function (section) { 209 section.hidden = true; 210 }); 211 if (focusIndex !== null && focusIndex !== undefined) { 212 var button = root.querySelector('[data-conf-open="' + focusIndex + '"]'); 213 if (button) { 214 button.focus(); 215 } 216 } 217 } 218 219 function openMobileSection(index, category) { 220 var opened = root.querySelector('[data-conf-msection="' + index + '"]'); 221 if (!opened) { 222 return; 223 } 224 if (mobileRoot) { 225 mobileRoot.hidden = true; 226 } 227 root.querySelectorAll("[data-conf-msection]").forEach(function (section) { 228 section.hidden = section !== opened; 229 }); 230 if (category !== null && category !== undefined && category !== "") { 231 openGroup(opened, category); 232 } else { 233 openGroup(opened, 0); 234 } 235 var backs = opened.querySelectorAll("[data-conf-back]"); 236 for (var backIndex = 0; backIndex < backs.length; backIndex++) { 237 if (backs[backIndex].offsetParent !== null) { 238 backs[backIndex].focus(); 239 break; 240 } 241 } 242 } 243 244 function closeMobile(restoreFocus) { 245 if (!root.classList.contains("menu_active")) { 246 showMobileRoot(null); 247 return; 248 } 249 root.classList.remove("menu_active"); 250 if (burger) { 251 burger.classList.remove("menu_active"); 252 } 253 document.body.classList.remove("menu_active"); 254 showMobileRoot(null); 255 syncScrollLock(); 256 if (restoreFocus && burger) { 257 burger.focus(); 258 } 259 } 260 261 function openGoto(token) { 262 if (!token) { 263 return; 264 } 265 var parts = String(token).split(":"); 266 var section = parts[0]; 267 var category = parts.length > 1 ? parts[1] : null; 268 if (isDesktop()) { 269 openDesktop(section, category); 270 return; 271 } 272 openMobileSection(section, category); 273 } 274 275 root.addEventListener("click", function (event) { 276 var menuButton = event.target.closest("[data-conf-menu]"); 277 if (menuButton && desktop && desktop.contains(menuButton)) { 278 if (isDesktop()) { 279 cancelClose(); 280 openDesktop(menuButton.getAttribute("data-conf-menu"), null); 281 } 282 return; 283 } 284 285 var categoryButton = event.target.closest("[data-conf-category]"); 286 if (categoryButton) { 287 selectCategory(categoryButton.closest("[data-conf-section]"), categoryButton.getAttribute("data-conf-category")); 288 return; 289 } 290 291 var sectionButton = event.target.closest("[data-conf-open]"); 292 if (sectionButton) { 293 openMobileSection(sectionButton.getAttribute("data-conf-open"), null); 294 return; 295 } 296 297 var subButton = event.target.closest(".conf-m__sub"); 298 if (subButton) { 299 var subPanel = document.getElementById(subButton.getAttribute("aria-controls")); 300 var subOpen = subButton.getAttribute("aria-expanded") === "true"; 301 subButton.setAttribute("aria-expanded", subOpen ? "false" : "true"); 302 if (subPanel) { 303 subPanel.hidden = subOpen; 304 } 305 return; 306 } 307 308 var groupButton = event.target.closest("[data-conf-group]"); 309 if (groupButton) { 310 var section = groupButton.closest("[data-conf-msection]"); 311 var groupIndex = groupButton.getAttribute("data-conf-group"); 312 if (groupButton.getAttribute("aria-expanded") === "true") { 313 collapseGroups(section); 314 } else { 315 openGroup(section, groupIndex); 316 } 317 return; 318 } 319 320 var backButton = event.target.closest("[data-conf-back]"); 321 if (backButton) { 322 var current = backButton.closest("[data-conf-msection]"); 323 showMobileRoot(current ? current.getAttribute("data-conf-msection") : null); 324 return; 325 } 326 327 var jump = event.target.closest("[data-conf-goto]"); 328 if (jump && root.contains(jump)) { 329 event.preventDefault(); 330 openGoto(jump.getAttribute("data-conf-goto")); 331 return; 332 } 333 334 var placeholder = event.target.closest("a.is-placeholder"); 335 if (placeholder && root.contains(placeholder)) { 336 event.preventDefault(); 337 } 338 });
339 340 document.addEventListener("click", function (event) { 341 if (!desktopIsOpen()) { 342 return; 343 } 344 if (event.target.closest(".conf-nav__desktop")) { 345 return; 346 } 347 closeDesktop(false); 348 }); 349 350 document.addEventListener("keydown", function (event) { 351 if (event.key !== "Escape") { 352 return; 353 } 354 if (isDesktop() && desktopIsOpen()) { 355 closeDesktop(true); 356 return; 357 } 358 if (root.classList.contains("menu_active")) { 359 closeMobile(true); 360 } 361 }); 362 363 if (burger) { 364 burger.addEventListener("keydown", function (event) { 365 if (event.key === "Enter" || event.key === " ") { 366 event.preventDefault(); 367 burger.click(); 368 } 369 }); 370 } 371 372 var mobileWasOpen = root.classList.contains("menu_active"); 373 var classObserver = new MutationObserver(function () { 374 var mobileOpen = root.classList.contains("menu_active"); 375 if (mobileOpen && !mobileWasOpen) { 376 placeMobileMenu(); 377 showMobileRoot(null); 378 } 379 mobileWasOpen = mobileOpen; 380 syncScrollLock(); 381 }); 382 classObserver.observe(root, { attributes: true, attributeFilter: ["class"] }); 383 384 window.addEventListener("resize", function () { 385 if (root.classList.contains("menu_active")) { 386 placeMobileMenu(); 387 } 388 if (!isDesktop()) { 389 closeDesktop(false); 390 } else if (root.classList.contains("menu_active")) { 391 closeMobile(false); 392 } 393 placePanel(); 394 }); 395 396 window.addEventListener("scroll", function () { 397 if (root.classList.contains("menu_active")) { 398 placeMobileMenu(); 399 } 400 window.requestAnimationFrame(placePanel); 401 }, { passive: true }); 402 403 document.addEventListener("click", function (event) { 404 if (event.target.closest(".hamburger-icon")) { 405 placeMobileMenu(); 406 } 407 }, true); 408 409 if (desktop) { 410 desktop.addEventListener("mouseover", function (event) { 411 if (!isDesktop()) { 412 return; 413 } 414 var menuButton = event.target.closest("[data-conf-menu]"); 415 if (!menuButton || !desktop.contains(menuButton)) { 416 cancelClose(); 417 return; 418 } 419 cancelClose(); 420 var index = menuButton.getAttribute("data-conf-menu"); 421 if (menuButton.getAttribute("aria-expanded") === "true" && desktopIsOpen()) { 422 return; 423 } 424 openDesktop(index, null); 425 }); 426 desktop.addEventListener("mouseleave", function () { 427 if (isDesktop()) { 428 scheduleClose(); 429 } 430 }); 431 } 432 433 placePanel(); 434 syncScrollLock(); 435})();
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.