- Add front + top/side dimensioned schematic views (inch + mm) inside the "Show info" section of Stage (front + top-edge I/O), Practice (front bar + both end faces), and Display (pyramid front + side profile). Shared .dview / .dschem CSS in base.css. - Fix: progbox.js now defers to DOM-ready, so the "Show info" toggle + #techinfo are wired even when they sit after the page script (Stage/Practice/Player were silently not toggling / ignoring ?info=1). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
63 lines
4.2 KiB
JavaScript
63 lines
4.2 KiB
JavaScript
/* Per-device program I/O + "Show info" toggle — assembled into each form-factor page.
|
|
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.
|
|
Defers to DOM-ready so the box/toggle/techinfo are found wherever they sit 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(); }
|
|
});
|
|
}
|
|
// "Show info" toggle — reveals the technical section (#techinfo + any .tech); ?info=1 opens it checked
|
|
var tog = document.getElementById("infoToggle"), tech = document.getElementById("techinfo");
|
|
if (tog) {
|
|
var extra = document.querySelectorAll(".tech");
|
|
var apply = function (on) { if (tech) tech.hidden = !on; for (var i = 0; i < extra.length; i++) extra[i].hidden = !on; };
|
|
var open = /[?&]info=1/.test(location.search);
|
|
tog.checked = open; apply(open);
|
|
tog.addEventListener("change", function () { apply(tog.checked); });
|
|
}
|
|
window.progRefresh();
|
|
}
|
|
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init); else init();
|
|
})();
|