`; return row; } function escapeHtml(value) { return String(value).replace(/[&<>"']/g, char => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[char])); } function buildText() { const lines = []; const selected = [...state.values()].filter(item => item.selected || item.qty || item.note); lines.push(`PURCHASE LIST - ${formatDate(el.date.value)}`); if (el.filledBy.value.trim()) lines.push(`Filled by: ${el.filledBy.value.trim()}`); if (el.eventName.value.trim()) lines.push(`Event/client: ${el.eventName.value.trim()}`); lines.push(""); categories.forEach(([category]) => { const group = selected.filter(item => item.category === category); if (!group.length) return; lines.push(category.toUpperCase()); group.forEach(item => { const amount = [item.qty, item.unit].filter(Boolean).join(" "); const note = item.note ? ` (${item.note})` : ""; lines.push(`- ${item.english}${amount ? `: ${amount}` : ""}${note}`); }); lines.push(""); }); if (!selected.length) { lines.push("No items selected."); } return lines.join("\n").trim(); } function formatDate(value) { if (!value) return today(); const [year, month, day] = value.split("-"); return `${day}.${month}.${year}`; } function updateSummary() { const selected = [...state.values()].filter(item => item.selected || item.qty || item.note); el.output.value = buildText(); el.stats.textContent = `${selected.length} item${selected.length === 1 ? "" : "s"} selected`; el.mobileStats.textContent = `${selected.length} item${selected.length === 1 ? "" : "s"} selected`; } function updateRowFromEvent(target) { const row = target.closest(".row"); if (!row) return; const item = state.get(row.dataset.id); item.selected = row.querySelector(".check").checked; item.qty = row.querySelector(".qty").value.trim(); item.unit = row.querySelector(".unit").value; item.note = row.querySelector(".note").value.trim(); if (target.classList.contains("qty") && item.qty) item.selected = true; if (target.classList.contains("note") && item.note) item.selected = true; row.querySelector(".check").checked = item.selected; row.classList.toggle("active", item.selected); updateSummary(); } async function copyOutput() { const text = el.output.value; try { await navigator.clipboard.writeText(text); } catch (error) { el.output.focus(); el.output.select(); document.execCommand("copy"); } toast("Copied"); } function toast(message) { el.toast.textContent = message; clearTimeout(toast.timer); toast.timer = setTimeout(() => { el.toast.textContent = ""; }, 1800); } function clearAll() { if (!confirm("Clear all selected items?")) return; state.forEach(item => { item.selected = false; item.qty = ""; item.unit = ""; item.note = ""; }); renderList(); updateSummary(); toast("Cleared"); } function downloadText() { const blob = new Blob([el.output.value], { type: "text/plain;charset=utf-8" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `purchase-list-${el.date.value || today()}.txt`; a.click(); URL.revokeObjectURL(url); } document.addEventListener("input", event => { if (event.target.matches(".qty, .note")) updateRowFromEvent(event.target); if (event.target.matches("#date, #filledBy, #eventName")) updateSummary(); if (event.target.matches("#search")) renderList(); }); document.addEventListener("change", event => { if (event.target.matches(".check, .unit")) updateRowFromEvent(event.target); }); el.tabs.addEventListener("click", event => { const button = event.target.closest("[data-category]"); if (!button) return; activeCategory = button.dataset.category; renderTabs(); renderList(); }); document.querySelector("#copyTop").addEventListener("click", copyOutput); document.querySelector("#copySide").addEventListener("click", copyOutput); document.querySelector("#copyMobile").addEventListener("click", copyOutput); document.querySelector("#downloadTxt").addEventListener("click", downloadText); document.querySelector("#clearAll").addEventListener("click", clearAll); document.querySelector("#printPage").addEventListener("click", () => window.print()); initState(); renderTabs(); renderList(); updateSummary();
Made on
Tilda