PageSourceSearch

https://www.chicagohumanities.org/tnew/interactions.js

js chicagohumanities.org collected 2026-09-24 17:38:49 UTC 4,846 bytes, 132 lines download raw bytes

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.