Setzen der Codes und der Lösung

Anpassung der README
main
Sebastian Schüler 2025-09-08 08:18:41 +02:00
parent 1945195790
commit 49f932bd55
2 changed files with 293 additions and 57 deletions

204
README.md
View File

@ -1,52 +1,204 @@
# 🎓 Projekt FH Eingabeprüfung & Wörterbuch Super — hier ist die README.md **mit rohem Markdown** (also mit `#`, `*`, etc.), zum Kopieren:
## ✨ Funktionalität ```markdown
# Escape-Pad
Dieses Projekt besteht aus **zwei Seiten**: Interaktives Zahlen-Pad über einem Hintergrundbild (Indiana-Jones-Style).
Vier Ziffern lassen sich über „Münz“-Klickflächen erhöhen/verringern.
1. **Hinweis-Abfrage (Startseite):** Ein Schlüssel-Button prüft den Code. Bei korrekter Eingabe wird der Pad-Inhalt geleert und eine frei definierbare Nachricht im Stil der Ziffern angezeigt. Code & Nachricht sind per Tastenkürzel änderbar und werden in `localStorage` gespeichert.
Hier kann man Wörter oder Sätze eingeben. Diese Eingabe wird mit den hinterlegten Daten im lokalen Speicher abgeglichen.
→ Wird ein passender Eintrag gefunden, wird die zugehörige Ausgabe (Text, Zahl oder Sonderzeichen) angezeigt.
2. **Datenpflege:**
Auf dieser Seite können neue Paare (Eingabe ↔ Ausgabe) eingetragen und gespeichert werden.
--- ---
### 🔁 Navigation ## Features
- Zwischen den beiden Seiten wird per **Tastenkombination `Strg + Ä`** umgeschaltet. - Vollbild-Layout (nutzt gesamten Viewport; F11 für echten Vollbildmodus)
- Beim Start der Anwendung wird standardmäßig die **Hinweis-Abfrage** angezeigt. - Unsichtbare, responsive Klickflächen über den Münzen
- Schlüssel-Bild als „Öffnen“-Button
- Erfolgstext ersetzt den gesamten Pad-Inhalt
- Code & Nachricht per Tastenkürzel setzen (persistiert via `localStorage`)
- „Indiana-Jones“-Ziffernstile (graviert **oder** gestempelt)
- Barrierefrei: versteckter Text für Screenreader, `role="status"`
--- ---
### ⌨️ Eingabeinteraktion ## Projektstruktur
- In den Eingabefeldern kann die Eingabe durch **Drücken der Enter-Taste** bestätigt werden. ```
- Alternativ steht jeweils ein **Button zur Bestätigung** zur Verfügung.
/projektordner
├─ index.html
├─ style.css
├─ script.js
├─ back\_image\_new\.jpg # Hintergrundbild
└─ key.png # Schlüssel-Button (PNG, transparent)
````
> Passe Dateinamen bei Bedarf in `index.html`/`style.css` an.
--- ---
### 🖥️ Vollbildmodus ## Schnellstart
Um die Anwendung im **Vollbild** zu nutzen, kann wie gewohnt die Taste **`F11`** gedrückt werden (Browser-Funktion). 1. `back_image_new.jpg` und `key.png` neben `index.html` ablegen.
2. `index.html` im Browser öffnen.
3. F11 → Vollbild.
4. Münzen ↑/↓ klicken, Code einstellen, Schlüssel anklicken.
--- ---
## 🚀 Starten ## Tastenkürzel
Einfach einen **Doppelklick auf `index.html`** ausführen. | Aktion | Windows/Linux | macOS | Hinweis |
Die Anwendung öffnet sich im Standardbrowser und ist sofort einsatzbereit. |------------------------|-------------------------|-----------------------|---------|
| Nachricht setzen | **Strg + Ä** / **Strg + M** | **⌘ + Ä** / **⌘ + M** | Prompt mit aktuellem Text |
| Code setzen (4 Ziffern)| **Strg + Ö** / **Strg + K** | **⌘ + Ö** / **⌘ + K** | Akzeptiert `4279` oder `4,2,7,9` |
- Gespeichert unter `localStorage`-Schlüsseln:
- `escape_message` (Nachricht)
- `escape_code` (Array der 4 Ziffern)
- Zurücksetzen: Seite neu laden **und** Site-Daten/LocalStorage löschen, oder neue Werte per Shortcut setzen.
--- ---
## 🔐 Sicherheit & Hinweis ## Konfiguration
Da es sich um eine **einfache, lokale Anwendung** handelt: ### 1) Position & Größen (`style.css`, im `:root`)
- wurden keine besonderen Sicherheitsmaßnahmen implementiert, ```css
- ist der komplette Quellcode offen einsehbar und lokal speicherbar. :root{
--pad-left: 12%; /* Abstand vom linken Bildrand */
--pad-top: 22%; /* Abstand von oben */
--pad-w: 50%; /* Breite des aktiven Bereichs */
--pad-h: 54%; /* Höhe des aktiven Bereichs */
Bitte beachten: Die Daten werden **im `localStorage` des Browsers** abgelegt und können dort manuell eingesehen oder gelöscht werden. --coin: 13.5%; /* Durchmesser der Münz-Klickflächen relativ zum Pad */
--key-size: 26%; /* Breite des Schlüssel-Bildes relativ zum Pad */
--digit-size: clamp(24px, 6.2vw, 82px); /* Basisschriftgröße der Ziffern */
}
````
> Diese Variablen an dein Hintergrundbild anpassen, bis die Klickflächen exakt auf den Münzen liegen.
### 2) Defaults (`script.js`)
```js
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";
```
--- ---
## Styling der Ziffern (Indy-Look)
Binde **eine** der Fonts in `index.html` (vor `style.css`) ein und nutze die zugehörige `.digit`-Regel in `style.css`.
**A) Graviert / antik (Cinzel):**
```html
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@700;900&display=swap" rel="stylesheet">
```
```css
.digit{
font: 900 var(--digit-size)/1 "Cinzel", Georgia, serif;
letter-spacing:.06em;
color:#3a2616;
-webkit-text-stroke:1px rgba(0,0,0,.18);
text-shadow:
0 1px 0 rgba(250,228,180,.65),
0 -1px 0 rgba(0,0,0,.20),
0 2px 2px rgba(0,0,0,.30),
0 0 8px rgba(110,80,40,.20);
pointer-events:none;
transform: translateY(4%);
/* optional: mix-blend-mode: multiply; */
}
```
**B) Gestempelt / Pulp (Special Elite):**
```html
<link href="https://fonts.googleapis.com/css2?family=Special+Elite&display=swap" rel="stylesheet">
```
```css
.digit{
font: 800 var(--digit-size)/1 "Special Elite","Courier New",monospace;
letter-spacing:.04em;
color:#2d1f12;
text-shadow:
0 1px 0 rgba(255,230,180,.45),
0 2px 2px rgba(0,0,0,.35);
filter: contrast(1.05) sepia(.25);
pointer-events:none;
transform: translateY(4%);
}
```
> Der Erfolgstext nutzt `.digit` erneut und wird über `.solvedText` größer skaliert.
---
## Technische Hinweise
* **Vollbild:** `.escape` nutzt `width: 100vw; height: 100vh;`. Hintergrundbild füllt per `object-fit: cover`.
* **Responsiv:** Prozentbasierte Positionen/Größen; Klickflächen skalieren mit.
* **Events:** Münz-Klicks werden delegiert über `#pad` behandelt; Schlüssel-Button hat `id="openBtn"`.
* **Erfolg:** Bei korrektem Code wird `#pad` geleert und eine `.solvedText.digit`-Nachricht eingesetzt (siehe CSS-Klasse `.pad--cleared`).
---
## Barrierefreiheit
* Schlüssel-Button enthält visuell versteckten Text (`.visually-hidden`) für Screenreader.
* Erfolgstext hat `role="status"` und `aria-live="polite"`.
---
## Troubleshooting
* **Klickflächen „unsichtbar“ / Höhe 0:**
Stelle sicher, dass `.escape { height: 100vh; }` gesetzt ist und `.overlay`, `.pad` prozentuale Größen davon ableiten.
* **Schlüssel-Button als graues Rechteck oder links verschoben:**
Alte Button-Styles überschreiben. In `style.css` sicherstellen:
```css
.open{ appearance:none; -webkit-appearance:none; background:transparent; border:0; padding:0; }
.open img{ position:static; display:block; width:var(--key-size); height:auto; }
```
Prüfe, ob es globale `img`-Regeln gibt (z. B. `position:absolute;`) diese dürfen **nicht** auf den Schlüssel wirken.
* **Bildpfade prüfen:**
`back_image_new.jpg` und `key.png` müssen erreichbar sein (gleicher Ordner wie `index.html` oder Pfade anpassen).
* **Cache leeren:**
Harte Aktualisierung (Ctrl/Cmd + Shift + R).
---
## Erweiterungen (Ideen)
* Klick-/Öffnen-Soundeffekte
* Mehr Ziffernstellen (Grid-Spalten erhöhen)
* Touch-Gesten (Wischen ↑/↓)
* Alternative „Öffnen“-Interaktion (z. B. Doppelklick)
---
## Lizenz / Assets
* **Google Fonts** (Cinzel, Special Elite): SIL Open Font License Nutzung in Webprojekten erlaubt.
* **Eigene Bilder** (`back_image_new.jpg`, `key.png`): Bitte Rechteinhaberschaft sicherstellen.
---
## Support
Feintuning gewünscht (exakte `--pad-*`-Werte, Button-Größe, Farbnuancen)?
Kurze Info oder Screenshot schicken ich passe die Parameter punktgenau an.
```
Oder direkt herunterladen: **[Download README.md](sandbox:/mnt/data/README.md)** ✅
```

146
script.js
View File

@ -1,48 +1,132 @@
// Startwerte // ================== Konfiguration / State ==================
const digits = [1, 2, 3, 4]; 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";
// Richtige Kombination const pad = document.getElementById("pad");
const code = [4, 2, 7, 9]; // <- anpassen!
const dEls = digits.map((_, i) => document.getElementById('d' + i)); // Merke dir das Original-HTML, damit wir es nach einem "Clear" wiederherstellen können
const pad = document.getElementById('pad'); const padTemplate = pad.innerHTML;
const openBtn = document.getElementById('openBtn');
const success = document.getElementById('success');
const render = () => digits.forEach((v, i) => dEls[i].textContent = v); // Startwerte der 4 Stellen (09)
let digits = [1, 2, 3, 4];
// Klicks auf Münzen // Elemente-Cache für die Ziffern
pad.addEventListener('click', (ev) => { let dEls = [];
const btn = ev.target.closest('.coin'); 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; 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 idx = +btn.dataset.idx;
const dir = btn.dataset.dir; const dir = btn.dataset.dir;
if (dir === 'up') digits[idx] = (digits[idx] + 1) % 10; if (dir === "up") digits[idx] = (digits[idx] + 1) % 10;
if (dir === 'down') digits[idx] = (digits[idx] + 9) % 10; if (dir === "down") digits[idx] = (digits[idx] + 9) % 10; // -1 modulo 10
render(); render();
}); });
// Öffnen-Button function onOpenClick() {
openBtn.addEventListener('click', () => {
const ok = digits.every((v, i) => v === code[i]); const ok = digits.every((v, i) => v === code[i]);
if (ok) { if (ok) showSolved();
// Inhalt des Pads ersetzen: alles raus, Nachricht rein else {
pad.classList.remove('pad--shake'); pad.classList.remove("pad--shake");
pad.classList.add('pad--cleared');
pad.innerHTML = `
<div class="solvedText digit" role="status" aria-live="polite">
GEHEIMNIS GEÖFFNET
</div>
`;
// Optional: Wenn du den Key-Button danach nicht mehr fokussierbar willst:
// openBtn.blur();
} else {
pad.classList.remove('pad--shake');
void pad.offsetWidth; void pad.offsetWidth;
pad.classList.add('pad--shake'); pad.classList.add("pad--shake");
}
}
function showSolved() {
pad.classList.remove("pad--shake");
pad.classList.add("pad--cleared");
pad.innerHTML = `
<div class="solvedText digit" role="status" aria-live="polite">
${escapeHtml(solvedText)}
</div>
`;
}
// 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 (09) 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) =>
({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[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(); render();