window.checkoutOptionsData = {"url":"https:\/\/enhanced-checkout-options.com\/checkout\/1ih2d8","enabled":true,"message":"Subscription is not active.","places":[{"id":"cart","name":"Cart","page":"cart","selectors":[{"selector":".cart-totals","position":"inside","tag":"table","class":"cart-section"}],"enabled":true,"groups":[{"name":"Fully Insure Order for $3.99","description":"Full coverage for loss and damage on your package","type":"checkbox","is_mandatory":false,"id":125,"specific_countries":[],"options":[{"name":"Fully Insure Order Against Loss and Damage","is_default":1,"price":"3.99","checked":false,"sku":"order-insurance","show_price":true,"item_id":null,"has_note":false,"note":""}]}]}],"allEnabledOptionSkus":[{"sku":"order-insurance","name":"Fully Insure Order Against Loss and Damage"},{"sku":"free-return","name":"Free returns & exchanges for $3.99 (US Customers)"}],"redirectAfterOptionSelect":false,"script":"https:\/\/enhanced-checkout-options.com\/js\/cart.js","currency":{"code":"USD","format":"${{PRICE}}"}};
// Guard against this script running more than once on the same page (e.g. a
// duplicate script-tag registration, or a stale entry left over from a
// reinstall). Without this, a second execution's top-level `let`/`const`
// declarations collide with the first's in the shared global scope and throw
// "Identifier '...' has already been declared" - a SyntaxError that aborts
// the *entire* second script before it runs a single statement. Wrapping the
// rest in a block also makes these declarations block-scoped, so even an
// unguarded second load can no longer redeclare them.
if (!window.__ecoCartBootLoaded) {
window.__ecoCartBootLoaded = true;
let places = window.checkoutOptionsData.places;
window.checkoutApplicationBaseApiUrl = window.checkoutOptionsData.url;
window.checkoutOptionsPlaces = window.checkoutOptionsData.places;
window.reloadData = false;
const addScript = async src => new Promise((resolve, reject) => {
const el = document.createElement('script');
el.src = src;
el.addEventListener('load', resolve);
el.addEventListener('error', reject);
document.body.append(el);
});
const hideTotalsFromCart = () => {
const namesToHide = [];
if (window.checkoutOptionsData && window.checkoutOptionsData.allEnabledOptionSkus) {
window.checkoutOptionsData.allEnabledOptionSkus.forEach(option => {
namesToHide.push(option.name);
});
}
if (namesToHide.length === 0) {
return;
}
// This runs on every insertPlaceHolders() poll (every 100ms). Only touch the DOM
// when something actually changed - unconditionally removing and recreating the
// .cart-total--custom
every tick made it impossible to interact with (e.g.
// inspect) and constantly churned the cart totals list for no reason.
const cartTotalsList = document.querySelector('ul.cart-totals');
const matchedNames = new Set();
const items = document.querySelectorAll('tr.cart-item');
items.forEach(item => {
const nameElement = item.querySelector('.cart-item-name__label, .cart-item-name a, .cart-item-name');
if (!nameElement) return;
const name = nameElement.textContent.trim().replace(/\s+/g, ' ');
const shouldHide = namesToHide.includes(name);
if (shouldHide) {
matchedNames.add(name);
if (item.style.display !== 'none') {
item.style.display = 'none';
}
if (cartTotalsList) {
const priceElement = item.querySelector('.cart-item-value');
const price = priceElement ? priceElement.textContent.trim() : '';
const existing = cartTotalsList.querySelector(
`.cart-total--custom[data-option-name="${CSS.escape(name)}"]`
);
if (existing) {
const valueEl = existing.querySelector('.cart-total-value span');
if (valueEl && valueEl.textContent.trim() !== price) {
valueEl.textContent = price;
}
} else {
const customTotal = document.createElement('li');
customTotal.className = 'cart-total cart-total--custom';
customTotal.dataset.optionName = name;
customTotal.innerHTML = `
${name}:
${price}
`;
cartTotalsList.prepend(customTotal);
}
}
} else if (item.style.display !== '') {
item.style.display = '';
}
});
// Drop custom totals for items that are no longer in the cart / no longer matched.
if (cartTotalsList) {
cartTotalsList.querySelectorAll('.cart-total--custom').forEach(el => {
if (!matchedNames.has(el.dataset.optionName)) {
el.remove();
}
});
}
const miniCartItems = document.querySelectorAll('.previewCartItem');
miniCartItems.forEach(item => {
const nameElement = item.querySelector('.previewCartItem-name a');
if (nameElement) {
const name = nameElement.textContent.trim();
const shouldHide = namesToHide.includes(name);
if (shouldHide) {
if (item.style.display !== 'none') item.style.display = 'none';
} else {
if (item.style.display !== '') item.style.display = '';
}
}
});
}
const insertPlaceHolders = () => {
hideTotalsFromCart();
window.checkoutOptionsPlaces.map((place, index) => {
if (!place.enabled) return false;
place.selectors.map((sel, index) => {
let element = document.querySelector(sel.selector);
let id = `cart-options-placeholder-${index}`;
if (element && !document.getElementById(id)) {
let placeHolder = document.createElement(sel.tag ?? 'div');
placeHolder.className = sel.class;
placeHolder.id = id;
placeHolder.dataset.checkoutOption = place.id;
placeHolder.innerHTML = [""
, "Loading..."
, "
"].join('');
if (sel.position === 'before') {
element.parentNode.insertBefore(placeHolder, element)
} else if (sel.position === 'inside') {
element.append(placeHolder);
} else {
element.parentNode.insertBefore(placeHolder, element.nextSibling);
}
}
});
});
setTimeout(insertPlaceHolders, 100);
}
insertPlaceHolders();
setTimeout(() => {
fetch('/api/storefront/carts', {
method: "GET",
credentials: "same-origin"
})
.then(response => response.json())
.then(result => {
addScript((document.location.href.indexOf("debug") > 0 ? "http://localhost/js/cart.js" : window.checkoutOptionsData.script) + "?v=5&id=" + result[0].id).then();
window.bigcommerceCartId = result[0].id;
})
.catch(error => console.error(error));
}, 300)
document.addEventListener('DOMContentLoaded', function () {
const cartContent = document.querySelector('[data-cart-content]');
if (!cartContent) return;
let removeTimeout = null;
const observer = new MutationObserver(function () {
clearTimeout(removeTimeout);
removeTimeout = setTimeout(function () {
window.reloadData = true;
const section = document.querySelector('.cart-section');
if (section) {
section.remove();
}
}, 1);
});
observer.observe(cartContent, {
childList: true,
subtree: true
});
});
}