1class PredictiveSearch extends SearchForm{constructor(){super(),this.cachedResults={},this.skuSearchCache={},this.predictiveSearchResults=this.querySelector("[data-predictive-search]"),this.allPredictiveSearchInstances=document.querySelectorAll("predictive-search"),this.isOpen=!1,this.abortController=new AbortController,this.searchTerm="",this.pendingSingleProductRedirect=!1,this.setupEventListeners()}setupEventListeners(){this.input.form.addEventListener("submit",this.onFormSubmit.bind(this)),this.input.addEventListener("focus",this.onFocus.bind(this)),this.addEventListener("focusout",this.onFocusOut.bind(this)),this.addEventListener("keyup",this.onKeyup.bind(this)),this.addEventListener("keydown",this.onKeydown.bind(this))}getQuery(){return this.input.value.trim()}onChange(){super.onChange();const newSearchTerm=this.getQuery();if(!this.searchTerm||!newSearchTerm.startsWith(this.searchTerm)){this.querySelector("#predictive-search-results-groups-wrapper")?.remove();const newSearchUpper=newSearchTerm.trim().toUpperCase();Object.keys(this.skuSearchCache).filter(key=>!newSearchUpper.startsWith(key)&&!key.startsWith(newSearchUpper)).forEach(key=>delete this.skuSearchCache[key])}if(this.updateSearchForTerm(this.searchTerm,newSearchTerm),this.searchTerm=newSearchTerm,this.pendingSingleProductRedirect=!1,!this.searchTerm.length){this.close(!0);return}this.getSearchResults(this.searchTerm)}getProductHandleFromUrl(href){if(!href)return null;try{const match=new URL(href,window.location.origin).pathname.match(/\/products\/([^/?#]+)/i);return match?decodeURIComponent(match[1]).toLowerCase():null}catch{return null}}getSingleProductUrl(){const productItems=this.querySelectorAll("#predictive-search-results-products-list .predictive-search__list-item, #predictive-search-results-sku-products-list .predictive-search__list-item"),uniqueProducts=new Map;return productItems.forEach(item=>{const href=item.querySelector("a[href]")?.getAttribute("href"),handle=this.getProductHandleFromUrl(href);if(!handle)return;const existingHref=uniqueProducts.get(handle),prefersVariantUrl=href.includes("variant=")&&(!existingHref||!existingHref.includes("variant="));(!existingHref||prefersVariantUrl)&&uniqueProducts.set(handle,href)}),uniqueProducts.size!==1?null:uniqueProducts.values().next().value}getProductHandlesFromMarkup(markup){const handles=new Set;return new DOMParser().parseFromString(markup,"text/html").querySelectorAll("#predictive-search-results-products-list a[href]").forEach(link=>{const handle=this.getProductHandleFromUrl(link.getAttribute("href"));handle&&handles.add(handle)}),handles}getUniqueSkuResults(skuResults,resultsMarkup){if(!skuResults||skuResults.length===0)return[];const existingHandles=this.getProductHandlesFromMarkup(resultsMarkup),uniqueSkuResults=[],seenHandles=new Set;return skuResults.forEach(item=>{const handle=item.product?.handle?.toLowerCase();!handle||existingHandles.has(handle)||seenHandles.has(handle)||(seenHandles.add(handle),uniqueSkuResults.push(item))}),uniqueSkuResults}hideDuplicateProductItems(){const seenHandles=new Set;this.querySelectorAll("#predictive-search-results-products-list .predictive-search__list-item, #predictive-search-results-sku-products-list .predictive-search__list-item").forEach(item=>{const handle=this.getProductHandleFromUrl(item.querySelector("a[href]")?.getAttribute("href"));if(handle){if(seenHandles.has(handle)){item.remove();return}seenHandles.add(handle)}});const skuList=this.querySelector("#predictive-search-results-sku-products-list");skuList&&!skuList.querySelector(".predictive-search__list-item")&&skuList.closest(".predictive-search__result-group")?.remove()}goToSingleProductIfAvailable(){const productUrl=this.getSingleProductUrl();return productUrl?(window.location.assign(productUrl),!0):!1}onFormSubmit(event){if(!this.getQuery().length||this.querySelector('[aria-selected="true"] a')){event.preventDefault();return}if(!this.querySelector('[aria-selected="true"]')){if(this.goToSingleProductIfAvailable()){event.preventDefault();return}this.hasAttribute("loading")&&(event.preventDefault(),this.pendingSingleProductRedirect=!0)}}onFormReset(event){super.onFormReset(event),super.shouldResetForm()&&(this.searchTerm="",this.abortController.abort(),this.abortController=new AbortController,this.closeResults(!0),this.pendingSingleProductRedirect=!1,this.skuSearchCache={})}onFocus(){const currentSearchTerm=this.getQuery();currentSearchTerm.length&&(this.searchTerm!==currentSearchTerm?this.onChange():this.getAttribute("results")==="true"?this.open():this.getSearchResults(this.searchTerm))}onFocusOut(){setTimeout(()=>{this.contains(document.activeElement)||this.close()})}onKeyup(event){switch(this.getQuery().length||this.close(!0),event.preventDefault(),event.code){case"ArrowUp":this.switchOption("up");break;case"ArrowDown":this.switchOption("down");break;case"Enter":this.selectOption();break}}onKeydown(event){(event.code==="ArrowUp"||event.code==="ArrowDown")&&event.preventDefault()}updateSearchForTerm(previousTerm,newTerm){const searchForTextElement=this.querySelector("[data-predictive-search-search-for-text]"),currentButtonText=searchForTextElement?.innerText;if(currentButtonText){const matches=currentButtonText.match(new RegExp(previousTerm,"g"));if(matches&&matches.length>1)return;const newButtonText=currentButtonText.replace(previousTerm,newTerm);searchForTextElement.innerText=newButtonText}}switchOption(direction){if(!this.getAttribute("open"))return;const moveUp=direction==="up",selectedElement=this.querySelector('[aria-selected="true"]'),allVisibleElements=Array.from(this.querySelectorAll("li, button.predictive-search__item")).filter(element=>element.offsetParent!==null);let activeElementIndex=0;if(moveUp&&!selectedElement)return;let selectedElementIndex=-1,i=0;for(;selectedElementIndex===-1&&i<=allVisibleElements.length;)allVisibleElements[i]===selectedElement&&(selectedElementIndex=i),i++;if(this.statusElement.textContent="",!moveUp&&selectedElement?activeElementIndex=selectedElementIndex===allVisibleElements.length-1?0:selectedElementIndex+1:moveUp&&(activeElementIndex=selectedElementIndex===0?allVisibleElements.length-1:selectedElementIndex-1),activeElementIndex===selectedElementIndex)return;const activeElement=allVisibleElements[activeElementIndex];activeElement.setAttribute("aria-selected",!0),selectedElement&&selectedElement.setAttribute("aria-selected",!1),this.input.setAttribute("aria-activedescendant",activeElement.id)}selectOption(){const selectedOption=this.querySelector('[aria-selected="true"] a, button[aria-selected="true"]');selectedOption&&selectedOption.click()}getSearchResults(searchTerm){const queryKey=searchTerm.replace(" ","-").toLowerCase();if(this.setLiveRegionLoadingState(),this.cachedResults[queryKey]){this.renderSearchResults(this.cachedResults[queryKey]);return}const looksLikeSKU=/^[A-Za-z0-9\-_]{2,20}$/.test(searchTerm.trim())&&!searchTerm.includes(" ");fetch(`${routes.predictive_search_url}?q=${encodeURIComponent(searchTerm)}§ion_id=predictive-search`,{signal:this.abortController.signal}).then(response=>{if(!response.ok){var error=new Error(response.status);throw this.close(),error}return response.text()}).then(text=>{const resultsMarkup=new DOMParser().parseFromString(text,"text/html").querySelector("#shopify-section-predictive-search").innerHTML,hasProducts=resultsMarkup.includes("predictive-search-option-product");
1if(looksLikeSKU){const skuCacheKey=searchTerm.trim().toUpperCase();if(this.skuSearchCache[skuCacheKey]){const cachedSkuResults=this.getUniqueSkuResults(this.skuSearchCache[skuCacheKey],resultsMarkup);if(cachedSkuResults.length>0){const skuResultsHTML=this.generateSKUResultsHTML(cachedSkuResults);return resultsMarkup+skuResultsHTML}return resultsMarkup}const searchTermLen=searchTerm.trim().length,exactMatchOnly=searchTermLen===6&&/^[A-Z]\d{5}$|^\d{6}$/.test(skuCacheKey)||searchTermLen>=8&&!hasProducts;return this.searchBySKU(searchTerm.trim().toUpperCase(),exactMatchOnly).then(skuResults=>{this.skuSearchCache[skuCacheKey]=skuResults;const uniqueSkuResults=this.getUniqueSkuResults(skuResults,resultsMarkup);if(uniqueSkuResults.length>0){const skuResultsHTML=this.generateSKUResultsHTML(uniqueSkuResults);return resultsMarkup+skuResultsHTML}return resultsMarkup}).catch(()=>resultsMarkup)}return resultsMarkup}).then(finalMarkup=>{this.allPredictiveSearchInstances.forEach(predictiveSearchInstance=>{predictiveSearchInstance.cachedResults[queryKey]=finalMarkup}),this.renderSearchResults(finalMarkup)}).catch(error=>{if(error?.code!==20)throw this.close(),error})}async searchBySKU(sku,exactMatch=!1){const foundProducts=[],skuUpper=sku.toUpperCase(),maxResults=exactMatch?1:10,maxPages=exactMatch?16:12;try{const pagePromises=[],pagesToCheck=[];for(let page=1;page<=maxPages;page++)pagesToCheck.push(page);const concurrentLimit=4;for(let i=0;i<pagesToCheck.length;i+=concurrentLimit){const batchPromises=pagesToCheck.slice(i,i+concurrentLimit).map(page=>fetch(`/collections/all/products.json?limit=250&page=${page}`,{signal:this.abortController.signal}).then(response=>response.ok?response.json():null).catch(()=>null)),batchResults=await Promise.all(batchPromises);for(let j=0;j<batchResults.length&&!(foundProducts.length>=maxResults);j++){const data=batchResults[j];if(!(!data||!data.products||data.products.length===0))for(const product of data.products){if(foundProducts.length>=maxResults)break;if(!(!product.variants||product.variants.length===0)){for(const variant of product.variants)if(variant.sku){const variantSkuUpper=variant.sku.toUpperCase();let matches=!1;if(exactMatch){if(matches=variantSkuUpper===skuUpper,matches)return foundProducts.push({product,variant}),foundProducts}else(variantSkuUpper===skuUpper||skuUpper.length>=3&&(variantSkuUpper.startsWith(skuUpper)||variantSkuUpper.includes(skuUpper)))&&(matches=!0);if(matches){foundProducts.push({product,variant});break}}}}}if(exactMatch&&foundProducts.length>0||foundProducts.length>=maxResults)break}}catch(error){error?.code!==20&&console.warn("Error searching for SKU:",error)}return foundProducts}generateSKUResultsHTML(skuResults){if(!skuResults||skuResults.length===0)return"";const formatMoney=cents=>{if(window.Shopify&&window.Shopify.formatMoney)return window.Shopify.formatMoney(cents,window.Shopify.money_format||"{{amount}}");const amount=(cents/100).toFixed(2),currency=window.Shopify?.currency?.active||"EUR";return`${amount} ${currency==="EUR"?"\u20AC":currency==="USD"?"$":currency}`},getImageUrl=product=>{if(product.featured_image)return typeof product.featured_image=="string"?product.featured_image:product.featured_image.src||"";if(product.variants&&product.variants.length>0){for(const v of product.variants)if(v.featured_image){const img=v.featured_image;if(typeof img=="string")return img;if(img.src)return img.src}}if(product.images&&product.images.length>0)for(const img of product.images){if(typeof img=="string")return img;if(img&&img.src)return img.src}if(product.image){if(typeof product.image=="string")return product.image;if(product.image.src)return product.image.src}return""};let html='<div class="predictive-search__result-group"><div>';return html+='<h2 id="predictive-search-sku-products" class="predictive-search__heading text-body caption-with-letter-spacing">Products</h2>',html+='<ul id="predictive-search-results-sku-products-list" class="predictive-search__results-list list-unstyled" role="group" aria-labelledby="predictive-search-sku-products">',skuResults.forEach((item,index)=>{const product=item.product,variant=item.variant,imageUrl=getImageUrl(product),priceFormatted=variant.price?formatMoney(variant.price):"";html+=`<li id="predictive-search-option-sku-product-${index+1}" class="predictive-search__list-item" role="option" aria-selected="false">`,html+=`<a href="/products/${product.handle}?variant=${variant.id}" class="predictive-search__item predictive-search__item--link-with-thumbnail link link--text" tabindex="-1">`,imageUrl&&(html+=`<img class="predictive-search__image" src="${this.escapeHtml(imageUrl)}" alt="${this.escapeHtml(product.title)}" width="50" height="50" loading="lazy">`),html+=`<div class="predictive-search__item-content${!imageUrl&&!priceFormatted?" predictive-search__item-content--centered":""}">`,html+=`<p class="predictive-search__item-heading h5">${this.escapeHtml(product.title)}</p>`,html+=`<p class="predictive-search__item-sku text-body-small" style="color: #666; font-size: 12px; margin-top: 2px;">${this.escapeHtml(variant.sku)}</p>`,html+="</div></a></li>"}),html+="</ul></div></div>",html}escapeHtml(text){const div=document.createElement("div");return div.textContent=text,div.innerHTML}setLiveRegionLoadingState(){this.statusElement=this.statusElement||this.querySelector(".predictive-search-status"),this.loadingText=this.loadingText||this.getAttribute("data-loading-text"),this.setLiveRegionText(this.loadingText),this.setAttribute("loading",!0)}setLiveRegionText(statusText){this.statusElement.setAttribute("aria-hidden","false"),this.statusElement.textContent=statusText,setTimeout(()=>{this.statusElement.setAttribute("aria-hidden","true")},1e3)}renderSearchResults(resultsMarkup){this.predictiveSearchResults.innerHTML=resultsMarkup,this.setAttribute("results",!0),this.hideDuplicateProductItems(),this.setLiveRegionResults(),this.open(),this.pendingSingleProductRedirect&&(this.pendingSingleProductRedirect=!1,this.goToSingleProductIfAvailable()||this.input.form.submit())}setLiveRegionResults(){this.removeAttribute("loading"),this.setLiveRegionText(this.querySelector("[data-predictive-search-live-region-count-value]").textContent)}getResultsMaxHeight(){return this.resultsMaxHeight=window.innerHeight-document.querySelector(".section-header")?.getBoundingClientRect().bottom,this.resultsMaxHeight}open(){this.predictiveSearchResults.style.maxHeight=this.resultsMaxHeight||`${this.getResultsMaxHeight()}px`,this.setAttribute("open",!0),this.input.setAttribute("aria-expanded",!0),this.isOpen=!0}close(clearSearchTerm=!1){this.closeResults(clearSearchTerm),this.isOpen=!1}closeResults(clearSearchTerm=!1){clearSearchTerm&&(this.input.value="",this.removeAttribute("results"));const selected=this.querySelector('[aria-selected="true"]');selected&&selected.setAttribute("aria-selected",!1),this.input.setAttribute("aria-activedescendant",""),this.removeAttribute("loading"),this.removeAttribute("open"),this.input.setAttribute("aria-expanded",!1),this.resultsMaxHeight=!1,this.predictiveSearchResults.removeAttribute("style")}}customElements.define("predictive-search",PredictiveSearch); 2//# sourceMappingURL=/cdn/shop/t/33/assets/predictive-search.js.map?v=173107362110754071101789728619
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.