1(function(){const s=document.createElement("style");s.textContent=` 2 .popup-quick-view__gallery.qv-gallery--loading { position: relative; max-height: 400px; overflow: hidden; } 3 .popup-quick-view__gallery.qv-gallery--loading > * { visibility: hidden; } 4 .popup-quick-view__gallery.qv-gallery--loading::before { 5 content: ''; position: absolute; top: 50%; left: 50%; 6 transform: translate(-50%, -50%); 7 width: 30px; height: 30px; 8 border: 2px solid rgba(0,0,0,0.15); border-top-color: #333; border-radius: 50%; 9 z-index: 6; animation: qv-spin 0.65s linear infinite; 10 } 11 @keyframes qv-spin { to { transform: translate(-50%, -50%) rotate(360deg); } } 12 `,document.head.appendChild(s)})();class QuickViewModal extends HTMLElement{constructor(){super(),this.isOpen=!1,this.productHandle="",this.quickBuyButtons=document.querySelectorAll("a[data-button-quick-view]"),this.assignEventButtons(),this.render(),this.addEventListeners()}assignEventButtons(){document.addEventListener("click",event=>{const btn=event.target.closest("[data-button-quick-view]");if(!btn)return;const handle=btn.getAttribute("data-handle");handle&&(event.preventDefault(),event.stopPropagation(),event.stopImmediatePropagation(),this.open(handle))},!0),document.addEventListener("mouseover",event=>{const button=event.target.closest("a[data-button-quick-view]");if(button){const handle=button.getAttribute("data-handle");handle&&this.prefetch(handle);return}const swatch=event.target.closest("a[data-swatch][product-handle]");if(swatch){const handle=swatch.getAttribute("product-handle");handle&&this.prefetch(handle)}}),document.addEventListener("click",event=>{const button=event.target.closest("a[data-button-quick-view]");if(!button)return;event.preventDefault(),event.stopPropagation(),event.stopImmediatePropagation();const handle=button.getAttribute("data-handle");this.open(handle)})}prefetch(handle){if(!handle||(this._prefetchCache||(this._prefetchCache=new Map),this._prefetchCache.has(handle)))return;const promise=fetch(`/products/${handle}?section_id=api-quickview`).then(r=>r.ok?r.text():Promise.reject(r.status)).catch(()=>{this._prefetchCache.delete(handle)});this._prefetchCache.set(handle,promise)}render(){this.innerHTML=` 13 <div class="quick-view-overlay" id="quick-view-overlay"> 14 <div class="quick-view-modal-wrapper"> 15 <button class="quick-view-close-button" id="quick-view-close-button">×</button> 16 <div class="quick-view-modal-content" id="quick-view-modal-content"> 17 <div class="quick-view-loading"></div> 18 </div> 19 </div> 20 </div> 21 `}addEventListeners(){this.querySelector("#quick-view-close-button").addEventListener("click",()=>this.close());const overlay=this.querySelector("#quick-view-overlay");overlay.addEventListener("click",event=>{event.target===overlay&&this.close()}),document.addEventListener("keydown",event=>{event.key==="Escape"&&this.isOpen&&this.close()}),document.addEventListener("click",event=>{const button=event.target.closest("[handle]");if(button){const handle=button.getAttribute("handle");handle&&(event.preventDefault(),this.open(handle))}})}open(handle){if(!handle)return;this.productHandle=handle,this.isOpen=!0,this.querySelector("#quick-view-overlay").classList.add("active"),document.body.style.overflow="hidden",this.loadProductContent(),this.onModalOpened()}openWithEvent(event){const parent=event.target.closest("[data-button-quick-view]");if(!parent)return;const handle=parent.getAttribute("data-handle");this.open(handle)}destroyFlickity(){if(this.flickity){try{this.flickity.destroy()}catch{}this.flickity=null}}close(){this.isOpen=!1,this.destroyFlickity();const overlay=this.querySelector("#quick-view-overlay");overlay&&overlay.classList.remove("active"),document.body.style.overflow="",document.dispatchEvent(new CustomEvent("theme:quick-view:close",{detail:{},bubbles:!0}))}async loadProductContent(){this._loadGen=(this._loadGen||0)+1;const gen=this._loadGen;this.destroyFlickity();const modalContent=this.querySelector(".quick-view-modal-wrapper");try{const existingGallery=modalContent.querySelector(".popup-quick-view__gallery");existingGallery?existingGallery.classList.add("qv-gallery--loading"):modalContent.innerHTML='<div class="quick-view-loading"></div>';const html=await(this._prefetchCache?.get(this.productHandle)||fetch(`/
21products/${this.productHandle}?section_id=api-quickview`).then(r=>{if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);return r.text()}));if(gen!==this._loadGen)return;modalContent.innerHTML=html;const gallery=modalContent.querySelector(".popup-quick-view__gallery");gallery&&gallery.classList.add("qv-gallery--loading"),this.lastClickedHandle=this.productHandle;const swatchToActivate=this.querySelector(`a[data-swatch][product-handle="${this.lastClickedHandle}"]`);swatchToActivate&&swatchToActivate.classList.add("is-active"),typeof Drawer=="function"&&new Drawer(document);const productJsonEl=modalContent.querySelector("[data-product-json]");if(!productJsonEl){console.error("Quick view: Missing product JSON");return}let productData;try{productData=JSON.parse(productJsonEl.textContent)}catch(e){console.error("Quick View: Invalid product JSON format",e);return}this.atsInventoryMap&&(productData.variants.forEach(variant=>{const atsQty=this.atsInventoryMap[variant.id];typeof atsQty=="number"&&(variant.available=atsQty>0)}),productJsonEl.textContent=JSON.stringify(productData));const variantIds=productData.variants.map(v=>v.id).join(",");if(window.isPro===!0||document.body.getAttribute("data-pro")==="true")fetch(`https://api.geostock.app/shop/toadandco.myshopify.com/multi_variant_locations/${variantIds}`).then(res=>res.json()).then(atsData=>{this.atsInventoryMap={}
21,productData.variants.forEach(variant=>{const stockQty=atsData[variant.id]?.locations?.find(loc=>loc.name==="ATS")?.stock??0;this.atsInventoryMap[variant.id]=stockQty;const inputSelectors=modalContent.querySelectorAll("[data-single-option-selector]");if(!inputSelectors.length){console.warn("[QuickViewModal] No variant inputs found.");return}inputSelectors.forEach(input=>{const indexAttr=input.dataset.index;if(!indexAttr||!indexAttr.includes("option"))return;const index=parseInt(indexAttr.replace("option",""),10)-1,value=input.value;if(variant.options&&variant.options[index]===value){const radioButton=input.closest(".radio__button");radioButton&&(stockQty<=0?radioButton.classList.add("sold-out"):radioButton.classList.remove("sold-out"))}})})}).then(()=>{if(gen!==this._loadGen)return;this.initProductFunctionality();const g=gen,gal=modalContent.querySelector(".popup-quick-view__gallery");requestAnimationFrame(()=>{requestAnimationFrame(()=>{g===this._loadGen&&this.initFlickity(gal)})})}).catch(error=>{if(console.error("Error fetching ATS stock for quick view:",error),gen!==this._loadGen)return;this.initProductFunctionality();const g=gen,gal=modalContent.querySelector(".popup-quick-view__gallery");requestAnimationFrame(()=>{requestAnimationFrame(()=>{g===this._loadGen&&this.initFlickity(gal)})})});else{this.initProductFunctionality();const g=gen,gal=modalContent.querySelector(".popup-quick-view__gallery");requestAnimationFrame(()=>{requestAnimationFrame(()=>{g===this._loadGen&&this.initFlickity(gal)})})}}catch(error){console.error("Error loading product content:",error),modalContent.innerHTML=`<div style="text-align: center; padding: 20px;"> 22 <p>Sorry, we couldn't load the product content.</p> 23 <p>Please try again later.</p> 24 </div>`}}onModalOpened(){setTimeout(()=>{const container=document.querySelector(".popup-quick-view__body");if(!container)return;const swatchValue=container.querySelector("fieldset.siblings")?.querySelector("a.is-active")?.dataset?.swatch,label=container.querySelector("#quickview-modal-color-name");label&&swatchValue&&(label.textContent=swatchValue)},800)}resetContent(){const modalContent=this.querySelector("#quick-view-modal-content");modalContent&&(modalContent.innerHTML='<div class="quick-view-loading"></div>'),this.productHandle=""}initProductFunctionality(){this.querySelector(".popup-quick-view__close")?.addEventListener("click",e=>{e.preventDefault(),this.close()}),this.initSwatches(),this.addEventsToInputs(),this.assignSubmitEventToAddToCart(),this.checkPrices(),this.updateSelectedVariant(),this.addSizeChartToggleListener()}_calcPricingProperties(variantId){const productJsonEl=this.querySelector("[data-product-json]");if(!productJsonEl)return{};let product;try{product=JSON.parse(productJsonEl.textContent)}catch{return{}}const variant=product.variants.find(v=>v.id===parseInt(variantId,10));if(!variant)return{};const msrp=variant.compare_at_price>0?variant.compare_at_price:variant.price,tags=product.tags||[],proSetPrice=window.TC_proSetPriceFrom?window.TC_proSetPriceFrom(this):0;let net=variant.price;if(window.calculatePriceFromTags){const result=window.calculatePriceFromTags(variant.price,tags,{},msrp,0,null,proSetPrice);net=Math.min(result.calculatedPrice,variant.price)}const fmt=cents=>(cents/100).toFixed(2),cur=window.TC_propCurrency?window.TC_propCurrency():window.Shopify?.currency?.active||"USD";return{_msrp:fmt(msrp),_net:fmt(net),_cur:cur}}_appendPricingProperties(formData){const props=this._calcPricingProperties(formData.get("id"));for(const[key,value]of Object.entries(props))formData.append(`properties[${key}]`,value)}assignSubmitEventToAddToCart(){this.__delegatedSubmitHandlerBound||(this.__delegatedSubmitHandlerBound=!0,this.addEventListener("click",e=>{const btn=e.target.closest(".btn--submit");if(!btn)return;const form=this.querySelector('form[action="/cart/add"]');if(!form||btn.dataset.notifyClickLock==="true")return;if(btn.dataset.notifyClickLock="true",setTimeout(()=>{btn.dataset.notifyClickLock="false"},800),btn.hasAttribute("data-bis-notification-popup")){e.preventDefault(),e.stopPropagation();return}e.preventDefault(),e.stopPropagation();const formData=new FormData(form);this._appendPricingProperties(formData),btn.classList.add("loading"),btn.disabled=!0,fetch("/cart/add.js",{method:"POST",headers:{Accept:"application/json"},body:formData}).then(response=>response.json()).then(data=>{btn.classList.remove("loading"),btn.disabled=!1,typeof window.TC_openCartDrawer=="function"?(window.TC_openCartDrawer(),this.close()):window.cart&&typeof window.cart.refreshDrawer=="function"&&(window.cart.refreshDrawer(),this.close())}).catch(error=>{btn.classList.remove("loading"),btn.disabled=!1,alert("Could not add to cart. Please try again.")})}),this.addEventListener("submit",e=>{const form=e.target.closest('form[action="/cart/add"]');if(!form)return;e.preventDefault(),e.stopPropagation();const submitBtn=form.querySelector(".btn--submit");
24if(submitBtn?.hasAttribute("data-notification-popup"))return;const formData=new FormData(form);if(this._appendPricingProperties(formData),window.cart&&typeof window.cart.addToCart=="function"){if(window.cart.button=submitBtn,window.cart.form=form,window.cart.formWrapper=submitBtn?.closest("[data-form-wrapper]")||submitBtn?.closest("form"),!formData.get("id")){console.warn("[QuickView] Missing variant id for add to cart");return}window.cart.addToCart(formData),setTimeout(()=>{window.cart.openCartDrawer?.()},250),this.close();return}fetch("/cart/add.js",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:formData.get("id"),quantity:formData.get("quantity")||1,properties:this._calcPricingProperties(formData.get("id"))})}).then(()=>{window.cart?.refreshDrawer&&window.cart.refreshDrawer(),this.close()}).catch(err=>console.error("[QuickView] add to cart failed",err))}))}checkPrices(){const priceWrapper=this.querySelector(".product__price[data-price-wrapper]");if(!priceWrapper)return;const regularPriceEl=priceWrapper.querySelector("[data-product-price]"),comparePriceEl=priceWrapper.querySelector("[data-compare-price]");regularPriceEl&&comparePriceEl&®ularPriceEl.textContent.trim()===comparePriceEl.textContent.trim()&&comparePriceEl.classList.add("hidden")}addEventsToInputs(){this.querySelectorAll("input[type='radio'], input[type='checkbox'], select").forEach(input=>{input.addEventListener("change",()=>this.updateSelectedVariant())})}updateSelectedVariant(){const form=this.querySelector('form[action="/cart/add"]');if(!form)return;const options=[];form.querySelectorAll("[data-single-option-selector]").forEach(el=>{const value=el.type==="radio"?el.checked?el.value:null:el.value;value!==null&&options.push(value)});const productJson=this.querySelector("[data-product-json]");if(!productJson)return;const product=JSON.parse(productJson.textContent),matchedVariant=product.variants.find(variant=>variant.options.every((opt,idx)=>opt===options[idx]));if(!matchedVariant)return;const shopifyPriceEl=this.querySelector("shopify-price");if(shopifyPriceEl&&typeof shopifyPriceEl.updateState=="function"){const priceScriptEl=this.querySelector("[shopify-price-json]");let priceData=null;if(priceScriptEl)try{priceData=JSON.parse(priceScriptEl.textContent)}catch{}if(priceData){const msrp=matchedVariant.compare_at_price>0?matchedVariant.compare_at_price:matchedVariant.price;let priceAfterDiscounts=matchedVariant.price;if(window.calculatePriceFromTags){const tags=priceData.product&&priceData.product.tags||[];priceAfterDiscounts=window.calculatePriceFromTags(matchedVariant.price,tags,{},msrp,priceData.discountPct||0,matchedVariant.price,Number(priceData.proSetPrice)||0).calculatedPrice}console.log("[QV] updateState call \u2014 variant.price:",matchedVariant.price,"| variant.compare_at_price:",matchedVariant.compare_at_price,"| product.compare_at_price:",priceData.product?.compare_at_price,"| priceAfterDiscounts:",priceAfterDiscounts),shopifyPriceEl.updateState({currentVariant:matchedVariant,product:priceData.product,priceAfterDiscounts})}}const priceWrapper=this.querySelector(".product__price[data-price-wrapper]");if(priceWrapper&&!shopifyPriceEl){const basePrice=matchedVariant.price||0,variantCompare=matchedVariant.compare_at_price||0,productC
24ompare=product.compare_at_price||0,isProExcluded=(Array.isArray(product.tags)?product.tags:(product.tags||"").split(",").map(t=>t.trim())).some(tag=>typeof tag=="string"&&tag.trim()==="ProExclusion");let finalPrice=basePrice;if(window.isPro===!0&&!isProExcluded){const setPrice=parseFloat(priceWrapper.dataset.proSetPrice)||0;setPrice>0?finalPrice=setPrice:finalPrice=variantCompare*(100-(window.proDiscount||0))/100}else{const markdownPct=parseFloat(priceWrapper.dataset.discountPct)||0;if(markdownPct>0&&markdownPct<100&&window.roundMarkdownTo99){const target=window.roundMarkdownTo99(basePrice*(1-markdownPct/100));target>0&&target<basePrice&&(finalPrice=target)}}const comparePrice=variantCompare>finalPrice?variantCompare:productCompare>finalPrice?productCompare:basePrice>finalPrice?basePrice:0;console.log("[QV] DOM price update \u2014 basePrice:",basePrice,"| finalPrice:",finalPrice,"| comparePrice:",comparePrice),comparePrice>0?priceWrapper.innerHTML=` 25 <span class="discounted-price product-grid-item__price-new price" aria-label="sale price">${Shopify.formatMoney(finalPrice)}</span> 26 <span class="original-price product-grid-item__price-new price" aria-label="original price" style="text-decoration: line-through;">${Shopify.formatMoney(comparePrice)}</span> 27 `:priceWrapper.innerHTML=`<span class="price">${Shopify.formatMoney(finalPrice)}</span>`}const atcButton=form.querySelector(".btn--submit"),ctaTextEl=this.querySelector("[data-add-to-cart-text]");if(!atcButton||!ctaTextEl)return;const showBISModal=atcButton.hasAttribute("data-show-bis"),idInput=form.querySelector('input[name="id"]');if(idInput&&(idInput.value=matchedVariant.id),document.dispatchEvent(new CustomEvent("theme:quick-view-variant:change",{detail:{variant:matchedVariant},bubbles:!0})),(window.isPro||document.body.getAttribute("data-pro")==="true")&&this.atsInventoryMap){const atsStock=this.atsInventoryMap[matchedVariant.id];typeof atsStock=="number"&&(matchedVariant.available=atsStock>0)}matchedVariant.available?(ctaTextEl.textContent="Add to Cart",atcButton.disabled=!1,atcButton.type="submit",atcButton.classList.remove("btn--primary","btn--solid","open-modal-button"),atcButton.innerHTML=` 28 <span data-add-to-cart-text="">Add to Cart</span> 29 <em class="loader loader--line"><em class="loader-indeterminate"></em></em> 30 `,showBISModal&&atcButton.removeAttribute("data-bis-notification-popup")):(ctaTextEl.textContent="Sold Out - Notify Me",atcButton.disabled=!1,atcButton.type="button",atcButton.classList.add("btn--primary","btn--solid","open-modal-button"),atcButton.innerHTML=` 31 <span data-add-to-cart-text="">Sold Out - Notify Me</span> 32 <em class="loader loader--line"><em class="loader-indeterminate"></em></em> 33 `,showBISModal&&atcButton.setAttribute("data-bis-notification-popup",!0),this.submitButton=this.querySelector(".btn--submit"));const quickViewItem=this.querySelector(".popup-quick-view__item");quickViewItem&&(matchedVariant.available?quickViewItem.classList.remove("variant--soldout"):quickViewItem.classList.add("variant--soldout")),this.markSoldOutVariants(product)}buildNotificationMarkup(variant){const productTitle=this.querySelector(".product__title")?.textContent||"Product",optionTitle=variant.title||"";return` 34 <div class='product__notification' data-notification> 35 <h2 class='product__notification__title'>${productTitle}</h2> 36 <p class='product__notification__subtitle'>${optionTitle}</p> 37 <form method='post' action='/contact#NotificationForm-${variant.id}' id='NotificationForm-${variant.id}' accept-charset='UTF-8' class='contact-form' data-notification-form> 38 <input type='hidden' name='form_type' value='customer' /> 39 <input type='hidden' name='utf8' value='\u2713' /> 40 <div class='product__notification__message'> 41 <p>Your email has been received.</p> 42 </div> 43 <div class='product__notification__form'> 44 <label for='Email-${variant.id}'>
44Please enter your email and we will let you know when your selected item becomes available.</label> 45 <input type='hidden' name='contact[tags]' value='newsletter, out-of-stock-notification--${productTitle}'/> 46 <input type='hidden' name='contact[first_name]' value='Newsletter' /> 47 <input type='hidden' name='contact[last_name]' value='Subscriber' /> 48 <div class='input-group input-group--inline'> 49 <div class='input-group__item'> 50 <input type='email' placeholder='Your email' name='contact[email]' id='Email-${variant.id}' class='input-group__field input-group__field--email' aria-label='Your email' autocorrect='off' autocapitalize='off' required data-popup-input> 51 </div> 52 <div class='input-group__item--btn'> 53 <button type='submit' name='subscribe' id='SubscribeSubmit-${variant.id}' class='btn btn--primary btn--solid'> 54 <span data-notification-button-text>Notify Me</span> 55 </button> 56 </div> 57 </div> 58 </div> 59 </form> 60 <button title='Close (Esc)' class='product__notification__close' data-popup-close> 61 <svg aria-hidden='true' focusable='false' role='presentation' class='icon icon-close' viewBox='0 0 192 192'><path d='M150 42 42 150M150 150 42 42' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round'/></svg> 62 </button> 63 </div> 64 `.trim()}showNotificationPopup(content){const popupWrapper=document.createElement("div");popupWrapper.innerHTML=content;const popup=popupWrapper.firstElementChild;document.body.appendChild(popup),popup.querySelector("[data-popup-close]")?.addEventListener("click",()=>popup.remove())}addSizeChartToggleListener(){const sizeChartButton=this.querySelector('[data-drawer-toggle][aria-controls^="size-chart"]');sizeChartButton&&sizeChartButton.addEventListener("click",e=>{e.preventDefault();const drawerId=sizeChartButton.getAttribute("aria-controls"),drawer=document.getElementById(drawerId);if(!drawer)return;drawer.classList.add("alt","is-open"),drawer.setAttribute("aria-hidden","false"),drawer.setAttribute("tabindex","-1"),sizeChartButton.setAttribute("aria-expanded","true"),document.dispatchEvent(new CustomEvent("theme:scroll:lock",{bubbles:!0,detail:drawer}));const closeButton=drawer.querySelector("[data-drawer-toggle]");closeButton&&closeButton.addEventListener("click",ev=>{ev.preventDefault(),drawer.classList.remove("is-open"),drawer.setAttribute("aria-hidden","true"),drawer.removeAttribute("tabindex"),sizeChartButton.setAttribute("aria-expanded","false"),document.dispatchEvent(new CustomEvent("theme:scroll:unlock",{bubbles:!0}))}),typeof Drawer=="function"&&new Drawer(document)})}markSoldOutVariants(product){this.querySelectorAll("[data-single-option-selector]").forEach(input=>{const value=input.value,optionIndex=parseInt(input.getAttribute("data-index").replace("option",""))-1,available=product.variants.some(variant=>variant.options[optionIndex]===value&&variant.available),label=this.querySelector(`label[for="${input.id}"]`);label&&label.classList.toggle("sold-out",!available)})}initSwatches(){const swatches=this.querySelectorAll("a[data-swatch]");swatches.length&&swatches.forEach(swatch=>{swatch.addEventListener("click",event=>{event.preventDefault(),event.stopPropagation();const selectedHandle=swatch.getAttribute("product-handle");this.open(selectedHandle)})})}initFlickity(gallery){const slider=this.querySelector("[data-product-single-media-slider]"),reveal=()=>{gallery&&gallery.classList.remove("qv-gallery--loading")};if(!slider){reveal();return}if(typeof themeVendor?.Flickity?.data=="function"){const existing=themeVendor.Flickity.data(slider);if(existing)try{existing.destroy()}catch{}}const doInit=()=>{try{this.flickity=new themeVendor.Flickity(slider,{draggable:!0,contain:!0,wrapAround:!0,cellAlign:"left",pageDots:!1,prevNextButtons:!0,adaptiveHeight:!1}),this.flickity.resize()}catch(e){console.error("Error initializing Flickity:",e)}reveal()};typeof imagesLoaded=="function"?imagesLoaded(slider,doInit):doInit()}
64connectedCallback(){console.log("QuickViewModal connected to the DOM")}disconnectedCallback(){console.log("QuickViewModal removed from the DOM")}}customElements.define("quick-view-modal",QuickViewModal),typeof NotificationPopup<"u"&&(window.NotificationPopup=NotificationPopup); 65//# sourceMappingURL=/cdn/shop/t/158/assets/quick-view-cart.js.map?v=134944613901475545961787594867
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.