Split the 100-line script into catalog, cart, format, dom and main modules. Money is integer cents, the bag is capped and sanitised and syncs across tabs, and the view (category, sort) lives in the URL. Templates escape every interpolation. Rewrite the minified stylesheet as cascade layers on design tokens. Fixes heading tracking that collapsed word gaps, a 2.6:1 focus ring on the hero, 1.3:1 control borders, misaligned cart quantities, uneven product cards and undersized touch targets. Adds a favicon and a resolvable dialog label.
21 lines
736 B
JavaScript
21 lines
736 B
JavaScript
/** Formatting helpers. Money is always handled as integer cents to avoid float drift. */
|
|
|
|
// Intl formatters are comparatively expensive to build, so create each one once.
|
|
const whole = new Intl.NumberFormat("en-US", {
|
|
style: "currency",
|
|
currency: "USD",
|
|
minimumFractionDigits: 0,
|
|
maximumFractionDigits: 0,
|
|
});
|
|
const exact = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
|
|
|
|
/** 8600 -> "$86", 8650 -> "$86.50" */
|
|
export function money(cents) {
|
|
return (cents % 100 === 0 ? whole : exact).format(cents / 100);
|
|
}
|
|
|
|
/** plural(1, "item") -> "1 item", plural(3, "item") -> "3 items" */
|
|
export function plural(count, noun, pluralNoun = `${noun}s`) {
|
|
return `${count} ${count === 1 ? noun : pluralNoun}`;
|
|
}
|