1// Desktop Dropdown Navigation 2document.addEventListener('DOMContentLoaded', function() { 3 const dropdownParents = document.querySelectorAll('.dropdown-parent'); 4 5 // Add hover events to each dropdown parent 6 dropdownParents.forEach(parent => { 7 const trigger = parent.querySelector('.dropdown-trigger'); 8 const menu = parent.querySelector('.dropdown-menu'); 9 const arrow = parent.querySelector('.dropdown-arrow'); 10 11 let hoverTimeout; 12 13 // Show dropdown on hover 14 parent.addEventListener('mouseenter', () => { 15 clearTimeout(hoverTimeout); 16 17 // Close other open dropdowns and remove their green underlines 18 dropdownParents.forEach(otherParent => { 19 if (otherParent !== parent) { 20 const otherMenu = otherParent.querySelector('.dropdown-menu'); 21 const otherArrow = otherParent.querySelector('.dropdown-arrow'); 22 const otherTrigger = otherParent.querySelector('.dropdown-trigger'); 23 otherMenu.classList.remove('opacity-100', 'visible', 'translate-y-0'); 24 otherMenu.classList.add('opacity-0', 'invisible', 'translate-y-2'); 25 otherArrow.classList.remove('rotate-180'); 26 otherTrigger.classList.remove('border-moss'); 27 otherTrigger.classList.add('border-transparent'); 28 } 29 }); 30 31 // Show current dropdown and add green underline 32 menu.classList.remove('opacity-0', 'invisible', 'translate-y-2'); 33 menu.classList.add('opacity-100', 'visible', 'translate-y-0'); 34 arrow.classList.add('rotate-180'); 35 trigger.classList.remove('border-transparent'); 36 trigger.classList.add('border-moss'); 37 }); 38 39 // Hide dropdown on leave (with delay) 40 parent.addEventListener('mouseleave', () => { 41 hoverTimeout = setTimeout(() => { 42 menu.classList.remove('opacity-100', 'visible', 'translate-y-0'); 43 menu.classList.add('opacity-0', 'invisible', 'translate-y-2'); 44 arrow.classList.remove('rotate-180'); 45 trigger.classList.remove('border-moss'); 46 trigger.classList.add('border-transparent'); 47 }, 150); // Small delay to prevent flickering 48 }); 49 50 // Prevent dropdown from closing when hovering over menu items 51 menu.addEventListener('mouseenter', () => { 52 clearTimeout(hoverTimeout); 53 }); 54 55 // Close dropdown when clicking outside 56 document.addEventListener('click', (e) => { 57 if (!parent.contains(e.target)) { 58 menu.classList.remove('opacity-100', 'visible', 'translate-y-0'); 59 menu.classList.add('opacity-0', 'invisible', 'translate-y-2'); 60 arrow.classList.remove('rotate-180'); 61 trigger.classList.remove('border-moss'); 62 trigger.classList.add('border-transparent'); 63 } 64 }); 65 66 // Close dropdown on escape key 67 document.addEventListener('keydown', (e) => { 68 if (e.key === 'Escape') { 69 menu.classList.remove('opacity-100', 'visible', 'translate-y-0'); 70 menu.classList.add('opacity-0', 'invisible', 'translate-y-2'); 71 arrow.classList.remove('rotate-180'); 72 trigger.classList.remove('border-moss'); 73 trigger.classList.add('border-transparent'); 74 } 75 }); 76 }); 77 78 // Close all dropdowns when scrolling 79 window.addEventListener('scroll', () => { 80 dropdownParents.forEach(parent => { 81 const menu = parent.querySelector('.dropdown-menu'); 82 const arrow = parent.querySelector('.dropdown-arrow'); 83 const trigger = parent.querySelector('.dropdown-trigger'); 84 menu.classList.remove('opacity-100', 'visible', 'translate-y-0'); 85 menu.classList.add('opacity-0', 'invisible', 'translate-y-2'); 86 arrow.classList.remove('rotate-180'); 87 trigger.classList.remove('border-moss'); 88 trigger.classList.add('border-transparent'); 89 }); 90 }); 91});
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.