// ================== Konfiguration / State ================== const DEFAULT_CODE = [4, 2, 7, 9]; let code = JSON.parse(localStorage.getItem("escape_code") || "null") || DEFAULT_CODE; let solvedText = localStorage.getItem("escape_message") || "GEHEIMNIS GEÖFFNET"; const pad = document.getElementById("pad"); // Merke dir das Original-HTML, damit wir es nach einem "Clear" wiederherstellen können const padTemplate = pad.innerHTML; // Startwerte der 4 Stellen (0–9) let digits = [1, 2, 3, 4]; // Elemente-Cache für die Ziffern let dEls = []; function cacheDigitEls() { dEls = [0, 1, 2, 3].map((i) => document.getElementById("d" + i)); } cacheDigitEls(); // ================== Rendering & UI-Aufbau ================== const render = () => digits.forEach((v, i) => dEls[i] && (dEls[i].textContent = v)); function wireOpenButton() { const btn = document.getElementById("openBtn"); if (!btn) return; btn.addEventListener("click", onOpenClick); } wireOpenButton(); // Delegierter Klick-Handler für die Münzen (↑/↓) pad.addEventListener("click", (ev) => { const btn = ev.target.closest(".coin"); if (!btn || !pad.contains(btn)) return; const idx = +btn.dataset.idx; const dir = btn.dataset.dir; if (dir === "up") digits[idx] = (digits[idx] + 1) % 10; if (dir === "down") digits[idx] = (digits[idx] + 9) % 10; // -1 modulo 10 render(); }); function onOpenClick() { const ok = digits.every((v, i) => v === code[i]); if (ok) showSolved(); else { pad.classList.remove("pad--shake"); void pad.offsetWidth; pad.classList.add("pad--shake"); } } function showSolved() { pad.classList.remove("pad--shake"); pad.classList.add("pad--cleared"); pad.innerHTML = `
${escapeHtml(solvedText)}
`; } // UI wieder in den „Zahlenmodus“ versetzen (z. B. nach neuem Code) function rebuildPadUI() { pad.classList.remove("pad--cleared"); pad.innerHTML = padTemplate; cacheDigitEls(); wireOpenButton(); render(); } // ================== Shortcuts zum Setzen von Nachricht & Code ================== document.addEventListener("keydown", (e) => { // Strg (oder Cmd) + Ä -> Nachricht setzen if ((e.ctrlKey || e.metaKey) && isKey(e, ["ä", "Ä", "m"])) { e.preventDefault(); const msg = prompt('Nachricht (wird nach dem Öffnen angezeigt):', solvedText); if (msg !== null) { const clean = msg.trim(); if (clean) { solvedText = clean; localStorage.setItem("escape_message", solvedText); // Wenn bereits gelöst, die sichtbare Nachricht aktualisieren if (pad.classList.contains("pad--cleared")) showSolved(); } } return; } // Strg (oder Cmd) + Ö -> Code setzen if ((e.ctrlKey || e.metaKey) && isKey(e, ["ö", "Ö", "k"])) { e.preventDefault(); const input = prompt('Neuen 4-stelligen Code eingeben (z. B. 4279 oder 4,2,7,9):', code.join("")); if (input !== null) { const parsed = parseCode(input); if (parsed) { code = parsed; localStorage.setItem("escape_code", JSON.stringify(code)); // Falls wir gerade die solved-Ansicht zeigen: UI wieder zum Schloss zurücksetzen if (pad.classList.contains("pad--cleared")) rebuildPadUI(); alert("Neuer Code gesetzt: " + code.join("")); } else { alert("Ungültiges Format. Bitte genau 4 Ziffern (0–9) angeben."); } } } }); // ================== Utilities ================== function parseCode(str) { if (!str) return null; // Erlaubt: "4279", "4 2 7 9", "4,2,7,9" etc. const onlyDigits = str.match(/\d/g); if (!onlyDigits || onlyDigits.length !== 4) return null; return onlyDigits.map((d) => +d); } // Minimaler HTML-Escape für die Nachricht function escapeHtml(s) { return s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]) ); } // Hilfsfunktion: trifft auch Fallback-Tasten (M/K) function isKey(e, keys) { const k = (e.key || "").toLowerCase(); return keys.some((x) => k === x.toLowerCase()); } // Initiales Rendern render();