1(function () { 2 'use strict'; 3 4 function toArray(list) { 5 return Array.prototype.slice.call(list || []); 6 } 7 8 function cleanPath(value) { 9 var path = value || '/'; 10 try { 11 path = new URL(path, window.location.href).pathname; 12 } catch (_) {} 13 path = path.replace(/\/(?:index)?\.(?:html?|php)$/i, '/').replace(/\.(?:html?|php)$/i, ''); 14 path = path.length > 1 ? path.replace(/\/$/, '') : path; 15 return decodeURIComponent(path || '/'); 16 } 17 18 function initHeader(root) { 19 if (!root || root.dataset.pdiHeaderReady === 'true') return; 20 root.dataset.pdiHeaderReady = 'true'; 21 22 var mobileToggle = root.querySelector('.pdi-nav__mobile-toggle'); 23 var nav = root.querySelector('#pdi-primary-navigation'); 24 var dropdownItems = toArray(root.querySelectorAll('.pdi-nav__item--dropdown')); 25 var toggles = toArray(root.querySelectorAll('.pdi-nav__toggle, .pdi-nav__branch-toggle')); 26 var media = window.matchMedia('(max-width: 1080px)'); 27 var submenuSequence = 0; 28 29 function isMobile() { 30 return media.matches; 31 } 32 33 function directSubmenu(item) { 34 if (!item) return null; 35 return item.querySelector(':scope > .pdi-nav__submenu'); 36 } 37 38 function directToggle(item) { 39 if (!item) return null; 40 return item.querySelector(':scope > .pdi-nav__toggle, :scope > .pdi-nav__branch-toggle, :scope > .pdi-nav__link-row > .pdi-nav__branch-toggle'); 41 } 42 43 dropdownItems.forEach(function (item) { 44 var toggle = directToggle(item); 45 var submenu = directSubmenu(item); 46 if (!toggle || !submenu) return; 47 if (!submenu.id) { 48 submenuSequence += 1; 49 submenu.id = 'pdi-submenu-' + submenuSequence; 50 } 51 toggle.setAttribute('aria-controls', submenu.id); 52 toggle.setAttribute('aria-haspopup', 'true'); 53 submenu.setAttribute('aria-hidden', 'true'); 54 }); 55 56 function setItemOpen(item, open, options) { 57 if (!item) return; 58 var toggle = directToggle(item); 59 var submenu = directSubmenu(item); 60 item.classList.toggle('is-open', open); 61 if (toggle) toggle.setAttribute('aria-expanded', open ? 'true' : 'false'); 62 if (submenu) submenu.setAttribute('aria-hidden', open ? 'false' : 'true'); 63 64 if (!open) { 65 toArray(item.querySelectorAll('.pdi-nav__item--dropdown.is-open')).forEach(function (child) { 66 if (child !== item) setItemOpen(child, false); 67 }); 68 } 69 70 if (open && options && options.focus) { 71 var focusable = toArray(submenu && submenu.querySelectorAll('a[href], button:not([disabled])')); 72 var target = options.focus === 'last' ? focusable[focusable.length - 1] : focusable[0]; 73 if (target) target.focus(); 74 } 75 } 76 77 function closeAll(except) { 78 dropdownItems.forEach(function (item) { 79 if (item !== except && (!except || !item.contains(except))) setItemOpen(item, false); 80 }); 81 } 82 83 function setMobileOpen(open, returnFocus) { 84 root.classList.toggle('is-mobile-open', open); 85 document.body.classList.toggle('pdi-nav-open', open && isMobile()); 86 if (mobileToggle) { 87 mobileToggle.setAttribute('aria-expanded', open ? 'true' : 'false'); 88 mobileToggle.setAttribute('aria-label', open ? 'Close navigation menu' : 'Open navigation menu'); 89 } 90 if (!open) { 91 closeAll(); 92 if (returnFocus && mobileToggle) mobileToggle.focus(); 93 } else if (nav) { 94 var first = nav.querySelector('a[href], button:not([disabled])'); 95 if (first) window.setTimeout(function () { first.focus(); }, 0); 96 } 97 } 98 99 /* Desktop flyouts open on hover/focus and close after a short grace period. 100 The delay prevents the menu from collapsing while the pointer moves from 101 the top-level trigger into its submenu. Click behavior remains available 102 for touch devices and keyboard users. */ 103 var hoverCloseDelay = 220; 104 105 function clearHoverTimer(item) { 106 if (!item || !item._pdiHoverTimer) return; 107 window.clearTimeout(item._pdiHoverTimer); 108 item._pdiHoverTimer = null; 109 } 110 111 function closeSiblingDropdowns(item) { 112 var siblings = item && item.parentElement ? item.parentElement.children : [];
113 toArray(siblings).forEach(function (sibling) { 114 if (sibling !== item && sibling.classList && sibling.classList.contains('pdi-nav__item--dropdown')) { 115 clearHoverTimer(sibling); 116 setItemOpen(sibling, false); 117 } 118 }); 119 } 120 121 dropdownItems.forEach(function (item) { 122 item.addEventListener('mouseenter', function () { 123 if (isMobile()) return; 124 clearHoverTimer(item); 125 closeSiblingDropdowns(item); 126 setItemOpen(item, true); 127 }); 128 129 item.addEventListener('mouseleave', function () { 130 if (isMobile()) return; 131 clearHoverTimer(item); 132 item._pdiHoverTimer = window.setTimeout(function () { 133 var active = document.activeElement; 134 if (!item.matches(':hover') && !(active && item.contains(active))) { 135 setItemOpen(item, false); 136 } 137 }, hoverCloseDelay); 138 }); 139 140 item.addEventListener('focusin', function () { 141 if (isMobile()) return; 142 clearHoverTimer(item); 143 closeSiblingDropdowns(item); 144 setItemOpen(item, true); 145 }); 146 147 item.addEventListener('focusout', function () { 148 if (isMobile()) return; 149 clearHoverTimer(item); 150 item._pdiHoverTimer = window.setTimeout(function () { 151 if (!item.contains(document.activeElement) && !item.matches(':hover')) { 152 setItemOpen(item, false); 153 } 154 }, hoverCloseDelay); 155 }); 156 }); 157 158 toggles.forEach(function (toggle) { 159 toggle.addEventListener('click', function (event) { 160 event.preventDefault(); 161 event.stopPropagation(); 162 var item = toggle.closest('.pdi-nav__item--dropdown'); 163 if (!item) return; 164 var shouldOpen = !item.classList.contains('is-open'); 165 var siblings = item.parentElement ? item.parentElement.children : []; 166 toArray(siblings).forEach(function (sibling) { 167 if (sibling !== item && sibling.classList && sibling.classList.contains('pdi-nav__item--dropdown')) { 168 setItemOpen(sibling, false); 169 } 170 }); 171 setItemOpen(item, shouldOpen); 172 }); 173 174 toggle.addEventListener('keydown', function (event) { 175 var item = toggle.closest('.pdi-nav__item--dropdown'); 176 if (!item) return; 177 if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { 178 event.preventDefault(); 179 setItemOpen(item, true, {focus: event.key === 'ArrowUp' ? 'last' : 'first'}); 180 } 181 }); 182 }); 183 184 if (mobileToggle) { 185 mobileToggle.addEventListener('click', function () { 186 setMobileOpen(!root.classList.contains('is-mobile-open'), false); 187 }); 188 } 189 190 root.addEventListener('keydown', function (event) { 191 var target = event.target; 192 var item = target && target.closest ? target.closest('.pdi-nav__item--dropdown') : null; 193 194 if (event.key === 'Escape') { 195 event.preventDefault(); 196 if (item && item.classList.contains('is-open')) { 197 var toggle = directToggle(item); 198 if (toggle) toggle.focus(); 199 // Focusin opens desktop menus; move focus before closing so Escape 200 // does not immediately reopen the branch. 201 setItemOpen(item, false); 202 return; 203 } 204 closeAll(); 205 if (root.classList.contains('is-mobile-open')) setMobileOpen(false, true); 206 return; 207 } 208 209 if (event.key === 'ArrowLeft' && item && !isMobile()) { 210 var parentItem = item.parentElement && item.parentElement.closest('.pdi-nav__item--dropdown'); 211 if (parentItem) { 212 event.preventDefault(); 213 var branchToggle = directToggle(item); 214 if (branchToggle) branchToggle.focus(); 215 setItemOpen(item, false); 216 } 217 } 218 }); 219 220 toArray(root.querySelectorAll('a[href]')).forEach(function (link) { 221 var linkPath; 222 try { 223 var url = new URL(link.href, window.location.href); 224 if (url.origin !== window.location.origin) return; 225 linkPath = cleanPath(url.pathname); 226 } catch (_) { 227 return; 228 } 229 if (linkPath === cleanPath(window.location.pathname)) { 230 link.setAttribute('aria-current', 'page'); 231 } 232 link.addEventListener('click', function () { 233 if (isMobile()) setMobileOpen(false, false); 234 }); 235 }); 236 237 document.addEventListener('click', function (event) { 238 if (!root.contains(event.target)) { 239 closeAll(); 240 if (isMobile()) setMobileOpen(false, false); 241 } 242 }); 243 244 function handleMediaChange() { 245 if (!isMobile()) setMobileOpen(false, false); 246 } 247 if (typeof media.addEventListener === 'function') media.addEventListener('change', handleMediaChange); 248 else if (typeof media.addListener === 'function') media.addListener(handleMediaChange); 249 } 250 251 function boot() { 252 initHeader(document.getElementById('pdi-common-header')); 253 } 254 255 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot, {once: true}); 256 else boot(); 257})();
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.