1document.addEventListener('DOMContentLoaded', function () { 2 const cartModal = document.getElementById('exampleModal2'); 3 const cartBackdrop = document.getElementById('cart-backdrop'); 4 if (cartModal && cartBackdrop) { 5 cartModal.addEventListener('show.bs.modal', function () { 6 cartBackdrop.classList.add('active'); 7 }); 8 cartModal.addEventListener('hide.bs.modal', function () { 9 cartBackdrop.classList.remove('active'); 10 }); 11 cartBackdrop.addEventListener('click', function () { 12 const instance = bootstrap.Modal.getInstance(cartModal); 13 if (instance) instance.hide(); 14 }); 15 } 16 17 let lastTrigger = null; 18 let openMenu = null; 19 20 function closeMenus() { 21 document.querySelectorAll('.mega-menu.show').forEach(function (m) { 22 m.classList.remove('show'); 23 }); 24 openMenu = null; 25 } 26 27 document.querySelectorAll('.top-category-url').forEach(function (toggle) { 28 toggle.addEventListener('click', function (event) { 29 lastTrigger = this; 30 const megaMenu = this.parentElement.querySelector('.mega-menu'); 31 const href = this.getAttribute('href'); 32 33 if (megaMenu) { 34 if (openMenu === megaMenu || window.getComputedStyle(megaMenu).visibility === 'visible') { 35 if (href && href !== '#') { 36 window.location.href = href; 37 } 38 } else { 39 event.preventDefault(); 40 closeMenus(); 41 megaMenu.classList.add('show'); 42 openMenu = megaMenu; 43 } 44 } 45 }); 46 47 toggle.addEventListener('keydown', function (e) { 48 if (e.key === 'Enter' || e.key === ' ') lastTrigger = this; 49 }); 50 51 document.addEventListener('click', function (event) { 52 if (!event.target.closest('.has-mega-menu')) { 53 closeMenus(); 54 } 55 }); 56 57 toggle.parentElement.addEventListener('mouseleave', function () { 58 openMenu = null; 59 }); 60 }); 61 62 // Escape closes menu and returns focus to trigger; Tab traps focus inside 63 function getFocusable(menu) { 64 return Array.from( 65 menu.querySelectorAll('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])') 66 ).filter(function (el) { return el.offsetParent !== null; }); 67 } 68 69 document.addEventListener('keydown', function (e) { 70 const menu = document.querySelector('.mega-menu.show'); 71 if (!menu) return; 72 73 if (e.key === 'Escape') { 74 closeMenus(); 75 if (lastTrigger) lastTrigger.focus(); 76 return; 77 } 78 79 if (e.key === 'Tab') { 80 const focusable = getFocusable(menu); 81 if (!focusable.length) return; 82 const first = focusable[0]; 83 const last = focusable[focusable.length - 1]; 84 if (e.shiftKey && document.activeElement === first) { 85 e.preventDefault(); 86 last.focus(); 87 } else if (!e.shiftKey && document.activeElement === last) { 88 e.preventDefault(); 89 first.focus(); 90 } 91 } 92 }); 93}); 94
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.