document.addEventListener('DOMContentLoaded', () => {
const priceEl = document.getElementById('product-price');
function getSelected(name) {
return document.querySelector(
`input[type="radio"][name="${name}"]:checked`
);
}
function readNumber(el, attr) {
if (!el) return 0;
const raw = el.getAttribute(attr);
const n = raw !== null ? Number(raw) : 0;
return Number.isFinite(n) ? n : 0;
}
// for multipliers like subMult, cFormMult, finMult
// default to 1 (no change) instead of 0
function readMultiplier(el, attr) {
if (!el) return 1;
const raw = el.getAttribute(attr);
if (raw === null) return 1;
const n = Number(raw);
if (!Number.isFinite(n) || n === 0) return 1;
return n;
}
// substrate key from the substrate radio
// expects data-sub="canvas" | "metal" | "fineartpaper" | "lusterpaper"
function getSubstrateKey(subEl) {
if (!subEl) return null;
const keyAttr = subEl.getAttribute('data-sub');
if (keyAttr) return keyAttr.trim().toLowerCase();
const val = (subEl.value || '').trim().toLowerCase();
return val || null;
}
// read pp/sq inch from the size radio based on substrate
// expects e.g. data-pp-sqi-canvas, data-pp-sqi-metal, etc.
function getPpSqiForSizeAndSubstrate(sizeEl, subEl) {
if (!sizeEl || !subEl) return 0;
const key = getSubstrateKey(subEl);
if (!key) return 0;
const attrName = `data-pp-sqi-${key}`;
return readNumber(sizeEl, attrName);
}
function setPriceValue(input, amount) {
if (!input) return;
const val = input.value || '';
const prefixMatch = val.match(/^([^{}]*)/);
let prefix = prefixMatch ? prefixMatch[1] : '';
if (!prefix) prefix = input.name || '';
input.value = `${prefix}{p+${amount}}`;
}
function recalc() {
const sizeEl = getSelected('size');
const subEl = getSelected('substrate');
const canvasEl = getSelected('canvas-format');
const finishEl = getSelected('finish');
const frameEl = getSelected('frame');
// size-related
const area = readNumber(sizeEl, 'data-area');
const perimeter = readNumber(sizeEl, 'data-perimeter');
// substrate / canvas / finish multipliers
const subMult = readMultiplier(subEl, 'data-sub-mult');
const cFormMult = readMultiplier(canvasEl, 'data-c-form-mult');
const finMult = readMultiplier(finishEl, 'data-fin-mult');
// frame-related
const ppFoot = readNumber(frameEl, 'data-pp-foot'); // price per foot
const fWidth = readNumber(frameEl, 'data-f-width'); // inches
// substrate-specific pp/sq inch from size radio
const ppSqi = getPpSqiForSizeAndSubstrate(sizeEl, subEl);
console.log({
area,
ppSqi,
subMult,
cFormMult,
finMult,
ppFoot,
fWidth
});
//------------------------------------------------------------------------
// FORMULA
//------------------------------------------------------------------------
const sizePrice = area * ppSqi;
const substratePrice = sizePrice * (subMult - 1);
const canvasFormatPrice = sizePrice * (cFormMult - 1);
const finishPrice = sizePrice * (finMult - 1);
const framePrice = (perimeter + 8 * fWidth) / 12 * ppFoot;
//------------------------------------------------------------------------
// FORMULA
//------------------------------------------------------------------------
const totalPrice =
sizePrice +
substratePrice +
canvasFormatPrice +
finishPrice +
framePrice;
// Foxy values
setPriceValue(sizeEl, sizePrice);
setPriceValue(subEl, substratePrice);
setPriceValue(canvasEl, canvasFormatPrice);
setPriceValue(finishEl, finishPrice);
setPriceValue(frameEl, framePrice);
// formatted display, e.g. $1402.85
if (priceEl) {
const safeTotal = Number.isFinite(totalPrice) ? totalPrice : 0;
priceEl.textContent = `$${safeTotal.toFixed(2)}`;
}
}
const radios = document.querySelectorAll(
'input[type="radio"][name="size"],' +
'input[type="radio"][name="substrate"],' +
'input[type="radio"][name="canvas-format"],' +
'input[type="radio"][name="finish"],' +
'input[type="radio"][name="frame"]'
);
radios.forEach(radio => radio.addEventListener('change', recalc));
recalc();
});