Previously every device .html bundled its full narrative (purpose, BOM,
dimensioned drawings, embedding docs) inside a #techinfo block that embed
mode (?embed=1) only CSS-hid — so every embedder and every landing-page
iframe downloaded all of it (showcase 77%, teacher 49% of the file) for
content no embedder ever sees.
Now:
- <device>.html is the lean widget only: header + front view/controls +
title + summary + program box. ?embed=1 still collapses to the bare
widget; the heavy narrative is gone from the payload.
- info-<device>.html (new, one per form factor) carries all the words —
purpose, dimensions, priced BOM, embedding docs — and embeds the live
widget at the top via the existing iframe + auto-resize protocol
(new shared src/infoembed.html + src/infoembed.js).
- Each device links out to its info page ("…dimensions & BOM →"); the
landing panes and viewport bar now offer both Open ↗ and Specs & info ⓘ.
- Dropped the now-dead "Show info" toggle (CSS + progbox.js).
Branding: adopt the official VARASYS "tagline on the bottom" logos from the
brand kit (light-background variant now matches; dark already did). The
tagline is baked into the PNGs, so remove the CSS .brand-tag / .dev-tag
spans and the showcase canvas-drawn tagline. Brand cyan #0AB3F7 / navy
#1C283F already match the official palette.
build.sh / deploy.sh: build + deploy the six new info-*.html pages.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
55 lines
3.7 KiB
JavaScript
55 lines
3.7 KiB
JavaScript
/* Per-device program I/O — assembled into each form-factor page (the thin widget).
|
|
Uses the engine codec (patchToSetup / setupToPatch / codeToSetlist) for decode + lint.
|
|
Host page provides: window.currentProgramString() and window.loadProgramString(plain).
|
|
Exposes window.progRefresh() — call it after the device's program changes. When the
|
|
page is embedded it posts {type:'varasys-prog'} to the parent instead of touching the box.
|
|
(Specs / dimensions / BOM live on the separate info-<device>.html page, not here.)
|
|
Defers to DOM-ready so the box is found wherever it sits on the page. */
|
|
(function () {
|
|
var embedded = document.documentElement.dataset.embed === "1";
|
|
var box, msg, editing = false;
|
|
function setMsg(t, ok) { if (!msg) return; msg.textContent = t || ""; msg.classList.toggle("ok", !!ok && !!t); msg.classList.toggle("bad", !ok && !!t); }
|
|
function lint(text) {
|
|
text = (text || "").trim(); if (!text) return { ok: false, msg: "empty" };
|
|
var m = text.match(/[#?&](p|sl)=([^&\s]+)/), kind = null, payload = text;
|
|
if (m) { kind = m[1]; try { payload = decodeURIComponent(m[2]); } catch (e) { payload = m[2]; } }
|
|
var b64 = /^[A-Za-z0-9_-]{12,}$/.test(payload) && !/[;:]/.test(payload);
|
|
try {
|
|
if (kind === "sl" || (kind !== "p" && b64)) {
|
|
var sl = codeToSetlist(payload); if (!sl.items || !sl.items.length) throw new Error("set-list code has no items");
|
|
return { ok: true, plain: setupToPatch(sl.items[0]), msg: "decoded set list “" + sl.title + "” — item 1" };
|
|
}
|
|
var s = patchToSetup(payload); if (!s.lanes.length) throw new Error("no lanes — try e.g. kick:4");
|
|
return { ok: true, plain: setupToPatch(s), msg: s.lanes.length + " lane" + (s.lanes.length > 1 ? "s" : "") + " · " + s.bpm + " BPM" };
|
|
} catch (e) { return { ok: false, msg: "✗ " + e.message }; }
|
|
}
|
|
function doLoad() {
|
|
var r = lint(box.value);
|
|
if (!r.ok) { box.classList.add("err"); setMsg(r.msg, false); return; }
|
|
box.classList.remove("err"); box.value = r.plain; setMsg("✓ " + r.msg, true);
|
|
try { if (window.loadProgramString) window.loadProgramString(r.plain); } catch (e) { setMsg("✗ " + e.message, false); }
|
|
}
|
|
// report the current program: to the parent when embedded, else into the box.
|
|
// No-op on pages without a program hook (e.g. panel-based Teacher/Player).
|
|
window.progRefresh = function () {
|
|
if (!window.currentProgramString) return;
|
|
var p = ""; try { p = window.currentProgramString(); } catch (e) {}
|
|
if (embedded) { try { parent.postMessage({ type: "varasys-prog", patch: p }, "*"); } catch (e) {} return; }
|
|
if (box && !editing) { box.value = p; setMsg("", true); }
|
|
};
|
|
function init() {
|
|
box = document.getElementById("dProg"); msg = document.getElementById("dProgMsg");
|
|
if (box) {
|
|
box.addEventListener("focus", function () { editing = true; });
|
|
box.addEventListener("blur", function () { editing = false; });
|
|
box.addEventListener("input", function () { box.classList.remove("err"); });
|
|
box.addEventListener("keydown", function (e) { if (e.key === "Enter") { e.preventDefault(); doLoad(); } });
|
|
var loadBtn = document.getElementById("dProgLoad"); if (loadBtn) loadBtn.addEventListener("click", doLoad);
|
|
var copyBtn = document.getElementById("dProgCopy"); if (copyBtn) copyBtn.addEventListener("click", function () {
|
|
try { navigator.clipboard.writeText(box.value); copyBtn.textContent = "Copied!"; setTimeout(function () { copyBtn.textContent = "Copy"; }, 1200); } catch (e) { box.select(); }
|
|
});
|
|
}
|
|
window.progRefresh();
|
|
}
|
|
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init); else init();
|
|
})();
|