1jQuery(function ($) { 2 console.log('Main.js loaded (jQuery version)'); // Log: Script loaded 3 4 /* -------------------------------------------------- 5 * Link Target Management 6 * Internal links open in same tab, external in new tab. 7 * -------------------------------------------------- */ 8 function manageLinkTargets() { 9 var currentHost = window.location.hostname; 10 11 $('a[href]').each(function () { 12 var $link = $(this); 13 var href = $link.attr('href'); 14 15 // Skip non-navigational links (anchors, mailto, tel, javascript, empty) 16 if (!href || href.charAt(0) === '#' || href.indexOf('mailto:') === 0 || href.indexOf('tel:') === 0 || href.indexOf('javascript:') === 0) { 17 return; 18 } 19 20 try { 21 var linkUrl = new URL(href, window.location.origin); 22 23 if (linkUrl.hostname === currentHost) { 24 // Internal link â same tab 25 $link.removeAttr('target'); 26 } else { 27 // External link â new tab with security attrs 28 $link.attr('target', '_blank'); 29 var rel = ($link.attr('rel') || '').split(/\s+/).filter(Boolean); 30 if (rel.indexOf('noopener') === -1) { rel.push('noopener'); } 31 if (rel.indexOf('noreferrer') === -1) { rel.push('noreferrer'); } 32 $link.attr('rel', rel.join(' ')); 33 } 34 } catch (e) { 35 // Malformed URL â treat as internal, leave it alone 36 } 37 }); 38 } 39 40 // Run on page load 41 manageLinkTargets(); 42 43 // Re-run when new content is injected (e.g. AJAX, infinite scroll) 44 $(document).ajaxComplete(function () { 45 manageLinkTargets(); 46 }); 47 48 /* -------------------------------------------------- 49 * Desktop Search Toggle 50 * -------------------------------------------------- */ 51 var $desktopSearchButton = $('#desktop-search-button'); 52 var $desktopSearchFormContainer = $('#desktop-search-form-container'); 53 54 $desktopSearchButton.on('click', function (e) { 55 e.preventDefault(); 56 $desktopSearchFormContainer.toggleClass('hidden'); 57 58 var desktopVisible = !$desktopSearchFormContainer.hasClass('hidden'); 59 console.log('Desktop search toggled. Visible:', desktopVisible); 60 61 if (desktopVisible) { 62 $desktopSearchFormContainer.find('input[type="search"]').first().focus(); 63 } 64 }); 65 66 /* -------------------------------------------------- 67 * Mobile Search Toggle 68 * -------------------------------------------------- */ 69 var $mobileSearchButton = $('#mobile-search-button'); 70 var $mobileSearchFormContainer = $('#mobile-search-form-container'); 71 72 $mobileSearchButton.on('click', function (e) { 73 e.preventDefault(); 74 $mobileSearchFormContainer.toggleClass('hidden'); 75 76 var mobileSearchVisible = !$mobileSearchFormContainer.hasClass('hidden'); 77 console.log('Mobile search toggled. Visible:', mobileSearchVisible); 78 79 if (mobileSearchVisible) { 80 $mobileSearchFormContainer.find('input[type="search"]').first().focus(); 81 } 82 }); 83 84 /* -------------------------------------------------- 85 * Mobile Menu Drilldown Logic 86 * -------------------------------------------------- */ 87 const $navContainer = $('#site-navigation'); 88 const $mobileMenuButton = $('#mobile-menu-toggle-button'); 89 90 // In our markup wp_nav_menu outputs the UL directly inside #site-navigation (no wrapper DIV) 91 const $rootUl = $navContainer.children('ul'); 92 93 // Utility: Update container height to match current menu 94 function updateNavHeight() { 95 const $activeMenu = $navContainer.children('ul.is-active').first(); 96 if ($activeMenu.length) { 97 $navContainer.height($activeMenu.outerHeight()); 98 } 99 } 100 101 // Bail if we didn't find a root <ul> 102 if (!$rootUl.length) { 103 return; 104 } 105 106 // --- 1. Initial Setup: Augment the menu markup ---
107 $rootUl.addClass('is-active').attr('data-level', 0); 108 109 $navContainer.find('.menu-item-has-children').each(function() { 110 const $parentLi = $(this); 111 const $parentLink = $parentLi.children('a'); 112 const $subMenu = $parentLi.children('.sub-menu'); 113 114 // Add a forward caret to the parent link 115 $parentLink.append('<span class="forward-caret" aria-hidden="true">âº</span>'); 116 117 // Add a back button to the submenu 118 const backButtonText = $parentLink.clone().children().remove().end().text(); // Get text without child spans 119 const backButton = $('<li class="menu-back-button"><a href="#" role="button">' + backButtonText + '</a></li>'); 120 $subMenu.prepend(backButton); 121 $subMenu.data('lwosParentLi', $parentLi); // store reference for back action 122 }); 123 124 125 // --- 2. Click Handlers --- 126 127 // Open/Close the main navigation container 128 $mobileMenuButton.on('click', function(e) { 129 e.preventDefault(); 130 131 $navContainer.toggleClass('hidden'); 132 const isVisible = !$navContainer.hasClass('hidden'); 133 $(this).attr('aria-expanded', isVisible.toString()); 134 135 if (isVisible) { 136 // Ensure height fits the root menu when opening 137 updateNavHeight(); 138 } else { 139 // Reset the menu state when closing 140 setTimeout(function() { 141 $navContainer.find('.is-hidden-left').removeClass('is-hidden-left'); 142 $navContainer.find('.sub-menu.is-active').removeClass('is-active'); 143 $rootUl.addClass('is-active'); 144 // Clear the explicit height so it can collapse 145 $navContainer.height(''); 146 }, 300); 147 } 148 }); 149 150 // Handle clicking a link that opens a submenu 151 $navContainer.on('click', '.menu-item-has-children > a', function(e) { 152 if ($(e.target).closest('.menu-back-button').length) { 153 return; 154 } 155 e.preventDefault(); 156 157 const $parentLi = $(this).parent('li'); 158 const $currentMenu = $parentLi.parent('ul'); 159 const $nextMenu = $parentLi.children('.sub-menu'); 160 161 // Before showing the next submenu, move any other submenus (previously appended) back to their original <li> 162 $navContainer.children('ul.sub-menu').not($currentMenu).not($nextMenu).each(function(){ 163 const $sm = $(this); 164 const $smParentLi = $sm.data('lwosParentLi'); 165 if ($smParentLi && $smParentLi.length) { 166 $sm.detach().appendTo($smParentLi); 167 $sm.removeClass('is-active is-hidden-left'); 168 } 169 }); 170 171 // Remove active state from any other menu before transitioning 172 $navContainer.find('ul.is-active').not($currentMenu).not($nextMenu).removeClass('is-active'); 173 174 // Move the submenu we are opening to be a direct child of navContainer so it's not affected by parent transforms 175 $nextMenu.appendTo($navContainer); 176 177 // Hide the current menu and activate the next 178 $currentMenu.addClass('is-hidden-left').removeClass('is-active'); 179 $nextMenu.addClass('is-active'); 180 181 // Adjust height for the newly active submenu 182 updateNavHeight(); 183 }); 184 185 // Handle clicking the back button 186 $navContainer.on('click', '.menu-back-button > a', function(e) { 187 e.preventDefault(); 188 189 const $currentMenu = $(this).closest('.sub-menu'); 190 const $parentLi = $currentMenu.data('lwosParentLi'); 191 192 if (!$parentLi || !$parentLi.length) { 193 return; // safety guard 194 } 195 196 const $parentMenu = $parentLi.parent('ul'); 197 198 // Move submenu back under its parent <li> 199 $currentMenu.detach().appendTo($parentLi); 200 201 // Restore class states 202 $currentMenu.removeClass('is-active'); 203 $parentMenu.removeClass('is-hidden-left').addClass('is-active'); 204 205 // Adjust height for the parent menu 206 updateNavHeight(); 207 }); 208});
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.