parent
1945195790
commit
49f932bd55
204
README.md
204
README.md
|
|
@ -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**:
|
||||
|
||||
1. **Hinweis-Abfrage (Startseite):**
|
||||
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.
|
||||
Interaktives Zahlen-Pad über einem Hintergrundbild (Indiana-Jones-Style).
|
||||
Vier Ziffern lassen sich über „Münz“-Klickflächen erhöhen/verringern.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
### 🔁 Navigation
|
||||
## Features
|
||||
|
||||
- Zwischen den beiden Seiten wird per **Tastenkombination `Strg + Ä`** umgeschaltet.
|
||||
- Beim Start der Anwendung wird standardmäßig die **Hinweis-Abfrage** angezeigt.
|
||||
- Vollbild-Layout (nutzt gesamten Viewport; F11 für echten Vollbildmodus)
|
||||
- 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.
|
||||
Die Anwendung öffnet sich im Standardbrowser und ist sofort einsatzbereit.
|
||||
| Aktion | Windows/Linux | macOS | Hinweis |
|
||||
|------------------------|-------------------------|-----------------------|---------|
|
||||
| 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,
|
||||
- ist der komplette Quellcode offen einsehbar und lokal speicherbar.
|
||||
```css
|
||||
: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)** ✅
|
||||
```
|
||||
|
|
|
|||
138
script.js
138
script.js
|
|
@ -1,48 +1,132 @@
|
|||
// Startwerte
|
||||
const digits = [1, 2, 3, 4];
|
||||
// ================== 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";
|
||||
|
||||
// Richtige Kombination
|
||||
const code = [4, 2, 7, 9]; // <- anpassen!
|
||||
const pad = document.getElementById("pad");
|
||||
|
||||
const dEls = digits.map((_, i) => document.getElementById('d' + i));
|
||||
const pad = document.getElementById('pad');
|
||||
const openBtn = document.getElementById('openBtn');
|
||||
const success = document.getElementById('success');
|
||||
// Merke dir das Original-HTML, damit wir es nach einem "Clear" wiederherstellen können
|
||||
const padTemplate = pad.innerHTML;
|
||||
|
||||
const render = () => digits.forEach((v, i) => dEls[i].textContent = v);
|
||||
// Startwerte der 4 Stellen (0–9)
|
||||
let digits = [1, 2, 3, 4];
|
||||
|
||||
// Klicks auf Münzen
|
||||
pad.addEventListener('click', (ev) => {
|
||||
const btn = ev.target.closest('.coin');
|
||||
// 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;
|
||||
|
||||
if (dir === "up") digits[idx] = (digits[idx] + 1) % 10;
|
||||
if (dir === "down") digits[idx] = (digits[idx] + 9) % 10; // -1 modulo 10
|
||||
render();
|
||||
});
|
||||
|
||||
// Öffnen-Button
|
||||
openBtn.addEventListener('click', () => {
|
||||
function onOpenClick() {
|
||||
const ok = digits.every((v, i) => v === code[i]);
|
||||
if (ok) {
|
||||
// Inhalt des Pads ersetzen: alles raus, Nachricht rein
|
||||
pad.classList.remove('pad--shake');
|
||||
pad.classList.add('pad--cleared');
|
||||
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 = `
|
||||
<div class="solvedText digit" role="status" aria-live="polite">
|
||||
GEHEIMNIS GEÖFFNET
|
||||
${escapeHtml(solvedText)}
|
||||
</div>
|
||||
`;
|
||||
// Optional: Wenn du den Key-Button danach nicht mehr fokussierbar willst:
|
||||
// openBtn.blur();
|
||||
}
|
||||
|
||||
// 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 {
|
||||
pad.classList.remove('pad--shake');
|
||||
void pad.offsetWidth;
|
||||
pad.classList.add('pad--shake');
|
||||
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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue