1(function () { 2 3 var desktop = document.getElementById('flyoutnavDesktop'); 4 var track = document.getElementById('flyoutnavTrack'); 5 6 if (!desktop || !track) return; 7 8 var activeTab = null; 9 var stack = []; 10 11 function childrenLis(ul) { 12 return Array.from(ul.children).filter(function (n) { return n.tagName === 'LI'; }); 13 } 14 function titleOf(li) { 15 var a = li.querySelector(':scope > a'); 16 return a ? a.textContent.trim() : ''; 17 } 18 function hrefOf(li) { 19 var a = li.querySelector(':scope > a'); 20 return a ? (a.getAttribute('href') || '#') : '#'; 21 } 22 function childUL(li) { 23 return li.querySelector(':scope > ul'); 24 } 25 26 function makePanel(ul) { 27 var entries = []; 28 childrenLis(ul).forEach(function (li) { 29 var sub = childUL(li); 30 entries.push({ 31 title: titleOf(li), 32 href: hrefOf(li), 33 childUL: sub 34 }); 35 }); 36 return entries; 37 } 38 //helpers to ensure active tab is greyed out when its menu is open 39 function markActiveTab(tabLi) { 40 // Remove from any previous tab 41 document 42 .querySelectorAll('.flyoutnav-tab > a.nav-link.flyoutnav-active') 43 .forEach(a => a.classList.remove('flyoutnav-active')); 44 45 if (!tabLi) return; 46 47 var link = tabLi.querySelector(':scope > a.nav-link'); 48 if (link) { 49 link.classList.add('flyoutnav-active'); 50 } 51 } 52 53 function clearActiveTab() { 54 document 55 .querySelectorAll('.flyoutnav-tab > a.nav-link.flyoutnav-active') 56 .forEach(a => a.classList.remove('flyoutnav-active')); 57 } 58 59 60 function renderAll() { 61 track.innerHTML = ''; 62 63 stack.forEach(function (panelEntries, idx) { 64 var col = document.createElement('div'); 65 col.className = 'flyoutnav-panel'; 66 67 var list = document.createElement('ul'); 68 list.className = 'flyoutnav-list'; 69 70 panelEntries.forEach(function (item) { 71 var li = document.createElement('li'); 72 73 if (item.childUL) { 74 // Parent: clickable but DOES NOT navigate 75 var row = document.createElement('button'); 76 row.type = 'button'; 77 row.className = 'flyoutnav-row has-children'; 78 row.innerHTML = '<span>' + item.title + '</span><span class="flyoutnav-chev">âº</span>'; 79 80 row.addEventListener('click', function (e) { 81 e.preventDefault(); 82 // trim stack to this column, then add next 83 stack.splice(idx + 1); 84 stack.push(makePanel(item.childUL)); 85 renderAll(); 86 }); 87 88 li.appendChild(row); 89 } else { 90 // Leaf: normal navigation 91 var a = document.createElement('a'); 92 a.className = 'flyoutnav-row'; 93 a.href = item.href || '#'; 94 a.textContent = item.title; 95 li.appendChild(a); 96 } 97 98 list.appendChild(li); 99 }); 100 101 col.appendChild(list); 102 track.appendChild(col); 103 }); 104 } 105 106 function openForTab(tabLi) { 107 activeTab = tabLi; 108 109 var source = tabLi.querySelector(':scope > ul.flyoutnav-source'); 110 if (!source) { 111 closeFlyout(); 112 return; 113 } 114 115 stack = [ makePanel(source) ]; 116 renderAll(); 117 118 desktop.classList.add('active'); 119 desktop.setAttribute('aria-hidden', 'false'); 120 121 markActiveTab(tabLi); 122 123 // Position under the navbar 124 var rect = tabLi.getBoundingClientRect(); 125 desktop.style.left = '0px'; 126 desktop.style.top = (tabLi.offsetTop + tabLi.offsetHeight) + 'px'; 127 } 128 129 function closeFlyout() { 130 activeTab = null; 131 stack = []; 132 track.innerHTML = ''; 133 desktop.classList.remove('active'); 134 desktop.setAttribute('aria-hidden', 'true'); 135 136 clearActiveTab(); 137 } 138 139 // Hover behavior on top-level tabs 140 document.querySelectorAll('.flyoutnav-tab').forEach(function (tabLi) { 141 tabLi.addEventListener('mouseenter', function () { 142 openForTab(tabLi); 143 }); 144 }); 145 146 // Keep open when mouse is over flyout 147 desktop.addEventListener('mouseenter', function () { 148 // do nothing 149 }); 150 151 // Close when leaving both tab area + flyout 152 desktop.addEventListener('mouseleave', closeFlyout); 153 154 // Close if user leaves nav entirely 155 var nav = document.querySelector('.primary-navigation'); 156 nav && nav.addEventListener('mouseleave', function () { 157 // small delay helps cursor move from tab into panel 158 setTimeout(function () { 159 if (!desktop.matches(':hover') && !(activeTab && activeTab.matches(':hover'))) { 160 closeFlyout(); 161 } 162 }, 150); 163 }); 164 const flyout = document.getElementById('flyoutnavDesktop'); 165 if (!flyout) return; 166 167 // Move flyout OUT of header/container for a full width dropdown menu 168 document.body.appendChild(flyout); 169 170})();
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.