1const rebuyWidgetTemplate=` 2 <div class="rebuy-widget__container"> 3 <div class="rebuy-widget__inner" data-slider-track> 4 <div class="rebuy-widget__products"> 5 {{products}} 6 </div> 7 </div> 8 <div class="rebuy-widget__scrollbar" data-slider-scrollbar> 9 <div class="rebuy-widget__scrollbar-thumb" data-slider-scrollbar-thumb></div> 10 </div> 11 </div> 12`,badgeTemplate=badge=>{let icon="";badge.icon&&(icon=`<img src="${badge.icon}" width="16" height="16" alt="" class="rebuy-widget__tag-icon" />`);let modalLinkClass="";badge.modal_id&&(modalLinkClass="modal-link");let modalIdAttribute="";return badge.modal_id&&(modalIdAttribute=`data-modal-id="${badge.modal_id}"`),`<span ${modalIdAttribute} class="badge ${badge.color_scheme} ${modalLinkClass}">${icon}${badge.text}</span>`},variantSelectorTemplate=({productId,variants,firstVariantId})=>{if(variants.length>1){const options=variants.map(v=>`<option value="${v.id}">${v.title}</option>`).join("");return` 13 <div class="select"> 14 <select class="rebuy-widget__variant-select select__select" data-product-id="${productId}"> 15 ${options} 16 </select> 17 <svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" class="icon icon-caret"> 18 <path fill-rule="evenodd" clip-rule="evenodd" d="M2.29289 5.79289C1.90237 6.18342 1.90237 6.81658 2.29289 7.20711L8.29289 13.2071C8.68342 13.5976 9.31658 13.5976 9.70711 13.2071L15.7071 7.20711C16.0976 6.81658 16.0976 6.18342 15.7071 5.79289C15.3166 5.40237 14.6834 5.40237 14.2929 5.79289L9 11.0858L3.70711 5.79289C3.31658 5.40237 2.68342 5.40237 2.29289 5.79289Z" fill="currentColor"></path> 19 </svg> 20 </div> 21 `}return` 22 <input 23 type="hidden" 24 class="rebuy-widget__variant-select" 25 data-product-id="${productId}" 26 value="${firstVariantId}" 27 > 28 `},productCardTemplate=({product,imageSrc,imageAlt,link,title,priceHtml,compareHtml,tagsHtml,techBadgesHtml,saleBadgeHtml,omnibusPriceHtml,variantSelectorHtml})=>` 29 <div class="rebuy-widget__product"> 30 <a href="${link}" class="rebuy-widget__product-link"> 31 <div class="rebuy-widget__product-image"> 32 <img src="${imageSrc}" alt="${imageAlt}"> 33 <div class="rebuy-widget__product-image-overlay"> 34 <div class="rebuy-widget__product-tags"> 35 ${tagsHtml} 36 </div> 37 <div class="rebuy-widget__sale"> 38 ${saleBadgeHtml} 39 </div> 40 </div> 41 42 <button 43 class="rebuy-widget__add-to-cart" 44 data-product-id="${product.id}" 45 > 46 <svg 47 width="24" 48 height="24"
49 viewBox="0 0 24 24" 50 fill="none" 51 aria-hidden="true" 52 class="icon icon-cart" 53 xmlns="http://www.w3.org/2000/svg" 54 > 55 <path d="M8.65332 17.9424C9.46239 17.9424 10.1181 18.6265 10.1182 19.4707C10.1182 20.315 9.46243 21 8.65332 21C7.84427 20.9999 7.18848 20.3149 7.18848 19.4707C7.18855 18.6265 7.84432 17.9425 8.65332 17.9424ZM18.9092 17.9424C19.7182 17.9424 20.3739 18.6265 20.374 19.4707C20.374 20.315 19.7183 21 18.9092 21C18.1001 20.9999 17.4443 20.315 17.4443 19.4707C17.4444 18.6265 18.1002 17.9424 18.9092 17.9424ZM5.72363 2.40039C6.19732 2.40063 6.60219 2.7554 6.68457 3.24219L6.92969 4.69336H20.6582V4.69434C20.8068 4.69436 20.9548 4.71843 21.0947 4.76855L21.2314 4.82715L21.3623 4.90137C21.4466 4.95555 21.5248 5.01964 21.5957 5.0918L21.6963 5.20605L21.7842 5.33105C21.838 5.41749 21.8826 5.50981 21.917 5.60645L21.9609 5.75488L21.9893 5.90723C22.0025 6.00947 22.0037 6.11305 21.9951 6.21582L21.9746 6.36914L20.6562 13.248C20.5953 13.5656 20.4313 13.8523 20.1914 14.0576C19.9513 14.2629 19.6493 14.3741 19.3389 14.374V14.375H8.56738L8.74023 15.3945H19.6406C20.1799 15.3945 20.617 15.8504 20.6172 16.4131C20.6172 16.9759 20.18 17.4326 19.6406 17.4326H7.9209C7.44707 17.4326 7.04146 17.0777 6.95898 16.5908L4.9043 4.43848H2.79297C2.25362 4.4384 1.81641 3.98176 1.81641 3.41895C1.81658 2.85629 2.25373 2.40047 2.79297 2.40039H5.72363ZM8.22266 12.3369H18.8398L19.9131 6.73145H7.27441L8.22266 12.3369Z" fill="currentColor"/> 56 </svg> 57 <div class="loading__spinner hidden"> 58 <svg 59 aria-hidden="true" 60 focusable="false" 61 class="spinner"
62 viewBox="0 0 66 66" 63 xmlns="http://www.w3.org/2000/svg" 64 > 65 <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle> 66 </svg> 67 </div> 68 69 </button> 70 </div> 71 ${techBadgesHtml} 72 <h3 class="rebuy-widget__product-title">${title}</h3> 73 <div class="rebuy-widget__product-pricing"> 74 ${compareHtml} 75 <span class="rebuy-widget__price">${priceHtml}</span> 76 </div> 77 <div class="rebuy-widget__product-omnibus-price"> 78 ${omnibusPriceHtml||""} 79 </div> 80 </a> 81 <div class="rebuy-widget__variant-wrapper"> 82 ${variantSelectorHtml} 83 </div> 84 </div> 85`;class RebuyWidget{constructor(selector){if(this.host=document.querySelector(selector),!this.host){console.warn("RebuyWidget: Host element not found:",selector);return}this.datasourceId=this.host.dataset.rebuyDatasourceId,this.apiKey=this.host.dataset.rebuyApiKey,this.shopifyProductIds=this.host.dataset.productId,this.limit=this.host.dataset.limit,this.attribution=this.host.dataset.rebuyAttribution,this.source=this.host.dataset.rebuySource,this.widgetId=this.host.dataset.rebuyWidgetId,this.showPercentageSale=this.host.dataset.showPercentageSale,this.priceFormatOptions={currencySymbol:this.host.dataset.currencySymbol||"\u20AC",position:this.host.dataset.currencyPosition||"after",decimalSeparator:this.host.dataset.decimalSeparator||",",thousandsSeparator:this.host.dataset.thousandsSeparator||" ",decimals:this.host.dataset.decimals},this.cart=document.querySelector("slide-cart"),this.badges=JSON.parse(document.querySelector(this.host.dataset.badgesSelector).textContent),this.apiResponse=null}async init(){if(this.host)try{const data=await this.fetchData();if(data.data.length===0){this.host.innerHTML="",this.wrapper.classList.add("rebuy-widget--empty");return}await this.render(data)}catch(err){console.error("RebuyWidget error:",err),this.host.innerHTML=""}}async fetchData(){const params=new URLSearchParams({format:"pretty",key:this.apiKey,shopify_product_ids:this.shopifyProductIds,limit:this.limit,variant_metafields:"yes",metafields:"yes",country_code:window.Shopify.country||"",product_groups:"yes",bust_cache:"yes"}),url=`https://rebuyengine.com/api/v1/custom/id/${this.datasourceId}?${params}`,res=await fetch(url);if(!res.ok)throw new Error(`API error ${res.status}`);return res.json()}formatPrice(value,{currencySymbol,position="after",decimalSeparator=",",thousandsSeparator=" ",decimals=2}){value=parseFloat(value);const fixed=value.toFixed(decimals);let[integer,decimal]=fixed.split(".");integer=integer.replace(/\B(?=(\d{3})+(?!\d))/g,thousandsSeparator);let formatted=decimals>0?`${integer}${decimalSeparator}${decimal}`:integer;return formatted=position==="before"?`${currencySymbol}${formatted}`:`${formatted} ${currencySymbol}`,formatted.trim()}computePercentageChange(oldPrice,newPrice){if(!oldPrice||!newPrice)return 0;const change=(oldPrice-newPrice)/oldPrice*100;return Math.round(change)}createLink(product,variant=null){let variantId=variant?variant.id:product.variants[0]?.id;return`${product.link}?variant=${variantId}&_rdiscovery-handle=${product.handle}&_rdiscovery-widget=${this.widgetId}`}async render(apiResponse){this.apiResponse=apiResponse;const products=apiResponse.data||[],productsHtml=await this.renderProducts(products),html=rebuyWidgetTemplate.replace("{{products}}",productsHtml);this.host.insertAdjacentHTML("beforeend",html),this.bindEvents(),this.host.classList.remove("rebuy-widget--loading")}async renderProducts(products){return(await Promise.all(products.map(p=>this.renderProductCard(p)))).join("")}async renderProductCard(p){const variants=p.variants||[],firstVariant=variants[0]||{},omnibusPriceHtml=await new OmnibusPrice({productId:p.id,variantId:firstVariant.id}).fetchHTML(),price=firstVariant.price?this.formatPrice(firstVariant.price,this.priceFormatOptions):"",compareAt=firstVariant.compare_at_price?this.formatPrice(firstVariant.compare_at_price,this.priceFormatOptions):"",hasDiscount=firstVariant.compare_at_price&&firstVariant.compare_at_price!==firstVariant.price,tagsHtml=this.renderTags({tagsRaw:p.tags,hasDiscount,compareAtPrice:firstVariant.compare_at_price,priceValue:firstVariant.price}
85),techBadgesHtml=this.renderTechBadges(p),saleBadgeHtml=this.renderSaleBadge(firstVariant),variantSelectorHtml=variantSelectorTemplate({productId:p.id,variants,firstVariantId:firstVariant.id}),compareHtml=hasDiscount?`<span class="rebuy-widget__compare">${compareAt}</span>`:"",imgSrc=p.image?.src||p.images?.[0]?.src||"",imgAlt=p.image?.alt||p.title||"";return productCardTemplate({product:p,imageSrc:imgSrc,imageAlt:imgAlt,link:this.createLink(p),title:p.title,priceHtml:price,compareHtml,tagsHtml,techBadgesHtml,saleBadgeHtml,omnibusPriceHtml,variantSelectorHtml})}renderTechBadges(product){const out=[];for(const[key,badge]of Object.entries(this.badges))product.metafields?.some(mf=>typeof mf.value=="string"&&mf.value.includes(key))&&badge.tech_badge&&out.push(badgeTemplate(badge));return` 86 <div class="rebuy-widget__badges"> 87 ${out.length?out.join(""):""} 88 </div> 89 `}renderSaleBadge(p){let output="";if(p.compare_at_price&&p.compare_at_price!==p.price){const saleCfg=this.badges.custom_sale;if(saleCfg){const percentageSale=` -${this.computePercentageChange(p.compare_at_price,p.price)}%`,badge={text:`${saleCfg.text}${this.showPercentageSale==="true"?percentageSale:""}`,color_scheme:saleCfg.color_scheme};output=badgeTemplate(badge)}}return output}renderTags({tagsRaw}){const tags=tagsRaw?tagsRaw.split(",").map(t=>t.trim()):[],out=[];for(const tag of tags){const badge=this.badges[tag];badge&&out.push(badgeTemplate(badge))}return` 90 <div class="rebuy-widget__tags"> 91 ${out.length?out.join(""):""} 92 </div> 93 `}bindEvents(){this.bindAddToCartEvents(),this.bindVariantChangeEvents()}bindAddToCartEvents(){this.host.querySelectorAll(".rebuy-widget__add-to-cart").forEach(btn=>{btn.addEventListener("click",async e=>{e.preventDefault();const productId=btn.dataset.productId,variantId=this.host.querySelector(`.rebuy-widget__variant-select[data-product-id="${productId}"]`)?.value,spinner=btn.querySelector(".loading__spinner");if(!variantId){console.warn("No variant selected for product",productId);return}btn.disabled=!0,spinner.classList.remove("hidden"),btn.classList.add("loading");const data=await(await fetch("/cart/add.js",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:variantId,sections:this.cart?.getSectionsToRender().map(s=>s.id),quantity:1,properties:{_source:this.source,_attribution:this.attribution,_widget_id:this.widgetId}})})).json();typeof publish=="function"&&typeof PUB_SUB_EVENTS<"u"&&publish(PUB_SUB_EVENTS.cartUpdate,{source:"product-form",cartAction:"add",cartData:data}),btn.disabled=!1,spinner.classList.add("hidden"),btn.classList.remove("loading")})})}bindVariantChangeEvents(){this.host.querySelectorAll(".rebuy-widget__variant-select").forEach(select=>{select.addEventListener("change",()=>this.onVariantChange(select))})}onVariantChange(selectEl){const variantId=selectEl.value,productId=selectEl.dataset.productId,product=this.apiResponse?.data?.find(p=>String(p.id)===String(productId));if(!product)return;const variant=product.variants?.find(v=>String(v.id)===String(variantId));if(!variant)return;const productEl=selectEl.closest(".rebuy-widget__product");productEl&&(this.updatePriceDOM(productEl,variant),this.updateTagsDOM(productEl,product,variant),this.updateSaleBadgeDOM(productEl,variant),this.updateOmnibusDOM(productEl,product,variant),this.updateImageDOM(productEl,product,variant),this.updateLinkDOM(productEl,product,variant))}updateLinkDOM(productEl,product,variant){const linkEl=productEl.querySelector(".rebuy-widget__product-link");linkEl&&(linkEl.href=this.createLink(product,variant))}updatePriceDOM(productEl,variant){const priceEl=productEl.querySelector(".rebuy-widget__price"),compareEl=productEl.querySelector(".rebuy-widget__compare");priceEl&&(priceEl.textContent=this.formatPrice(variant.price,this.priceFormatOptions)),compareEl&&(variant.compare_at_price&&variant.compare_at_price!==variant.price?(compareEl.textContent=this.formatPrice(variant.compare_at_price,this.priceFormatOptions),compareEl.style.display="inline"):compareEl.style.display="none")}updateTagsDOM(productEl,product,variant){const tagsEl=productEl.querySelector(".rebuy-widget__tags");if(!tagsEl)return;const hasDiscount=variant.compare_at_price&&variant.compare_at_price!==variant.price;tagsEl.innerHTML=this.renderTags({tagsRaw:product.tags})}updateSaleBadgeDOM(productEl,variant){const saleEl=productEl.querySelector(".rebuy-widget__sale");saleEl&&(saleEl.innerHTML=this.renderSaleBadge(variant))}updateOmnibusDOM(productEl,product,variant){new OmnibusPrice({productId:product.id,variantId:variant.id}).fetchHTML().then(omnibusPriceHtml=>{const el=productEl.querySelector(".rebuy-widget__product-omnibus-price");el&&(el.innerHTML=omnibusPriceHtml||"")})}updateImageDOM(productEl,product,variant){if(!variant.image_id)return;const variantImg=product.images?.find(img=>String(img.id)===String(variant.image_id)),imgEl=productEl.querySelector("img");variantImg&&imgEl&&(imgEl.src=variantImg.src)}}class OmnibusPrice{constructor({productId,variantId}){this.shop=window.Shopify,this.productId=productId,this.variantId=variantId}async fetchHTML(){const res=await fetch("/apps/am-omnibus-price",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({shop:this.shop.shop,productId:this.productId,variantId:this.variantId,locale:this.shop.locale,currency:this.shop.currency})});try{const html=(await res.json()).lowestPriceHtml;if(!html)throw new Error("No lowest price HTML returned.");return html}catch(error){console.warn("Error fetching Omnibus price:",error)}}} 94//# sourceMappingURL=/cdn/shop/t/3/assets/rebuy-api.js.map?v=15027211639191305691778136887
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.