1/** 2 * Vanilla JS interactions for TNEW pages. 3 * Since Vue doesn't hydrate on these pages (noScripts: true), 4 * we need plain JS for header/footer interactions. 5 */ 6(function () { 7 // Get base URL from data attribute on script tag 8 var scriptTag = document.currentScript; 9 var baseUrl = scriptTag ? scriptTag.getAttribute('data-base-url') || '' : ''; 10 11 const handleRedirects = () => { 12 if (typeof window === 'undefined') return; 13 const redirects = { 14 '/': '/cart/details', 15 '/events': '/cart/details', 16 '/events/': '/cart/details', 17 }; 18 const { pathname, host } = window.location; 19 const hosts = ['mycart.chicagohumanities.org', 'staging-cart.chicagohumanities.org']; 20 if (hosts.includes(host)) { 21 if (redirects[pathname]) { 22 window.location.replace(window.location.origin + redirects[pathname]); 23 } 24 } 25 }; 26 27 function initMobileMenu() { 28 var toggle = document.querySelector('.mobile-toggle'); 29 var header = document.querySelector('.global-header'); 30 if (!toggle || !header) return; 31 32 toggle.addEventListener('click', function () { 33 var isOpen = header.classList.toggle('active'); 34 toggle.setAttribute('aria-expanded', String(isOpen)); 35 if (isOpen) { 36 document.documentElement.classList.add('showing-modal'); 37 } else { 38 document.documentElement.classList.remove('showing-modal'); 39 } 40 }); 41 } 42 43 function initDesktopSubnav() { 44 var navLinks = document.querySelectorAll('.nav-desktop .nav-link'); 45 navLinks.forEach(function (navLink) { 46 var subnav = navLink.querySelector('.subnav-drop-down'); 47 var trigger = navLink.querySelector('.show-links-trigger'); 48 if (!subnav) return; 49 50 navLink.addEventListener('mouseenter', function () { 51 navLink.classList.add('subnav-visible'); 52 subnav.style.display = 'block'; 53 }); 54 navLink.addEventListener('mouseleave', function () { 55 navLink.classList.remove('subnav-visible'); 56 subnav.style.display = 'none'; 57 }); 58 59 if (trigger) { 60 trigger.addEventListener('click', function (e) { 61 e.preventDefault(); 62 e.stopPropagation(); 63 var isVisible = navLink.classList.toggle('subnav-visible'); 64 subnav.style.display = isVisible ? 'block' : 'none'; 65 }); 66 } 67 68 subnav.addEventListener('click', function () { 69 navLink.classList.remove('subnav-visible'); 70 subnav.style.display = 'none'; 71 }); 72 }); 73 } 74 75 function initSearchToggle() { 76 // On TNEW pages, redirect search icon clicks to main site search 77 var searchButtons = document.querySelectorAll('.icon.search'); 78 searchButtons.forEach(function (btn) { 79 btn.addEventListener('click', function (e) { 80 e.preventDefault(); 81 window.location.href = baseUrl + '/search'; 82 }); 83 }); 84 } 85 86 function initMobileSubnav() { 87 // Handle mobile menu subnav toggles 88 var menuItems = document.querySelectorAll('.mobile-menu-item'); 89 menuItems.forEach(function (menuItem) { 90 var button = menuItem.querySelector('button.item-link'); 91 if (!button) return; 92 93 button.addEventListener('click', function (e) { 94 e.preventDefault(); 95 var isOpen = menuItem.classList.toggle('open'); 96 button.setAttribute('aria-expanded', String(isOpen)); 97 98 // Update expand/collapse indicator (last span, not the sr-only one) 99 var spans = button.querySelectorAll('span'); 100 var indicator = spans[spans.length - 1]; 101 if (indicator) { 102 indicator.className = isOpen ? 'collapse' : 'expand'; 103 } 104 }); 105 }); 106 } 107 108 function markEmptyImageItems() { 109 document.querySelectorAll('.tn-prod-list-item__property--img-container') 110 .forEach(function (el) { 111 if (!el.children.length) { 112 var item = el.closest('.tn-prod-list-item'); 113 if (item) item.classList.add('no-image'); 114 } 115 }); 116 } 117
118 function init() { 119 handleRedirects(); 120 initMobileMenu(); 121 initMobileSubnav(); 122 initDesktopSubnav(); 123 initSearchToggle(); 124 markEmptyImageItems(); 125 } 126 127 if (document.readyState === 'loading') { 128 document.addEventListener('DOMContentLoaded', init); 129 } else { 130 init(); 131 } 132})();
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.