1/** 2 * Convention-based Add-to-Cart CTA. 3 * 4 * Any HTML element with a data-shopify-add-to-cart attribute becomes a 5 * functional add-to-cart button. Uses event delegation so dynamically 6 * injected elements (chatbot, GTM, ECM) work without re-initialization. 7 * 8 * Usage: 9 * <button data-shopify-add-to-cart="gid://shopify/ProductVariant/12345">Buy Now</button> 10 * <button data-shopify-add-to-cart="gid://shopify/ProductVariant/12345" 11 * data-shopify-selling-plan="gid://shopify/SellingPlan/67890">Subscribe</button> 12 */ 13 14window.ShopifyCTA = (function () { 15 'use strict'; 16 17 const SELECTOR = '[data-shopify-add-to-cart]'; 18 const LOADING_CLASS = 'shopify-cta-loading'; 19 20 function init() { 21 document.body.addEventListener('click', handleClick); 22 } 23 24 async function handleClick(event) { 25 const ctaElement = event.target.closest(SELECTOR); 26 if (!ctaElement) { 27 return; 28 } 29 30 // Prevent default behavior (e.g., if used on an <a> tag). 31 event.preventDefault(); 32 33 // Ignore clicks while a request is in flight. 34 if (ctaElement.classList.contains(LOADING_CLASS)) { 35 return; 36 } 37 38 const variantId = ctaElement.getAttribute('data-shopify-add-to-cart'); 39 const sellingPlanId = ctaElement.getAttribute('data-shopify-selling-plan') || null; 40 41 if (!variantId) { 42 return; 43 } 44 45 ctaElement.classList.add(LOADING_CLASS); 46 ctaElement.disabled = true; 47 48 try { 49 await window.ShopifyCart.addToCart(variantId, 1, sellingPlanId); 50 } catch (error) { 51 console.error('ShopifyCTA: Failed to add to cart', error); 52 } finally { 53 ctaElement.classList.remove(LOADING_CLASS); 54 ctaElement.disabled = false; 55 } 56 } 57 58 return { init }; 59})();
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.