1document.addEventListener("DOMContentLoaded", function() { 2 document.addEventListener("keydown", function(e) { 3 if (e.code == "Space" || e.code == "Enter") { 4 document.activeElement.click(); 5 } 6 }); 7 8 // Mobile Nav 9 const hamburger = document.querySelector(".hamburger"); 10 const navMenu = document.getElementById("main-nav"); 11 12 hamburger.addEventListener("click", mobileMenu); 13 14 function mobileMenu() { 15 hamburger.classList.toggle("active"); 16 navMenu.classList.toggle("active"); 17 } 18 19 // Search bar functionality 20 const search = document.getElementById("nav-search"); 21 const mobileSearch = document.getElementById("mobile-nav-search"); 22 const searchButton = document.querySelector(".wp-block-search__button"); 23 const mobileSearchButton = document.querySelector(".mobile-search .wp-block-search__button"); // Adjust this selector if needed 24 25 function toggleSearchBar(input) { 26 if (input.classList.contains("active")) { 27 input.classList.remove("active"); 28 } else { 29 input.classList.add("active"); 30 input.focus(); // Focus on the input field when it becomes visible 31 } 32 } 33 34 function handleButtonClick(event, input) { 35 // Check if the input is already active 36 if (!input.classList.contains("active")) { 37 event.preventDefault(); // Prevent form submission 38 toggleSearchBar(input); 39 } else { 40 // Allow form submission if input is active and not empty 41 if (!input.value.trim()) { 42 event.preventDefault(); // Prevent submission if the search field is empty 43 input.focus(); 44 } 45 } 46 } 47 48 // Event listeners for button clicks 49 if (searchButton) { 50 searchButton.addEventListener("click", function(event) { 51 handleButtonClick(event, search); 52 }); 53 } 54 55 if (mobileSearchButton) { 56 mobileSearchButton.addEventListener("click", function(event) { 57 handleButtonClick(event, mobileSearch); 58 }); 59 } 60 61 // Close search bar on click outside if input is empty 62 document.addEventListener("click", function(event) { 63 if (!search.contains(event.target) && !searchButton.contains(event.target) && !search.value) { 64 search.classList.remove("active"); 65 } 66 if (mobileSearch && !mobileSearch.contains(event.target) && !mobileSearchButton.contains(event.target) && !mobileSearch.value) { 67 mobileSearch.classList.remove("active"); 68 } 69 }); 70 71 // Keep nested submenus from overflowing 72 function checkAndRepositionSubMenu() { 73 const nestedSubMenus = document.querySelectorAll('.sub-menu .sub-menu'); 74 75 nestedSubMenus.forEach(nestedSubMenu => { 76 const subMenuRect = nestedSubMenu.getBoundingClientRect(); 77 78 // Check if the submenu overflows the right side of the window 79 if (subMenuRect.right > window.innerWidth) { 80 nestedSubMenu.style.left = 0; 81 nestedSubMenu.style.transform = 'translateX(calc(-100% - 14px))'; 82 } 83 }); 84 } 85 function attachSubMenuCheckOnHover() { 86 const mainMenuItems = document.querySelectorAll('.sub-menu .menu-item-has-children'); 87 88 mainMenuItems.forEach(mainMenuItem => { 89 mainMenuItem.addEventListener('mouseover', checkAndRepositionSubMenu); 90 }); 91 } 92 attachSubMenuCheckOnHover(); 93 94 95 // Add .masonry-gallery class to blocks with class added from Gutenberg 96 let allIsStyleMasonryGalleries = document.querySelectorAll('.is-style-masonry-gallery'); 97 if (allIsStyleMasonryGalleries) { 98 allIsStyleMasonryGalleries.forEach(isStyleMasonryGallery => { 99 isStyleMasonryGallery.classList.add('masonry-gallery'); 100 }) 101 } 102 103 //Masonry Galleries 104 let galleryContainers = document.querySelectorAll('.masonry-gallery'); 105 let masonryGallery; 106 107 if (galleryContainers) { 108 galleryContainers.forEach(galleryContainer => { 109 imagesLoaded( galleryContainer, function() { 110 masonryGallery = new Masonry( galleryContainer, { 111 itemSelector: '.wp-block-image', 112 columnWidth: '.wp-block-image', 113 gutter: 0, 114 percentPosition: true, 115 horizontalOrder: false 116 }); 117 }); 118 }); 119 } 120 121 // Add .masonry-cards class to blocks with class added from Gutenberg 122 let allIsStyleMasonryCards = document.querySelectorAll('.is-style-masonry-cards'); 123 if (allIsStyleMasonryCards) { 124 allIsStyleMasonryCards.forEach(isStyleMasonryCards => { 125 isStyleMasonryCards.classList.add('masonry-cards'); 126 }) 127 } 128 129 //Masonry Galleries 130 let masonryCardsContainers = document.querySelectorAll('.masonry-cards'); 131 let masonryCards; 132
133 if (masonryCardsContainers) { 134 masonryCardsContainers.forEach(masonryCardsContainer => { 135 imagesLoaded( masonryCardsContainer, function() { 136 masonryCards = new Masonry( masonryCardsContainer, { 137 itemSelector: '.card', 138 columnWidth: '.card', 139 gutter: 0, 140 percentPosition: true, 141 horizontalOrder: false 142 }); 143 }); 144 }); 145 } 146 147 148 // Make sure blockquote border color is the same as text 149 const blockquotes = document.querySelectorAll('.wp-block-quote:not(.is-style-plain)'); 150 151 for (let i = 0; i < blockquotes.length; i++) { 152 153 let quoteText = blockquotes[i].querySelector("p"); 154 let quoteTextStyle = window.getComputedStyle(quoteText); 155 let quoteTextColor = quoteTextStyle.getPropertyValue("color"); 156 blockquotes[i].style.borderLeftColor = quoteTextColor; 157 } 158 159 // Allow nested ordered lists 160 function convertNestedULtoOL(element) { 161 // Convert the current <ul> element to <ol> 162 const ol = document.createElement('ol'); 163 while (element.firstChild) ol.appendChild(element.firstChild); 164 165 // Ensure element has a parent node before attempting to replace it 166 if (element.parentNode) { 167 element.parentNode.replaceChild(ol, element); 168 } 169 170 // Search for any further nested <ul>s within the new <ol>
171 Array.from(ol.querySelectorAll('ul')).forEach(ul => { 172 convertNestedULtoOL(ul); // Recursively convert any nested <ul> elements 173 }); 174 } 175 176 const orderedLists = document.querySelectorAll('article ol ul'); 177 178 if (orderedLists.length > 0) { 179 orderedLists.forEach(ul => convertNestedULtoOL(ul)); 180 } 181 182 // Heading tags for details blocks 183 184 function applyHeadingTagsForDetails() { 185 // Loop through heading levels from 2 to 6 186 for (let level = 2; level <= 6; level++) { 187 const headingClass = `details.is-style-h${level}-summary`; 188 const detailsElements = document.querySelectorAll(headingClass); 189 190 detailsElements.forEach(detailsElement => { 191 const summary = detailsElement.querySelector("summary"); 192 if (summary) { 193 const summaryContent = summary.innerHTML; 194 summary.innerHTML = `<h${level}>${summaryContent}</h${level}>`; 195 } 196 }); 197 } 198 } 199 200 applyHeadingTagsForDetails(); 201 202 203 204 205 206 // SLIDE IN ANIMATION TRIGGERS 207 function isInViewport(element) { 208 const rect = element.getBoundingClientRect(); 209 return ( 210 rect.top >= 0 && 211 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) 212 ); 213 } 214 215 function isInViewportTop(element) { 216 const rect = element.getBoundingClientRect(); 217 return ( 218 rect.top <= (window.innerHeight || document.documentElement.clientHeight) 219 ); 220 } 221 222 const progressBars = document.querySelectorAll('.progress-bar'); 223 224 progressBars.forEach((progressBar) => { 225 addEventListener("scroll", (event) => { 226 227 if (isInViewportTop(progressBar)) { 228 progressBar.classList.add("visible"); 229 } 230 }); 231 }); 232 233 })
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.