From 60efc1c12e8d0f422160107485b718794076466c Mon Sep 17 00:00:00 2001 From: Kyle Date: Sat, 25 Apr 2026 23:04:13 -0400 Subject: [PATCH] Increase font size ranges; add save/load design as JSON --- gauge-designer.html | 91 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/gauge-designer.html b/gauge-designer.html index 6ef5480..9faef17 100644 --- a/gauge-designer.html +++ b/gauge-designer.html @@ -291,7 +291,7 @@
- + 3%
@@ -363,7 +363,7 @@
- + 6%
@@ -377,7 +377,7 @@
- + 3%
@@ -484,6 +484,10 @@
PDF prints at exact physical size.
Print at 100% — no scaling.
+
+ + +
@@ -1018,6 +1022,87 @@ $('exportPngBtn').addEventListener('click', () => { link.click(); }); +// ── save / load design ──────────────────────────────────────────────────────── +$('saveDesignBtn').addEventListener('click', () => { + const data = { version: 1, gaugeMode, sweepDir, zones: JSON.parse(JSON.stringify(zones)) }; + document.querySelectorAll('#sidebar input, #sidebar select').forEach(el => { + if (!el.id || el.type === 'file') return; + data[el.id] = el.type === 'checkbox' ? el.checked : el.value; + }); + if (logoImg) { + data.logoDataUrl = logoImg.src; + data.logoFileName = $('logoFileName').textContent; + } + const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); + const a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + a.download = `${$('gaugeTitle').value || 'gauge'}-design.json`; + a.click(); + URL.revokeObjectURL(a.href); +}); + +$('loadDesignBtn').addEventListener('click', () => $('loadDesignInput').click()); + +$('loadDesignInput').addEventListener('change', e => { + const file = e.target.files[0]; + if (!file) return; + const reader = new FileReader(); + reader.onload = ev => { + let data; + try { data = JSON.parse(ev.target.result); } catch { alert('Invalid design file.'); return; } + + // restore all inputs silently (no events yet) + document.querySelectorAll('#sidebar input, #sidebar select').forEach(el => { + if (!el.id || el.type === 'file' || !(el.id in data)) return; + if (el.type === 'checkbox') el.checked = data[el.id]; + else el.value = data[el.id]; + }); + + // update range display spans by firing input events on ranges + document.querySelectorAll('#sidebar input[type=range]').forEach(el => { + el.dispatchEvent(new Event('input')); + }); + + // restore gauge mode UI + gaugeMode = data.gaugeMode || 'standard'; + if (gaugeMode === 'center') { + $('modeCtr').classList.add('active'); $('modeStd').classList.remove('active'); + $('ctrFields').style.display = ''; $('stdFields').style.display = 'none'; + $('ctrTickNote').style.display = ''; $('stdTickNote').style.display = 'none'; + $('stdMajorInterval').style.display = 'none'; + } else { + $('modeStd').classList.add('active'); $('modeCtr').classList.remove('active'); + $('stdFields').style.display = ''; $('ctrFields').style.display = 'none'; + $('stdTickNote').style.display = ''; $('ctrTickNote').style.display = 'none'; + $('stdMajorInterval').style.display = ''; + } + + // restore sweep direction UI + sweepDir = data.sweepDir || 'cw'; + if (sweepDir === 'ccw') { + $('dirCCW').classList.add('active'); $('dirCW').classList.remove('active'); + } else { + $('dirCW').classList.add('active'); $('dirCCW').classList.remove('active'); + } + + // restore zones + zones = data.zones || []; + renderZones(); + + // restore logo + if (data.logoDataUrl) { + const img = new Image(); + img.onload = () => { setLogo(img, data.logoFileName || 'logo'); drawGauge(); }; + img.src = data.logoDataUrl; + } else { + clearLogo(); + drawGauge(); + } + }; + reader.readAsText(file); + e.target.value = ''; +}); + // ── preview background toggle ───────────────────────────────────────────────── const previewArea = $('preview-area');