PageSourceSearch

https://www.lyleandscott.com/cdn/shop/t/458/assets/algolia-product-card.js?v=110552046640825710161788364385

js lyleandscott.com collected 2026-09-24 22:59:48 UTC 14,430 bytes, 118 lines download raw bytes

1import{createMoneyFormatter,escapeAttribute,escapeHtml,formatMoney,imageUrl,isSameProduct,isWhiteSwatch,metafieldValue,numericId,variantLabel}from"@lyle/algolia-product-utils";document.addEventListener("click",event=>{const button=event.target.closest("[data-card-size]");button&&(event.preventDefault(),selectSize(button))});async function selectSize(button){const productUrl=new URL(button.dataset.productUrl,window.location.origin),size=button.dataset.sizeValue;button.setAttribute("aria-busy","true");try{const response=await fetch(`${productUrl.pathname}.js`),variant=(response.ok?await response.json():null)?.variants?.find(item=>variantLabel(item).toLowerCase()===size.toLowerCase());variant?.id&&productUrl.searchParams.set("variant",numericId(variant.id))}catch{}window.location.href=productUrl.toString()}export class AlgoliaProductCardRenderer{#config;#hiddenSaleCookie;#icons;#isMobile;#moneyFormatter;constructor({config,hiddenSaleCookie="ls-can-view-hidden-sale",icons={},isMobile=()=>!1}){this.#config=config,this.#hiddenSaleCookie=hiddenSaleCookie,this.#icons=icons,this.#isMobile=isMobile,this.#moneyFormatter=this.#createMoneyFormatter()}render(product,index,options={}){const card=this.#cardViewModel(product,index,options),imageAttrs=this.#imageOptionAttrs(options);return`
2      <article class="product-card" data-product-card data-product-id="${this.#escapeHtml(card.id)}" data-product-index="${this.#escapeHtml(index)}" data-product-url="${this.#escapeHtml(card.url)}" data-product-handle="${this.#escapeHtml(card.handle)}" data-algolia-index="${this.#escapeHtml(card.indexName)}"${imageAttrs}>
3        <div class="product-card__thumbnail">
4          <a href="${this.#escapeHtml(card.url)}" data-product-link data-object-id="${this.#escapeHtml(card.objectID)}" data-query-id="${this.#escapeHtml(card.queryID)}" data-position="${this.#escapeHtml(card.position)}">
5            ${this.#badgeMarkup(card.badge)}
6            ${this.#imageMarkup(card.primaryImage,product.title,index,"product-card__primary-image")}
7            ${this.#imageMarkup(card.secondaryImage,"",index,"product-card__secondary-image",{hidden:!0})}
8          </a>
9
10          ${this.#quickAddMarkup(card)}
11
12          <div class="product-card__sizes" data-product-card-sizes>${this.#sizesMarkup(product)}</div>
13        </div>
14
15        <div class="product-card__footer">
16          <p class="product-card__title text-body-sm text-center">${this.#escapeHtml(product.title)}</p>
17
18          ${product.featuredCollection?`<p class="product-card__featured-collection text-eyebrow-2xs text-center">${this.#escapeHtml(product.featuredCollection)}</p>`:""}
19          ${this.#priceMarkup(product)}
20          ${this.#memberMarkup(product)}
21
22          <div class="product-card__swatches" data-product-card-swatches></div>
23        </div>
24
25        <script type="application/json" data-card-product>${this.#safeJson(this.#cardState(product))}<\/script>
26      </article>
27    `}renderSwatches(card,product,swatches){const container=card.querySelector("[data-product-card-swatches]");if(!container||!swatches.length)return;const visible=this.#visibleSwatches(swatches,product),hiddenCount=swatches.length-visible.length;container.innerHTML=`
28      ${visible.map(swatch=>this.#swatchMarkup(swatch,product)).join("")}
29      ${hiddenCount>0?`<a class="product-card__swatch-count text-eyebrow-2xs" href="${this.#escapeHtml(product.url)}">+${hiddenCount}</a>`:""}
30    `}#cardViewModel(product,index,options={}){return{badge:this.#productBadge(product),handle:product.handle,id:product.id,indexName:product.__indexName,objectID:product.objectID||product.id,position:product.__position||index+1,primaryImage:this.#primaryImage(product,options),queryID:product.__queryID||"",quickVariant:this.#quickVariant(product),secondaryImage:this.#secondaryImage(product,options),url:product.url}}#imageOptionAttrs(options={}){if(options.imageOrder==null&&options.useAltImage==null)return"";const imageOrder=options.imageOrder??this.#config.productCard?.imageOrder??"modal",useAltImage=options.useAltImage??this.#config.productCard?.useAltImage??!1;return` data-image-order="${this.#escapeHtml(imageOrder)}" data-use-alt-image="${useAltImage?"true":"false"}"`}#imageOptions(options={}){return{imageOrder:options.imageOrder??this.#config.productCard?.imageOrder??"modal",useAltImage:options.useAltImage??this.#config.productCard?.useAltImage??!1}}#quickVariant(product){return product.variantId||product.variants?.find(variant=>variant.available)?.id||product.variants?.[0]?.id||""}#badgeMarkup(badge){return badge.label?`
31      <span class="product-card__badge text-eyebrow-2xs ${badge.type==="sale"?"product-card__badge--sale":""}" style="${this.#badgeStyle(badge)}">
32        ${this.#escapeHtml(badge.label)}
33      </span>
34    `:""}#imageMarkup(image,alt,index,className,options={}){const{hidden=!1}=options;if(!image)return"";const altText=hidden?"":alt||image.alt||"";return`
35      <span class="product-card__image-frame ${className}" ${hidden?'aria-hidden="true"':""}>
36        <img
37          class="product-card__image"
38          src="${this.#escapeHtml(this.#imageUrl(image,900))}"
39          srcset="${this.#escapeHtml(this.#imageSrcset(image))}"
40          sizes="(width >= 1024px) 25vw, 50vw"
41          alt="${this.#escapeHtml(altText)}"
42          loading="${hidden||index>=4?"lazy":"eager"}"
43          decoding="async"
44          ${!hidden&&index<4?'fetchpriority="high"':""}
45          ${image.width?`width="${this.#escapeHtml(image.width)}"`:""}
46          ${image.height?`height="${this.#escapeHtml(image.height)}"`:""}
47        >
48      </span>
49    `}#quickAddMarkup(card){return this.#config.productCard?.showQuickAdd===!1||!card.quickVariant?"":`
50      <button class="product-card__quick-add-mobile" type="button" data-quick-view data-variant-id="${this.#escapeHtml(card.quickVariant)}" data-object-id="${this.#escapeHtml(card.objectID)}" data-query-id="${this.#escapeHtml(card.queryID)}" aria-label="${this.#escapeHtml(this.#config.strings.quickAdd)}">
51        ${this.#icon("bag")}
52      </button>
53    `}#priceMarkup(product){const memberDiscount=Number(this.#metafieldValue(product,"member_discount_percentage")||0),membersOnly=this.#metafieldValue(product,"members_only_purchase")===!0,price=this.#hiddenSalePrice(product)||product.price?.amount||0,compareAtPrice=product.compareAtPrice?.amount||null,onSale=compareAtPrice&&price<compareAtPrice;if(!this.#config.memberPricing.isCustomer&&memberDiscount&&membersOnly)return`<p class="product-card__membership-text text-body-sm">${this.#escapeHtml(this.#config.strings.memberPricing.onlyMembers)}</p>`;const baseMarkup=`
54      <p class="product-prices product-card__prices text-body-sm text-center">
55        ${onSale?`<span class="product-prices__compare-at-price">${this.#formatMoney(compareAtPrice)}</span>`:""}
56        <span class="product-prices__price ${onSale?"product-prices__price--on-sale":""}">${this.#formatMoney(price)}</span>
57        ${product.available===!1?`<span class="product-prices__sold-out">${this.#escapeHtml(this.#config.strings.soldOut||"")}</span>`:""}
58      </p>
59    `;if(!this.#config.memberPricing.isCustomer||!memberDiscount)return baseMarkup;const memberPrice=price-price*memberDiscount;return`
60      <div class="product-card__prices-container">
61        <span class="product-card__original-price text-body-xs">${this.#escapeHtml(this.#config.strings.memberPricing.originalPrice)}</span>
62        ${baseMarkup}
63      </div>
64
65      <div class="product-card__membership-badge">
66        ${this.#icon("eagle")}
67        <span class="text-body-xs">${this.#escapeHtml(this.#config.strings.memberPricing.memberPrice)} ${this.#formatMoney(memberPrice)}</span>
68      </div>
69    `}#memberMarkup(product){const memberDiscount=Number(this.#metafieldValue(product,"member_discount_percentage")||0);return this.#config.memberPricing.isCustomer||!memberDiscount?"":`
70      <div class="product-card__membership-badge">
71        ${this.#icon("eagle")}
72        <span class="text-body-xs">${this.#escapeHtml(this.#config.strings.memberPricing.exclusive)}</span>
73      </div>
74    `}#productBadge(product){const strings=this.#config.strings.badges,badgeTag=product.tags?.find(tag=>tag.toLowerCase().startsWith("badge:"))||"";let[label="",color="#111111",bgColor="#f9f9f9"]=badgeTag.replace(/badge:/i,"").split(":").map(part=>part.trim()),type="badge";switch((product.tags||[]).includes("coming-soon")&&!label&&(label=strings.comingSoon),label.toLowerCase()){case"bestseller":case"best seller":label=strings.bestseller;break;case"coming soon":case"coming-soon":label=strings.comingSoon;break;case"new":case"new in":label=strings.newIn;break;case"sale":label=strings.sale,type="sale";break;default:/\d+% off/i.test(label)&&(label=label.replace(/(\d+)% off/i,(_,percent)=>strings.percentOff.replace("__percent__",percent)));break}return{label,color,bgColor,type}}#badgeStyle(badge){return`color: ${this.#escapeHtml(badge.color)}; background-color: ${this.#escapeHtml(badge.bgColor)};`}#primaryImage(product,options={}){const{imageOrder,useAltImage}=this.#imageOptions(options),images=this.#imagesWithoutAlt(product),altImage=this.#altLandingImage(product);return useAltImage&&altImage?altImage:imageOrder==="flat"?images[images.length-1]||product.images?.[0]||null:images[0]||product.images?.[0]||null}#secondaryImage(product,options={}){const{imageOrder,useAltImage}=this.#imageOptions(options);if(useAltImage)return null;const images=this.#imagesWithoutAlt(product);return images.length<2?null:imageOrder==="flat"?images[0]:images[images.length-1]}#altLandingImage(product){return(product.images||[]).find(image=>String(image.alt||"").includes("alt_landing_image"))}#imagesWithoutAlt(product){return(product.images||[]).filter(image=>!String(image.alt||"").includes("alt_landing_image"))}#swatchMarkup(swatch,product){const color=this.#metafieldValue(swatch,"swatch_code")||"#ffffff";return`
75      <button
76        class="product-card__swatch ${this.#isSameProduct(swatch,product)?"is-active":""} ${isWhiteSwatch(color)?"product-card__swatch--white":""}"
77        type="button"
78        data-card-swatch
79        data-product='${this.#escapeAttribute(JSON.stringify(swatch))}'
80        aria-label="${this.#escapeHtml(swatch.title)}"
81      >
82        <span class="product-card__swatch-inner" style="--swatch-color: ${this.#escapeHtml(color)}"></span>
83      </button>
84    `}#variantSizeMarkup(variant,product){const label=this.#variantLabel(variant),id=this.#numericId(variant.id);return variant.available?`
85      <a
86        class="product-card__size text-eyebrow-md"
87        href="${this.#escapeHtml(`${product.url}?variant=${id}`)}"
88        data-product-link
89        data-object-id="${this.#escapeHtml(product.objectID||product.id)}"
90        data-query-id="${this.#escapeHtml(product.__queryID||"")}"
91        data-position="${this.#escapeHtml(product.__position||"")}"
92      >
93        ${this.#escapeHtml(label)}
94      </a>
95    `:`
96        <span class="product-card__size text-eyebrow-md" aria-disabled="true">
97          ${this.#escapeHtml(label)}
98        </span>
99      `}#sizesMarkup(product){const variants=product.variants||[];return variants.length>1?new Set(variants.map(variant=>this.#variantLabel(variant))).size<2?"":variants.map(variant=>this.#variantSizeMarkup(variant,product)).join(""):product.sizes?.length?product.sizes.length<2?"":product.sizes.map(size=>
99this.#fallbackSizeMarkup(size,product)).join(""):(product.sizesAvailable||[]).map(size=>this.#fallbackSizeMarkup(size,product)).join("")}#fallbackSizeMarkup(size,product){return Number(product.sizeStock?.[size])===0?`
100        <span class="product-card__size text-eyebrow-md" aria-disabled="true">
101          ${this.#escapeHtml(size)}
102        </span>
103      `:`
104      <button
105        class="product-card__size text-eyebrow-md"
106        type="button"
107        data-card-size
108        data-product-link
109        data-product-url="${this.#escapeHtml(product.url)}"
110        data-size-value="${this.#escapeHtml(size)}"
111        data-object-id="${this.#escapeHtml(product.objectID||product.id)}"
112        data-query-id="${this.#escapeHtml(product.__queryID||"")}"
113        data-position="${this.#escapeHtml(product.__position||"")}"
114      >
115        ${this.#escapeHtml(size)}
116      </button>
117    `}#visibleSwatches(swatches,product){const max=this.#isMobile()?6:8,visible=swatches.slice(0,max),activeSwatch=swatches.find(swatch=>this.#isSameProduct(swatch,product));return!activeSwatch||visible.some(swatch=>this.#isSameProduct(swatch,product))?visible:[activeSwatch,...swatches.filter(swatch=>!this.#isSameProduct(swatch,activeSwatch))].slice(0,max)}#variantLabel(variant){return variantLabel(variant)}#metafieldValue(product,name){return metafieldValue(product,name)}#hiddenSalePrice(product){if(!document.cookie.includes(`${this.#hiddenSaleCookie}=true`))return null;const currency=this.#config.market.currencyCode,tag=product.tags?.find(item=>item.startsWith(`vip-price-${currency}:`));if(!tag)return null;const value=Number(tag.split(":")[1]);return Number.isNaN(value)?null:value}#isSameProduct(productA,productB){return isSameProduct(productA,productB)}#cardState(product){return{available:product.available,compareAtPrice:product.compareAtPrice,featuredCollection:product.featuredCollection,handle:product.handle,id:product.id,images:product.images||[],metafields:product.metafields||[],objectID:product.objectID,price:product.price,sizeStock:product.sizeStock,sizes:product.
117sizes,sizesAvailable:product.sizesAvailable,tags:product.tags||[],title:product.title,url:product.url,variantId:product.variantId,variants:product.variants||[],__indexName:product.__indexName,__position:product.__position,__queryID:product.__queryID}}#imageSrcset(image){return[200,300,400,500,700,900].map(width=>`${this.#imageUrl(image,width)} ${width}w`).join(", ")}#imageUrl(image,width){return imageUrl(image,width)}#createMoneyFormatter(){return createMoneyFormatter(this.#config.market)}#formatMoney(value){return formatMoney(value,{currencySymbol:this.#config.market.currencySymbol,formatter:this.#moneyFormatter})}#numericId(id){return numericId(id)}#icon(name){return this.#icons[name]||""}#safeJson(value){return JSON.stringify(value).replace(/<\/script/gi,"<\\/script")}#escapeHtml(value){return escapeHtml(value)}#escapeAttribute(value){return escapeAttribute(value)}}
118//# sourceMappingURL=/cdn/shop/t/458/assets/algolia-product-card.js.map?v=110552046640825710161788364385

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.