1(function(){"use strict";const CONFIG={MAX_LOAD_ATTEMPTS:50,POLL_INTERVAL:100,MOBILE_BREAKPOINT:768,TITLE_TEXT:"Make Your Jewelry Perfect",IMAGE_FALLBACK_BG:"#F9F6EC",MIN_VALIDATION_ATTEMPTS:3};function detectAddonSystem(){const boldOptions=document.querySelector(".bold_options"),boldCheckboxes=boldOptions?.querySelectorAll(".bold_option_checkbox"),nativeOptions=document.querySelector("#fieldset-section-2.fieldset"),nativeCheckboxes=nativeOptions?.querySelectorAll('input.product-custom-option[type="checkbox"]'),boldHasCheckboxes=boldCheckboxes&&boldCheckboxes.length>0;return nativeCheckboxes&&nativeCheckboxes.length>0?{type:"native",container:nativeOptions}:boldHasCheckboxes?{type:"bold",container:boldOptions}:{type:"none",container:null}}function validateBoldOptionsComplete(container){if(!container.classList.contains("bold_options_loaded"))return!1;const checkboxes=container.querySelectorAll(".bold_option_checkbox");if(checkboxes.length===0)return!1;let foundValidAddon=!1;for(const element of checkboxes){const handle=element.querySelector('input[type="checkbox"]')?.getAttribute("data-product-handle"),title=element.querySelector(".bold_option_title")?.textContent.trim(),price=element.querySelector(".bold_option_value_price")?.textContent.trim();if(handle){if(!title||!price)return!1;foundValidAddon=!0}}return foundValidAddon}function validateNativeOptionsComplete(container){const checkboxes=container.querySelectorAll('input.product-custom-option[type="checkbox"]');if(checkboxes.length===0)return!1;let foundValidAddon=!1;for(const checkbox of checkboxes){const fieldChoice=checkbox.closest(".field.choice");if(!fieldChoice)continue;const label=fieldChoice.querySelector("label.label");if(!label)continue;const titleSpan=label.querySelector("span:first-child"),priceNotice=label.querySelector(".price-notice"),productSku=checkbox.getAttribute("product-sku"),hasTitle=titleSpan?.textContent.trim(),hasPrice=priceNotice?.textContent.trim()||checkbox.getAttribute("price");hasTitle&&hasPrice&&productSku&&(foundValidAddon=!0)}return foundValidAddon}function injectCustomCSS(){const style=document.createElement("style");style.id="nominal-addon-redesign-styles",style.textContent=` 2 .addon-checkbox-new { 3 -webkit-appearance: none; 4 -moz-appearance: none; 5 appearance: none; 6 width: 16px; 7 height: 16px; 8 border-radius: 2.5px; 9 border: 1px solid #767676; 10 background: #FFFFFF; 11 cursor: pointer; 12 margin: 0; 13 position: relative; 14 transition: all 0.2s ease; 15 } 16 17 .addon-checkbox-new:checked { 18 background-color: #000000 !important; 19 border-color: #000000 !important; 20 } 21 22 .addon-checkbox-new:checked::after { 23 content: ''; 24 position: absolute; 25 left: 5px; 26 top: 2px; 27 width: 4px; 28 height: 8px; 29 border: solid white; 30 border-width: 0 1.5px 1.5px 0; 31 transform: rotate(45deg); 32 } 33 34 .addon-card { 35 transition: opacity 0.2s ease; 36 } 37 38 .addon-card:hover { 39 opacity: 0.85; 40 } 41 42 /* Hide Bold Options total/summary */ 43 .bold_options .bold_option_total { 44 display: none !important; 45 } 46 47 /* Hide native options container and all child elements */ 48 #fieldset-section-2.fieldset.nominal-hidden, 49 #fieldset-section-2.fieldset.nominal-hidden * { 50 display: none !important; 51 visibility: hidden !important; 52 opacity: 0 !important; 53 height: 0 !important; 54 width: 0 !important; 55 margin: 0 !important; 56 padding: 0 !important; 57 overflow: hidden !important; 58 } 59 60 @media (max-width: ${CONFIG.MOBILE_BREAKPOINT}px) { 61 .nominal-addon-redesign { 62 width: 342px !important; 63 } 64 } 65 `,document.getElementById("nominal-addon-redesign-styles")||document.head.appendChild(style)}function waitForAddons(callback,maxAttempts=CONFIG.MAX_LOAD_ATTEMPTS){let done=!1;const STABILITY_MS=100,TIMEOUT_MS=maxAttempts*CONFIG.POLL_INTERVAL;let stabilityTimer=null;function tryValidate(){if(done)return;
65const system=detectAddonSystem();let isValid=!1;system.type==="bold"&&(isValid=validateBoldOptionsComplete(system.container)),system.type==="native"&&(isValid=validateNativeOptionsComplete(system.container)),isValid&&(done=!0,clearTimeout(stabilityTimer),clearTimeout(fallbackTimer),observer.disconnect(),console.log(`[Nominal A/B Test] ${system.type} system fully loaded and validated (mutation-driven)`),callback(system))}function scheduleValidate(){clearTimeout(stabilityTimer),stabilityTimer=setTimeout(tryValidate,STABILITY_MS)}const observer=new MutationObserver(scheduleValidate);observer.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["class"]});const fallbackTimer=setTimeout(()=>{done||(done=!0,observer.disconnect(),console.warn("[Nominal A/B Test] Add-ons did not load within expected time"))},TIMEOUT_MS);tryValidate()}function extractBoldAddons(boldContainer){const addons=[];return boldContainer.querySelectorAll(".bold_option_checkbox").forEach(element=>{const checkbox=element.querySelector('input[type="checkbox"]'),hiddenInput=element.querySelector('input[type="hidden"]');if(!checkbox)return;const productHandle=checkbox.getAttribute("data-product-handle"),title=element.querySelector(".bold_option_title")?.textContent.trim(),price=element.querySelector(".bold_option_value_price")?.textContent.trim(),tooltip=element.querySelector(".bold_tooltip")?.textContent.trim()||"",checkboxClass=checkbox.className,propertyName=hiddenInput?.name.replace("properties[","").replace("]","")||"";!productHandle||!price||addons.push({system:"bold",element,checkbox,hiddenInput,productHandle,productSku:null,title,price,tooltip,checkboxClass,propertyName,imageUrl:null,disabled:checkbox.disabled||!1})}),addons}function extractNativeAddons(nativeContainer){const addons=[];return nativeContainer.querySelectorAll('input.product-custom-option[type="checkbox"]').forEach(checkbox=>{const fieldChoice=checkbox.closest(".field.choice"),dynamicOption=checkbox.closest('[id^="dynamic_option_id_"]');if(!fieldChoice||!dynamicOption)return;const labelElement=fieldChoice.querySelector("label.label");if(!labelElement)return;const title=labelElement.querySelector("span:first-child")?.textContent.trim();let price=labelElement.querySelector(".price-notice")?.textContent.trim();if(!price){const priceAttr=checkbox.getAttribute("price");priceAttr&&(price=`+$${parseFloat(priceAttr).toFixed(0)}`)}const productSku=checkbox.getAttribute("product-sku"),disabled=checkbox.disabled||labelElement.textContent.includes("out of stock"),tooltip=dynamicOption.querySelector("label:first-child")?.textContent.trim()||"";!title||!price||addons.push({system:"native",element:fieldChoice,checkbox,hiddenInput:null,productHandle:null,productSku,title,price,tooltip:tooltip!==title?tooltip:"",checkboxClass:checkbox.className,propertyName:checkbox.name,imageUrl:null,disabled})}),addons}async function fetchProductImages(addons){const skuToHandleMap={"GIFT BOX":"nominal-gift-box","Chain-N-Ext-G":"chain-extension","JC-SPRY-W":"jewelry-cleaner-kit","RING GIFT BOX":"ring-gift-box","NECKLACE GIFT BOX":"necklace-gift-box","CUFF GIFT BOX":"cuff-gift-box"},promises=addons.map(async addon=>{if(addon.system==="bold"&&addon.productHandle)try{const response=await fetch(`/products/${addon.productHandle}.js`);if(!response.ok)throw new Error(`HTTP ${response.status}`);const productData=await response.json();addon.imageUrl=productData.featured_image||productData.images&&productData.images[0]||null}catch(error){console.warn(`[Nominal A/B Test] Failed to fetch image for ${addon.productHandle}:`,error),addon.imageUrl=null}if(addon.system==="native"&&addon.productSku)try{let handle=skuToHandleMap[addon.productSku];handle||(handle=addon.productSku.toLowerCase().replace(/\s+/g,"-"));const response=await fetch(`/products/${handle}.js`);if(!response.ok)throw new Error(`HTTP ${response.status}`);const productData=await response.json();addon.imageUrl=productData.featured_image||productData.images&&productData.images[0]||null}catch{addon.imageUrl=null}});return await Promise.all(promises),addons}function generateNewHTML(addons){let html=` 66 <div class="nominal-addon-redesign" style=" 67 display: flex; 68 flex-direction: column; 69 align-items: flex-start; 70 padding: 0; 71 gap: 12px; 72 width: ${window.innerWidth<=CONFIG.MOBILE_BREAKPOINT?"342px":"441px"}; 73 max-width: 100%; 74 margin-bottom: 20px; 75 "> 76 <div class="addon-title" style=" 77 font-family: 'Aktiv Grotesk Corp', 'Aktiv Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 78 font-style: normal; 79 font-weight: 500; 80 font-size: 12px; 81 line-height: 14px; 82 display: flex; 83 align-items: center; 84 text-transform: capitalize; 85 color: #000000; 86 "> 87 ${CONFIG.TITLE_TEXT} 88 </div> 89 `;return addons.forEach((addon,index)=>{const imageHTML=addon.imageUrl?`<img src="${addon.imageUrl}" alt="${addon.title}" style="width: 40px; height: 40px; object-fit: cover; background: ${CONFIG.IMAGE_FALLBACK_BG}; display: block;">`:`<div style="width: 40px; height: 40px; background: ${CONFIG.IMAGE_FALLBACK_BG};"></div>`,tooltipHTML=addon.tooltip?`<div class="addon-tooltip" style=" 90 position: relative; 91 width: 14px; 92 height: 14px; 93 flex-shrink: 0; 94 margin-left: 4px; 95 "> 96 <div class="tooltip-icon" style=" 97 width: 14px; 98 height: 14px; 99 border-radius: 50%; 100 border: 1px solid rgba(0, 0, 0, 0.4); 101 display: flex; 102 align-items: center; 103 justify-content: center; 104 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 105 font-size: 10px; 106 font-weight: 600; 107 color: rgba(0, 0, 0, 0.6); 108 cursor: help; 109 background: transparent; 110 ">i</div> 111 <div class="tooltip-content" style=" 112 display: none; 113 position: absolute; 114 bottom: calc(100% + 8px); 115 left: 50%; 116 transform: translateX(-50%); 117 background: #2d2d2d; 118 color: white; 119 padding: 8px 12px; 120 border-radius: 4px; 121 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 122 font-size: 11px; 123 line-height: 14px; 124 white-space: nowrap; 125 z-index: 1000; 126 pointer-events: none; 127 "> 128 ${addon.tooltip} 129 <div style=" 130 position: absolute; 131 top: 100%; 132 left: 50%; 133 transform: translateX(-50%); 134 width: 0; 135 height: 0; 136 border-left: 5px solid transparent; 137 border-right: 5px solid transparent; 138 border-top: 5px solid #2d2d2d; 139 "></div> 140 </div> 141 </div>`:"",priceText=addon.disabled&&!addon.price.includes("out of stock")?`${addon.price} (out of stock)`:addon.price,disabledAttr=addon.disabled?"disabled":"",curs
141orStyle=addon.disabled?"cursor: not-allowed;":"cursor: pointer;",opacityStyle=addon.disabled?"opacity: 0.5;":"";html+=` 142 <div class="addon-card" data-addon-index="${index}" style=" 143 display: flex; 144 flex-direction: row; 145 align-items: center; 146 padding: 0; 147 gap: 8px; 148 width: 100%; 149 height: 40px; 150 ${cursorStyle} 151 ${opacityStyle} 152 "> 153 <div class="addon-checkbox-wrapper" style=" 154 width: 16px; 155 height: 16px; 156 flex-shrink: 0; 157 "> 158 <input 159 type="checkbox" 160 class="addon-checkbox-new" 161 data-addon-index="${index}" 162 data-original-class="${addon.checkboxClass}" 163 aria-label="Select ${addon.title}" 164 ${disabledAttr} 165 /> 166 </div> 167 168 <div class="addon-image" style="flex-shrink: 0;"> 169 ${imageHTML} 170 </div> 171 172 <div class="addon-info" style=" 173 display: flex; 174 flex-direction: column; 175 justify-content: center; 176 align-items: flex-start; 177 padding: 0; 178 gap: 4px; 179 flex-grow: 1; 180 "> 181 <div style=" 182 display: flex; 183 align-items: center; 184 gap: 4px; 185 "> 186 <div class="addon-name" style=" 187 font-family: 'AktivGrotesk-Medium', 'Aktiv Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 188 font-style: normal; 189 font-weight: 400; 190 font-size: 14.4px; 191 line-height: 17px; 192 color: #000000; 193 "> 194 ${addon.title} 195 </div> 196 ${tooltipHTML} 197 </div> 198 <div class="addon-price" style=" 199 font-family: 'Aktiv Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 200 font-style: normal; 201 font-weight: 400; 202 font-size: 12px; 203 line-height: 15px; 204 color: rgba(0, 0, 0, 0.6); 205 "> 206 ${priceText} 207 </div> 208 </div> 209 </div> 210 `}),html+="</div>",html}function replaceUI(container,newHTML,addons,systemType){if(systemType==="bold"){addons.forEach(addon=>{addon.element.style.display="none"});const boldTotal=container.querySelector(".bold_option_total");boldTotal&&(boldTotal.style.display="none"),container.insertAdjacentHTML("afterend",newHTML)}else systemType==="native"&&(container.classList.add("nominal-hidden"),container.insertAdjacentHTML("afterend",newHTML));return document.querySelector(".nominal-addon-redesign")}function bindEventListeners(addons,newContainer){addons.forEach((addon,index)=>{const newCheckbox=newContainer.querySelector(`.addon-checkbox-new[data-addon-index="${index}"]`),cardElement=newContainer.querySelector(`.addon-card[data-addon-index="${index}"]`);if(!newCheckbox||!addon.checkbox)return;newCheckbox.checked=addon.checkbox.checked,newCheckbox.addEventListener("change",e=>{addon.checkbox.checked=e.target.checked;
210const changeEvent=new Event("change",{bubbles:!0});addon.checkbox.dispatchEvent(changeEvent);const clickEvent=new Event("click",{bubbles:!0});addon.checkbox.dispatchEvent(clickEvent)}),addon.disabled||cardElement.addEventListener("click",e=>{e.target===newCheckbox||e.target.closest(".addon-tooltip")||e.target.closest(".tooltip-icon")||newCheckbox.click()}),addon.checkbox.addEventListener("change",()=>{newCheckbox.checked=addon.checkbox.checked});const tooltipIcon=cardElement.querySelector(".tooltip-icon"),tooltipContent=cardElement.querySelector(".tooltip-content");tooltipIcon&&tooltipContent&&(tooltipIcon.addEventListener("mouseenter",()=>{tooltipContent.style.display="block"}),tooltipIcon.addEventListener("mouseleave",()=>{tooltipContent.style.display="none"}),tooltipIcon.addEventListener("click",e=>{e.stopPropagation();const isVisible=tooltipContent.style.display==="block";tooltipContent.style.display=isVisible?"none":"block"}))})}function init(){if(document.querySelector(".nominal-addon-redesign")){console.log("[Nominal A/B Test] Already initialized");return}injectCustomCSS(),waitForAddons(async system=>{try{let addons;if(system.type==="bold")addons=extractBoldAddons(system.container);else if(system.type==="native")addons=extractNativeAddons(system.container);else{console.log("[Nominal A/B Test] No add-ons found on this product");return}if(addons.length===0){console.log("[Nominal A/B Test] No add-ons extracted");return}console.log(`[Nominal A/B Test] Found ${addons.length} add-ons using ${system.type} system`),await fetchProductImages(addons);const newHTML=generateNewHTML(addons),newContainer=replaceUI(system.container,newHTML,addons,system.type);bindEventListeners(addons,newContainer),console.log(`[Nominal A/B Test] Redesign applied successfully (${addons.length} add-ons, ${system.type} system)`)}catch(error){console.error("[Nominal A/B Test] Error during initialization:",error),system.type==="bold"?extractBoldAddons(system.container).forEach(addon=>{addon.element&&(addon.element.style.display="")}):system.type==="native"&&system.container.classList.remove("nominal-hidden")}})}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",init):init()})(); 211//# sourceMappingURL=/cdn/shop/t/417/assets/ab19.js.map?v=80213340448644581111790728175
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.