PageSourceSearch

https://wpamelia.com/wp-content/themes/amelia-theme/amelia-blocks/assets/js/main-header.js?ver=1773907555

js wpamelia.com collected 2026-10-02 02:29:05 UTC 8,828 bytes, 249 lines download raw bytes

1/**
2 * Amelia Main Header Widget JavaScript
3 * Handles mobile menu functionality and dropdown interactions
4 */
5
6(function() {
7    'use strict';
8
9    // Initialize when DOM is ready
10    document.addEventListener('DOMContentLoaded', function() {
11        initMainHeaderFunctionality();
12    });
13
14    // Also initialize immediately if DOM is already loaded
15    if (document.readyState === 'loading') {
16        document.addEventListener('DOMContentLoaded', initMainHeaderFunctionality);
17    } else {
18        initMainHeaderFunctionality();
19    }
20
21    // Also initialize for Elementor preview mode
22    if (typeof elementorFrontend !== 'undefined') {
23        document.addEventListener('elementor/frontend/init', function() {
24            elementorFrontend.hooks.addAction('frontend/element_ready/amelia-main-header.default', function($scope) {
25                initMainHeaderFunctionality($scope);
26            });
27        });
28    }
29
30    function initMainHeaderFunctionality(scope) {
31        let container;
32        
33        if (scope) {
34            // Handle jQuery objects from Elementor
35            if (scope.length !== undefined && scope[0]) {
36                container = scope[0];
37            } else if (scope.nodeType) {
38                // Handle DOM elements
39                container = scope;
40            } else {
41                container = document;
42            }
43        } else {
44            container = document;
45        }
46
47        if (!container || !container.querySelectorAll) {
48            container = document;
49        }
50
51        const headers = container.querySelectorAll('.amelia-main-header');
52
53        headers.forEach(function(header) {
54            initMobileMenu(header);
55            initDesktopDropdowns(header);
56        });
57    }
58
59    function initMobileMenu(header) {
60        const mobileToggle = header.querySelector('.mobile-menu-toggle');
61        // Look for mobile overlay globally since it's outside the header
62        const mobileOverlay = document.querySelector('.amelia-mobile-menu-overlay');
63        const mobileClose = mobileOverlay ? mobileOverlay.querySelector('.mobile-menu-close') : null;
64        const dropdownItems = mobileOverlay ? mobileOverlay.querySelectorAll('.mobile-menu-item.has-dropdown') : [];
65
66        // Check if already initialized
67        if (mobileToggle && mobileToggle.hasAttribute('data-initialized')) {
68            return;
69        }
70
71        if (!mobileToggle || !mobileOverlay) {
72            return;
73        }
74
75        // Mark as initialized
76        mobileToggle.setAttribute('data-initialized', 'true');
77
78        // Toggle mobile menu
79        mobileToggle.addEventListener('click', function(e) {
80            e.preventDefault();
81            toggleMobileMenu();
82        });
83
84        function toggleMobileMenu() {
85            const isActive = mobileToggle.classList.contains('active');
86            
87            if (isActive) {
88                closeMobileMenu();
89            } else {
90                mobileToggle.classList.add('active');
91                mobileOverlay.classList.add('active');
92                document.body.classList.add('mobile-menu-open');
93            }
94        }
95
96        // Close mobile menu
97        if (mobileClose) {
98            mobileClose.addEventListener('click', closeMobileMenu);
99        }
100
101        // Close on overlay click (outside content)
102        mobileOverlay.addEventListener('click', function(e) {
103            if (e.target === mobileOverlay) {
104                closeMobileMenu();
105            }
106        });
107
108        // Close on escape key
109        document.addEventListener('keydown', function(e) {
110            if (e.key === 'Escape' && mobileOverlay.classList.contains('active')) {
111                closeMobileMenu();
112            }
113        });
114
115        function closeMobileMenu() {
116            mobileToggle.classList.remove('active');
117            mobileOverlay.classList.remove('active');
118            document.body.classList.remove('mobile-menu-open');
119        }
120
121        // Close mobile menu on window resize to larger screens
122        let resizeTimeout;
123        window.addEventListener('resize', function() {
124            clearTimeout(resizeTimeout);
125            resizeTimeout = setTimeout(function() {
126                // Check if screen is now larger than mobile breakpoint (1024px)
127                if (window.innerWidth > 1024 && mobileOverlay.classList.contains('active')) {
128                    closeMobileMenu();
129                }
130            }, 150); // Debounce resize events
131        });
132
133        // Handle mobile dropdown toggles
134        dropdownItems.forEach(function(item) {
135            const toggleItem = item.querySelector('.mobile-menu-toggle-item');
136            
137            if (toggleItem) {
138                toggleItem.addEventListener('click', function() {
139                    // Close other dropdowns
140                    dropdownItems.forEach(function(otherItem) {
141                        if (otherItem !== item) {
142                            otherItem.classList.remove('expanded');
143                        }
144                    });
145
146                    // Toggle current dropdown
147                    item.classList.toggle('expanded');
148                });
149            }
150        });
151
152        // Handle mobile footer dropdown toggles
153        const mobileFooterItems = mobileOverlay ? mobileOverlay.querySelectorAll('.mobile-footer-item.has-dropdown') : [];
154        mobileFooterItems.forEach(function(footerItem) {
155            const toggleItem = footerItem.querySelector('.mobile-footer-toggle-item');
156            
157            if (toggleItem) {
158                toggleItem.addEventListener('click', function(e) {
159                    e.preventDefault();
160                    
161                    // Close other footer dropdowns
162                    mobileFooterItems.forEach(function(otherItem) {
163                        if (otherItem !== footerItem) {
164                            otherItem.classList.remove('expanded');
165                        }
166                    });
167
168                    // Toggle current footer dropdown
169                    footerItem.classList.toggle('expanded');
170                });
171            }
172        });
173
174        // Close mobile menu when clicking on menu links
175        const mobileLinks = header.querySelectorAll('.mobile-menu-link, .mobile-dropdown-items a');
176        mobileLinks.forEach(function(link) {
177            link.addEventListener('click', function() {
178                // Only close if it's not a hash link or if it's going to a different page
179                if (!link.getAttribute('href').startsWith('#') || link.getAttribute('href') === '#') {
180                    setTimeout(closeMobileMenu, 300);
181                }
182            });
183        });
184    }
185
186    function initDesktopDropdowns(header) {
187        const dropdownItems = header.querySelectorAll('.desktop-nav .has-dropdown');
188
189        dropdownItems.forEach(function(item) {
190            let hideTimeout;
191
192            // Show dropdown on mouse enter
193            item.addEventListener('mouseenter', function() {
194                clearTimeout(hideTimeout);
195                
196                // Hide other dropdowns
197                dropdownItems.forEach(function(otherItem) {
198                    if (otherItem !== item) {
199                        otherItem.classList.remove('dropdown-open');
200                    }
201                });
202
203                item.classList.add('dropdown-open');
204            });
205
206            // Hide dropdown on mouse leave
207            item.addEventListener('mouseleave', function() {
208                hideTimeout = setTimeout(function() {
209                    item.classList.remove('dropdown-open');
210                }, 100);
211            });
212
213            // Handle keyboard navigation
214            const link = item.querySelector('.main-menu-link');
215            if (link) {
216                link.addEventListener('keydown', function(e) {
217                    if (e.key === 'Enter' || e.key === ' ') {
218                        e.preventDefault();
219                        item.classList.toggle('dropdown-open');
220                    }
221                    if (e.key === 'Escape') {
222                        item.classList.remove('dropdown-open');
223                    }
224                });
225            }
226        });
227
228        // Close dropdowns when clicking outside
229        document.addEventListener('click', function(e) {
230            if (!header.contains(e.target)) {
231                dropdownItems.forEach(function(item) {
232                    item.classList.remove('dropdown-open');
233                });
234            }
235        });
236    }
237
238    // Prevent body scroll when mobile menu is open
239    const style = document.createElement('style');
240    style.textContent = `
241        body.mobile-menu-open {
242            overflow: hidden;
243            position: fixed;
244            width: 100%;
245        }
246    `;
247    document.head.appendChild(style);
248
249})();

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.