1const createCSS = (query) => { 2 let css = ""; 3 query 4 .trim() 5 .split(" ") 6 .filter((part) => part.length > 0) 7 .reverse() 8 .slice(0, 3) 9 .forEach((word) => { 10 css += ` 11 [data-category*="${word}"], 12 [data-subcategory*="${word}"], 13 [data-title*="${word}"] { 14 display: flex!important; 15 } 16 [data-category*="${word}"] ~ .no-results, 17 [data-subcategory*="${word}"] ~ .no-results, 18 [data-title*="${word}"] ~ .no-results{ 19 display: none!important; 20 } 21 .no-results span::before{ 22 content: "${searchField.value}"; 23 } 24 `; 25 }); 26 27 return css; 28}; 29 30const focusFirst = (el) => { 31 el.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')[0]?.focus(); 32} 33 34const scrollToWithOffset = (el, callback, offset = -180) => { 35 36 const target = el.getBoundingClientRect().top + window.pageYOffset + offset; 37 const step = (x) => x / 50 < 0.5 ? 1 - Math.pow(-2 * x / 50 + 2, 3) / 2 : 4 * x / 50 * x / 50 * x / 50; 38 let i = 0; 39 40 const interval = setInterval(( 41 ) => { 42 i++; 43 if (window.pageYOffset + step(i) < target) { 44 window.scroll( 45 0, window.pageYOffset + step(i) 46 ); 47 } else { 48 clearInterval(interval) 49 callback && callback(); 50 } 51 }, 10) 52 53}; 54 55// search 56 57const searchWrap = document.querySelector(".help-desk__search-wrap"); 58const searchField = document.querySelector(".help-desk__search-field"); 59const searchResults = document.querySelector(".help-desk__search-wrap ul"); 60const styleTag = document.head.appendChild(document.createElement("style")); 61 62const clearSearchBtn = document.querySelector(".help-desk__search-clear"); 63 64const states = ["focus", "hasquery", "hasresults", "noresults"]; 65 66const updateState = () => { 67 searchWrap.classList[searchField.value == "" ? "remove" : "add"]( 68 "help-desk__search-wrap--hasquery" 69 ); 70}; 71 72searchField.addEventListener("input", () => { 73 styleTag.innerHTML = createCSS(searchField.value.trim()); 74 updateState(); 75}); 76 77const clearSearch = () => { 78 searchField.value = ""; 79 searchField.dispatchEvent(new Event("input")); 80 searchField.focus(); 81}; 82 83const handleSearchKeyDown = (e) => { 84 if (e.key === 'ArrowDown') { 85 e.preventDefault(); 86 searchResults.firstElementChild.firstElementChild?.focus(); 87 } 88}; 89 90const handleOptionKeyDown = (e) => { 91 if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { 92 e.preventDefault(); 93 94 const nextElementToFocus = (e.target).parentElement[ 95 `${e.key === 'ArrowDown' ? 'next' : 'previous'}ElementSibling` 96 ]?.firstElementChild; 97 98 if (nextElementToFocus && nextElementToFocus.clientHeight > 10) { 99 nextElementToFocus.focus(); 100 } else { 101 searchField.focus(); 102 } 103 } 104}; 105 106searchField.addEventListener("keydown", handleSearchKeyDown); 107searchResults.querySelectorAll("li a").forEach((el) => { 108 el.addEventListener("keydown", handleOptionKeyDown); 109}); 110 111clearSearchBtn.addEventListener("click", clearSearch); 112 113// anchors 114 115const accordionAnchors = document.querySelectorAll( 116 ".help-desk__search-wrap a:not([target='_blank'])" 117); 118const anchorBlocks = document.querySelectorAll(".help-desk__category-anchor"); 119 120[...anchorBlocks, ...accordionAnchors].forEach((anchorBlock) => { 121 anchorBlock.addEventListener("click", (e) => { 122 e.preventDefault(); 123 const el = e.target.closest("a"); 124 const isBlockAnchor = el?.classList.contains("help-desk__category-anchor"); 125 126 if (!isBlockAnchor) { 127 clearSearch(); 128 document.querySelectorAll(".details[open]").forEach(detail => detail.removeAttribute("open")) 129 } 130 const target = document.getElementById(el.getAttribute("href").slice(1)); 131 scrollToWithOffset(target, () => { 132 focusFirst(target) 133 const firstButton = target.querySelector("button"); 134 const isOpen = firstButton?.parentElement?.getAttribute("open") !== null; 135 !isOpen && firstButton?.click(); 136 } 137 ); 138 }) 139}); 140 141// modal 142 143const modal = document.createElement("dialog"); 144 145const openModal = () => { 146 modal.setAttribute("open", ""); 147 document.querySelector("html").style = "overflow:hidden"; 148 const firstInput = modal.querySelector("select, input:not([type='hidden'])"); 149 firstInput?.focus(); 150}; 151 152const closeModal = () => { 153 document.querySelector("html").style = "overflow:auto"; 154 modal.removeAttribute("open"); 155}; 156 157document.addEventListener("DOMContentLoaded", () => { 158 const openBtns = document.querySelectorAll(".js-open-modal-form"); 159 const close = document.createElement("button"); 160 close.classList.add("help-desk__form-modal-close-btn"); 161 modal.classList.add("help-desk__form-modal"); 162 163 const form = 164 document.querySelector(".wpcf7"); 165 166 const thankYouTemplate = ` 167 <h2>Thank you for your message!</h2> 168 <p>We will get back to you as soon as possible.</p> 169 <button type="button" class="thank-you-close">Close</button> 170 `; 171 172 const thankYouElement = document.createElement("div"); 173 174 thankYouElement.classList.add("help-desk__form-thank-you") 175 thankYouElement.innerHTML = thankYouTemplate; 176 177 thankYouElement.querySelector("button").addEventListener("click", closeModal) 178 179 form.querySelector("form").appendChild(thankYouElement); 180 181 const errorOutput = document.querySelector(".wpcf7-response-output"); 182 form.parentElement.removeChild(form); 183 form.prepend(close); 184 185 errorOutput.parentElement.removeChild(errorOutput); 186 form.querySelector("#contactus-form").appendChild(errorOutput); 187 188 modal.appendChild(form); 189 document.querySelector("body").appendChild(modal); 190 191 if (window.location.search.includes("contact")) { 192 openModal(); 193 } 194
195 [...openBtns].forEach((openBtn) => 196 openBtn.addEventListener("click", openModal) 197 ); 198 199 const whatsAppForm = document.querySelector(".help-desk__form-modal-whatsapp-form"); 200 201 if (whatsAppForm) { 202 whatsAppForm.parentNode.removeChild(whatsAppForm); 203 const newForm = document.createElement("form"); 204 newForm.append(...whatsAppForm.childNodes) 205 Object.entries(whatsAppForm.attributes).map(([_, attributes]) => [attributes.name, attributes.value]).forEach(([name, value]) => newForm.setAttribute(name, value)) 206 form.append(newForm); 207 } 208 209 document.querySelectorAll(".help-desk__form-modal-whatsapp-switcher button").forEach(btn => { 210 btn.addEventListener("click", (e) => { 211 e.target.parentElement.querySelector("button[active]").removeAttribute("active"); 212 e.target.setAttribute("active", ""); 213 modal.classList[e.target.classList.contains("whatsapp") ? "add" : "remove"]("whatsapp"); 214 }) 215 }) 216 217 close.addEventListener("click", closeModal); 218 219 modal.addEventListener("click", (e) => { 220 if (e.target.classList.contains("help-desk__form-modal")) { 221 closeModal(); 222 } 223 }); 224 225 window.addEventListener("keydown", (e) => { 226 if (e.key === "Escape") { 227 closeModal(); 228 } 229 }); 230}); 231 232document.querySelectorAll(".details__summary").forEach(el => el.addEventListener("click", () => el.parentElement.toggleAttribute("open")))
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.