1class ProductRecommendations extends HTMLElement{#intersectionObserver=new IntersectionObserver((entries,observer)=>{if(!entries[0]?.isIntersecting)return;observer.disconnect();this.#loadRecommendations()},{rootMargin:'0px 0px 400px 0px'});#mutationObserver=new MutationObserver((mutations)=>{for(const mutation of mutations){if(mutation.target!==this||mutation.type!=='attributes')continue;if(mutation.attributeName==='data-recommendations-performed'&&this.dataset.recommendationsPerformed==='true') 2continue;this.#loadRecommendations();break}});#cachedRecommendations={};#activeFetch=null;connectedCallback(){this.#intersectionObserver.observe(this);this.#mutationObserver.observe(this,{attributes:!0})} 3#loadRecommendations(){const{productId,recommendationsPerformed,sectionId,intent}=this.dataset;const id=this.id;if(!productId||!id){throw new Error('Product ID and an ID attribute are required')} 4if(recommendationsPerformed==='true'){return} 5this.#fetchCachedRecommendations(productId,sectionId,intent).then((result)=>{if(!result.success){if(!Shopify.designMode){this.#handleError(new Error(`Server returned ${result.status}`))} 6return} 7const html=document.createElement('div');html.innerHTML=result.data||'';const recommendations=html.querySelector(`product-recommendations[id="${id}"]`);if(recommendations?.innerHTML&&recommendations.innerHTML.trim().length){this.dataset.recommendationsPerformed='true';this.innerHTML=recommendations.innerHTML}else{this.#handleError(new Error('No recommendations available'))}}).catch((e)=>{this.#handleError(e)})} 8async #fetchCachedRecommendations(productId,sectionId,intent){const url=`${this.dataset.url}&product_id=${productId}§ion_id=${sectionId}&intent=${intent}`;const cachedResponse=this.#cachedRecommendations[url];if(cachedResponse){return{success:!0,data:cachedResponse}} 9this.#activeFetch?.abort();this.#activeFetch=new AbortController();try{const response=await fetch(url,{signal:this.#activeFetch.signal});if(!response.ok){return{success:!1,status:response.status}} 10const text=await response.text();this.#cachedRecommendations[url]=text;return{success:!0,data:text}}finally{this.#activeFetch=null}} 11#handleError(error){console.error('Product recommendations error:',error);this.classList.add('hidden');this.dataset.error='Error loading product recommendations'}} 12if(!customElements.get('product-recommendations')){customElements.define('product-recommendations',ProductRecommendations)}
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.