PageSourceSearch

https://www.lyleandscott.com/cdn/shop/t/458/assets/algolia-product…?v=182558789341924908031788364384

js lyleandscott.com collected 2026-09-24 22:59:49 UTC 11,178 bytes, 96 lines download raw bytes

1import{escapeAttribute,escapeHtml,hiddenSaleLineItemProperties,imageUrl,isSameProduct,isWhiteSwatch,metafieldValue,numericId,parseJson,variantLabel}from"@lyle/algolia-product-utils";export class AlgoliaProductCardQuickView{#callbacks;#config;#icons;#product=null;#root;#splide=null;#variantId=null;constructor({callbacks,config,icons={},root}){this.#callbacks=callbacks,this.#config=config,this.#icons=icons,this.#root=root}async open(button){const card=button.closest("[data-product-card]"),product=this.#callbacks.cardProduct(card),overlay=this.#overlay();if(!card||!product||!overlay)return;this.#product=product,this.#variantId=null,this.#showOverlay(overlay,button);const productJson=await this.#callbacks.fetchProductJson(product.handle),mergedProduct=this.#mergeProduct(product,productJson);this.#product=mergedProduct,this.#variantId=this.#defaultVariantId(mergedProduct),await this.#render(mergedProduct)}close(){const overlay=this.#overlay();overlay&&(this.#destroyGallery(),overlay.classList.remove("is-open"),overlay.matches(":popover-open")&&typeof overlay.hidePopover=="function"&&overlay.hidePopover(),this.#product=null,this.#variantId=null,document.body.style.overflow="")}handleToggle(event){event.newState==="closed"&&(this.#destroyGallery(),event.target.classList.remove("is-open"),this.#product=null,this.#variantId=null,document.body.style.overflow="")}async selectSwatch(button){const product=this.#parseJson(button.dataset.product);if(!product)return;const currentProduct=this.#product,productJson=await this.#callbacks.fetchProductJson(product.handle),selectedProduct=this.#mergeProduct({...product,__queryID:currentProduct?.__queryID||product.__queryID},productJson);this.#product=selectedProduct,this.#variantId=this.#defaultVariantId(selectedProduct),await this.#render(selectedProduct)}selectVariant(button){this.#variantId=numericId(button.dataset.variantId),this.#product&&this.#render(this.#product)}async add(button){const product=this.#product,variant=this.#selectedVariant(product);if(!(!product||!variant?.available)){button.setAttribute("aria-busy","true");try{const response=await fetch(this.#cartAddUrl(),{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({id:numericId(variant.id),properties:this.#lineItemProperties(product),quantity:1,sections:"cart-drawer"})});if(response.ok){const cart=await response.json();button.querySelector(".button__label").textContent=this.#config.strings.quickViewAddedToCart,this.#callbacks.sendConversionEvent(button),document.dispatchEvent(new CustomEvent("cart:refresh",{detail:{sections:cart.sections}})),window.setTimeout(()=>this.close(),400)}}catch{}finally{button.removeAttribute("aria-busy")}}}#cartAddUrl(){const root=this.#config.market?.rootUrl||window.Shopify?.routes?.root||"/";return`${String(root).replace(/\/+$/,"")}/cart/add.js`}scrollGallery(){this.#splide?.go(">")}async#render(product){const container=this.#root.querySelector("[data-quick-view-content]");if(!container)return;const swatches=await this.#swatches(product),gallery=this.#galleryMarkup(product);this.#destroyGallery(),container.innerHTML=`
2      ${gallery}
3
4      <div class="quick-view__desktop-content">
5        ${this.#detailsMarkup(product)}
6        ${this.#swatchesMarkup(product,swatches)}
7      </div>
8
9      <div class="quick-view__footer">
10        ${this.#sizesMarkup(product)}
11        <div class="quick-view__actions">
12          ${this.#buttonMarkup(product)}
13        </div>
14      </div>
15    `,await this.#mountGallery()}async#mountGallery(){const carousel=this.#root.querySelector("[data-quick-view-gallery]");if(!carousel)return;const{default:Splide}=await import("@splidejs/splide");carousel.isConnected&&(this.#splide=new Splide(carousel,{arrows:!1,autoWidth:!0,drag:!0,gap:"0.875rem",pagination:!1,type:"slide"}),this.#splide.mount())}#destroyGallery(){this.#splide?.destroy(),this.#splide=null}#showOverlay(overlay,source){typeof overlay.showPopover=="function"&&!overlay.matches(":popover-open")&&overlay.showPopover({source}),overlay.classList.add("is-open"),document.body.style.overflow="hidden"}#detailsMarkup(product){const titleId=`quick-view-title-${this.#root.dataset.sectionId||"collection"}`;return`
16      <div class="quick-view__details">
17        <p id="${this.#escapeHtml(titleId)}" class="quick-view__title text-body-sm">
18          ${this.#escapeHtml(product.title||this.#config.strings.loading||"")}
19        </p>
20        ${this.#priceMarkup(product)}
21      </div>
22    `}#priceMarkup(product){const price=product.price?.amount||0,compareAtPrice=product.compareAtPrice?.amount||null,onSale=compareAtPrice&&price<compareAtPrice;return`
23      <p class="product-prices quick-view__prices text-body-sm">
24        ${onSale?`<span class="product-prices__compare-at-price">${this.#callbacks.formatMoney(compareAtPrice)}</span>`:""}
25        <span class="product-prices__price ${onSale?"product-prices__price--on-sale":""}">${this.#callbacks.formatMoney(price)}</span>
26        ${product.available===!1?`<span class="product-prices__sold-out">${this.#escapeHtml(this.#config.strings.soldOut||"")}</span>`:""}
27      </p>
28    `}#galleryMarkup(product){const images=this.#images(product);return images.length?`
29      <div class="quick-view__gallery">
30        <div class="quick-view__carousel splide" data-quick-view-gallery aria-label="${this.#escapeHtml(product.title||"")}">
31          <div class="quick-view__track splide__track">
32            <ul class="quick-view__list splide__list">
33            ${images.map(image=>`
34                <li class="quick-view__slide splide__slide">
35                  ${this.#imageMarkup(image,product.title,600)}
36                </li>
37              `).join("")}
38            </ul>
39          </div>
40          ${images.length>2?`<button class="quick-view__gallery-arrow" type="button" data-quick-view-arrow aria-label="${this.#escapeHtml(this.#config.strings.next||"Next")}">${this.#icon("chevron-right")}</button>`:""}
41        </div>
42      </div>
43    `:""}#imageMarkup(image,title,width){return`
44      <img
45        class="quick-view__image"
46        src="${this.#escapeHtml(imageUrl(image,width))}"
47        alt="${this.#escapeHtml(image.alt||title||"")}"
48        loading="lazy"
49        decoding="async"
50        ${image.width?`width="${this.#escapeHtml(image.width)}"`:""}
51        ${image.height?`height="${this.#escapeHtml(image.height)}"`:""}
52      >
53    `}#images(product){const images=(product.images||[]).filter(image=>!image.alt?.includes("alt_landing_image"));return images.length?images:product.images||[]}async#swatches(product){const familyTag=this.#callbacks.familyTag(product);if(!familyTag)return this.#uniqueProducts([product]).filter(item=>metafieldValue(item,"swatch_code"));const relatedProducts=(await this.#callbacks.fetchRelatedProductsBatch([familyTag])).get(familyTag)||[],colourProducts=this.#callbacks.filterColourProducts(product,relatedProducts);return this.#uniqueProducts([...colourProducts,product]).filter(item=>metafieldValue(item,"swatch_code")).slice(0,18)}#swatchesMarkup(product,swatches){return swatches.length?`
54      <div class="quick-view__colour-swatches">
55        ${swatches.map(swatch=>this.#swatchMarkup(swatch,product)).join("")}
56      </div>
57    `:""}#swatchMarkup(swatch,product){const color=metafieldValue(swatch,"swatch_code")||"#ffffff";return`
58      <button
59        class="quick-view__swatch ${this.#isSameProduct(swatch,product)?"is-active":""} ${isWhiteSwatch(color)?"quick-view__swatch--white":""}"
60        type="button"
61        data-quick-view-swatch
62        data-product='${this.#escapeAttribute(JSON.stringify(swatch))}'
63        aria-label="${this.#escapeHtml(swatch.title)}"
64      >
65        <span class="quick-view__swatch-inner" style="--swatch-color: ${this.#escapeHtml(color)}"></span>
66      </button>
67    `}#sizesMarkup(product){const variants=product.variants||[];return variants.length<=1?"":`
68      <div class="quick-view__sizes">
69        <div class="quick-view__size-content">
70          ${variants.map(variant=>this.#sizeMarkup(variant)).join("")}
71        </div>
72      </div>
73    `}#sizeMarkup(variant){const id=numericId(variant.id),active=String(id)===String(this.#variantId||""),disabled=variant.available===!1;return`
74      <button
75        class="quick-view__size text-body-sm ${active?"is-active":""}"
76        type="button"
77        data-quick-view-size
78        data-variant-id="${this.#escapeHtml(id)}"
79        ${disabled?"disabled":""}
80      >
81        ${this.#escapeHtml(variantLabel(variant))}
82      </button>
83    `}#buttonMarkup(product){const canAdd=!!this.#selectedVariant(product)?.available,label=canAdd?this.#config.strings.quickViewAddToCart:this.#config.strings.quickViewSelectSize;return`
84      <button
85        class="button button--block ${canAdd?"":"button--no-icon"} quick-view__add-to-bag"
86        type="button"
87        data-quick-view-add
88        data-object-id="${this.#escapeHtml(product.objectID||product.id)}"
89        data-query-id="${this.#escapeHtml(product.__queryID||"")}"
90        ${canAdd?"":"disabled"}
91      >
92        <span class="button__label">${this.#escapeHtml(label)}</span>
93        ${canAdd?`<span class="button__icon">${this.#icon("bag")}</span>`:""}
94      </button>
95    `}#mergeProduct(product,productJson){if(!productJson)return product;const variants=productJson.variants?.length?productJson.variants:product.variants;return{...product,handle:productJson.handle||product.handle,id:productJson.id||product.id,title:productJson.title||product.title,url:product.url||productJson.url,variants:this.#applySizeStock(variants,product.sizeStock)}}#applySizeStock(variants,sizeStock){return sizeStock?(variants||[]).map(variant=>{const stock=sizeStock[variantLabel(variant)];return stock===void 0?variant:{...variant,available:stock!==0}}):variants||[]}#defaultVariantId(product){const variants=product.variants||[];return variants.length===1?numericId(variants[0].id):null}#selectedVariant(product){if(!product)return null;const variants=product.variants||[];return variants.length===1?variants[0]:variants.find(variant=>numericId(variant.id)===String(this.#variantId||""))}#lineItemProperties(product){const swatchName=metafieldValue(product,"swatch_name"),memberDiscount=metafieldValue(product,"member_discount_percentage"),properties=hiddenSaleLineItemProperties(product.tags);return swatchName&&(properties.Colour=swatchName),this.#config.memberPricing?.isCustomer&&Number(memberDiscount)>0&&(properties.__member_discount_percentage=memberDiscount,properties.__is_eagle_club_member=!0),properties}#uniqueProducts(products){const seen=new Set;return products.filter(product=>{const key=String(product?.id||product?.handle||"");return!key||seen.has(key)?!1:(seen.add(key),!0)})}#isSameProduct(productA,productB){return isSameProduct(productA,productB)}#overlay(){return this.#root.querySelector("[data-quick-view-overlay]")}#icon(name){return this.#icons[name]||""}#parseJson(value){return parseJson(value)}#escapeHtml(value){return escapeHtml(value)}#escapeAttribute(value){return escapeAttribute(value)}}
96//# sourceMappingURL=/cdn/shop/t/458/assets/algolia-product-card-quick-view.js.map?v=182558789341924908031788364384

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.