- Created index.html for the main application interface with responsive design and dark mode support. - Added manifest.webmanifest for PWA configuration, including app icons and display settings. - Implemented service worker (sw.js) for offline caching of assets and network-first strategy for versioning. - Introduced version.json to manage app versioning.
638 lines
24 KiB
JavaScript
638 lines
24 KiB
JavaScript
/*
|
||
* Bibel Lern‑App
|
||
*
|
||
* Dieses Skript lädt die Daten aus einer separaten JSON‑Datei,
|
||
* gruppiert sie nach Themen, baut den Lernkarten‑Stapeln je nach Modus auf
|
||
* und verwaltet das Anzeigen von Karten, Zählern, Hinweisen und Dark‑Mode.
|
||
* Außerdem wird ein Splash‑Screen bereitgestellt, über den die App
|
||
* installiert werden kann, sobald das Browser‑Ereignis
|
||
* `beforeinstallprompt` ausgelöst wird.
|
||
*/
|
||
|
||
(() => {
|
||
// Fallback‑Daten, falls data.json nicht geladen werden kann (z.B. beim file://‑Protokoll).
|
||
const fallbackData = [
|
||
{
|
||
"Thema": "Zukunft",
|
||
"Kommentar": "Die aktuelle Weltlage und die Einstellung der Menschen deuten darauf hin, dass große Veränderungen bevorstehen",
|
||
"Bibel-Verweis": "Mat. 24:3",
|
||
"Bibeltext": "Und als er auf dem Ölberg saß, traten zu ihm seine Jünger allein und fragten: Sage uns, wann wird das geschehen, und was wird das Zeichen deines Kommens und des Endes der Welt?",
|
||
"Schluesselwoerter": ["Veränderungen", "Zeichen"]
|
||
},
|
||
{
|
||
"Thema": "Zukunft",
|
||
"Kommentar": "Die Erde wird nie zerstört werden",
|
||
"Bibel-Verweis": "Ps. 104:5",
|
||
"Bibeltext": "Der du die Erde auf ihre Grundfesten gegründet hast, daß sie für immer und ewig steht.",
|
||
"Schluesselwoerter": ["Erde", "ewig"]
|
||
},
|
||
{
|
||
"Thema": "Zukunft",
|
||
"Kommentar": "Die Umweltzerstörung wird vollständig rückgängig gemacht",
|
||
"Bibel-Verweis": "Jes. 35:1-2",
|
||
"Bibeltext": "Die Wüste und Einöde wird lustig sein, und das dürre Land wird frohlocken; sie wird blühen wie die Lilien.",
|
||
"Schluesselwoerter": ["Wüste", "blühen"]
|
||
},
|
||
{
|
||
"Thema": "Zukunft",
|
||
"Kommentar": "Alle Menschen werden völlig gesund sein",
|
||
"Bibel-Verweis": "Jes. 33:24",
|
||
"Bibeltext": "Kein Einwohner wird sagen: Ich bin krank; dem Volk, das dort wohnt, wird seine Schuld vergeben sein.",
|
||
"Schluesselwoerter": ["gesund", "heil"]
|
||
},
|
||
{
|
||
"Thema": "Zukunft",
|
||
"Kommentar": "Sie können für immer auf der Erde leben",
|
||
"Bibel-Verweis": "Ps. 37:29",
|
||
"Bibeltext": "Die Gerechten erben das Land und bleiben ewiglich darin.",
|
||
"Schluesselwoerter": ["erben", "Land"]
|
||
},
|
||
{
|
||
"Thema": "Familie",
|
||
"Kommentar": "Ein Ehemann sollte seine Frau „lieben wie sich selbst“",
|
||
"Bibel-Verweis": "Eph. 5:33",
|
||
"Bibeltext": "Doch auch ihr, jeder von euch liebe seine Frau wie sich selbst; die Frau aber erweise dem Mann Ehrfurcht.",
|
||
"Schluesselwoerter": ["Liebe", "Respekt"]
|
||
},
|
||
{
|
||
"Thema": "Familie",
|
||
"Kommentar": "Eine Ehefrau sollte ihren Mann von Herzen respektieren",
|
||
"Bibel-Verweis": "Eph. 5:33",
|
||
"Bibeltext": "Doch auch ihr, jeder von euch liebe seine Frau wie sich selbst; die Frau aber erweise dem Mann Ehrfurcht.",
|
||
"Schluesselwoerter": ["Respekt", "Ehemann"]
|
||
},
|
||
{
|
||
"Thema": "Familie",
|
||
"Kommentar": "Mann und Frau sollten einander treu sein",
|
||
"Bibel-Verweis": "Mal. 2:16",
|
||
"Bibeltext": "Denn ich hasse die Scheidung, spricht der HERR … so hütet euch in eurem Geist und seid nicht treulos.",
|
||
"Schluesselwoerter": ["Treue", "Ehe"]
|
||
},
|
||
{
|
||
"Thema": "Familie",
|
||
"Kommentar": "Es wirkt sich auf Kinder gut aus, wenn sie ihre Eltern respektieren und auf sie hören",
|
||
"Bibel-Verweis": "Spr. 1:8-9",
|
||
"Bibeltext": "Höre, mein Sohn, die Unterweisung deines Vaters und verlaß nicht das Gesetz deiner Mutter; denn das wird deinem Haupt ein lieblicher Schmuck sein.",
|
||
"Schluesselwoerter": ["Kinder", "Gehorsam"]
|
||
},
|
||
{
|
||
"Thema": "Gott",
|
||
"Kommentar": "Gott hat einen Namen",
|
||
"Bibel-Verweis": "Ps. 83:18",
|
||
"Bibeltext": "… damit man erkenne: Du allein, dessen Name Jehova ist, der Höchste bist über die ganze Erde.",
|
||
"Schluesselwoerter": ["Name", "Jehova"]
|
||
},
|
||
{
|
||
"Thema": "Gott",
|
||
"Kommentar": "Gott kommuniziert mit uns",
|
||
"Bibel-Verweis": "2. Tim. 3:16-17",
|
||
"Bibeltext": "Alle Schrift ist von Gott eingegeben und nütze zur Lehre, zur Zurechtweisung, zur Besserung … damit der Mensch Gottes vollkommen sei.",
|
||
"Schluesselwoerter": ["Schrift", "göttlich"]
|
||
},
|
||
{
|
||
"Thema": "Gott",
|
||
"Kommentar": "Gott ist fair und hat keine Vorurteile",
|
||
"Bibel-Verweis": "5. Mo. 10:17",
|
||
"Bibeltext": "Denn der HERR, euer Gott, … ist kein Anseher der Person und nimmt keine Bestechung an.",
|
||
"Schluesselwoerter": ["gerecht", "unparteiisch"]
|
||
},
|
||
{
|
||
"Thema": "Gott",
|
||
"Kommentar": "Gott möchte uns helfen",
|
||
"Bibel-Verweis": "Ps. 46:1",
|
||
"Bibeltext": "Gott ist unsre Zuflucht und Stärke, ein bewährter Helfer in Nöten.",
|
||
"Schluesselwoerter": ["Hilfe", "Zuflucht"]
|
||
},
|
||
{
|
||
"Thema": "Gebet",
|
||
"Kommentar": "Gott wünscht sich, dass wir zu ihm beten",
|
||
"Bibel-Verweis": "Ps. 62:8",
|
||
"Bibeltext": "Vertraut auf ihn allezeit, liebe Leute, schüttet euer Herz vor ihm aus; Gott ist unsere Zuflucht.",
|
||
"Schluesselwoerter": ["Beten", "vertrauen"]
|
||
},
|
||
{
|
||
"Thema": "Gebet",
|
||
"Kommentar": "Aus der Bibel erfahren wir, wie man beten sollte",
|
||
"Bibel-Verweis": "Mat. 6:7-13",
|
||
"Bibeltext": "Wenn ihr betet, sollt ihr nicht plappern … Unser Vater im Himmel! Dein Name werde geheiligt …",
|
||
"Schluesselwoerter": ["Gebet", "Vaterunser"]
|
||
},
|
||
{
|
||
"Thema": "Gebet",
|
||
"Kommentar": "Wir sollten oft beten",
|
||
"Bibel-Verweis": "Mat. 7:7-8",
|
||
"Bibeltext": "Bittet, so wird euch gegeben; suchet, so werdet ihr finden; klopfet an, so wird euch aufgetan.",
|
||
"Schluesselwoerter": ["bitten", "suchen"]
|
||
},
|
||
{
|
||
"Thema": "Jesus",
|
||
"Kommentar": "Jesus war ein außergewöhnlicher Lehrer. Sein Rat funktioniert immer",
|
||
"Bibel-Verweis": "Mat. 6:14-15",
|
||
"Bibeltext": "Denn wenn ihr den Menschen ihre Verfehlungen vergebt, wird euch euer himmlischer Vater auch vergeben.",
|
||
"Schluesselwoerter": ["Vergebung", "Lehrer"]
|
||
},
|
||
{
|
||
"Thema": "Jesus",
|
||
"Kommentar": "Jesus hat Ereignisse vorausgesagt, die wir heute beobachten können",
|
||
"Bibel-Verweis": "Mat. 24:3",
|
||
"Bibeltext": "Und als er auf dem Ölberg saß, traten zu ihm seine Jünger allein und fragten: Sage uns, wann wird das geschehen, und was wird das Zeichen deines Kommens und des Endes der Welt?",
|
||
"Schluesselwoerter": ["Prophezeiung", "Endzeit"]
|
||
},
|
||
{
|
||
"Thema": "Jesus",
|
||
"Kommentar": "Jesus ist Gottes Sohn",
|
||
"Bibel-Verweis": "Mat. 16:16",
|
||
"Bibeltext": "Du bist der Christus, der Sohn des lebendigen Gottes.",
|
||
"Schluesselwoerter": ["Christus", "Sohn"]
|
||
},
|
||
{
|
||
"Thema": "Jesus",
|
||
"Kommentar": "Jesus ist nicht der allmächtige Gott",
|
||
"Bibel-Verweis": "Joh. 14:28",
|
||
"Bibeltext": "… denn der Vater ist größer als ich.",
|
||
"Schluesselwoerter": ["Vater", "größer"]
|
||
},
|
||
{
|
||
"Thema": "Reich Gottes",
|
||
"Kommentar": "Das Reich Gottes ist eine echte Regierung im Himmel",
|
||
"Bibel-Verweis": "Dan. 2:44",
|
||
"Bibeltext": "Aber zur Zeit solcher Königreiche wird der Gott des Himmels ein Königreich aufrichten, das nimmermehr zerstört wird; und sein Königreich wird auf kein ander Volk kommen. Es wird alle diese Königreiche zermalmen und verstören; aber es selbst wird ewiglich bleiben.",
|
||
"Schluesselwoerter": ["Königreich", "Himmel"]
|
||
},
|
||
{
|
||
"Thema": "Reich Gottes",
|
||
"Kommentar": "Gottes Reich wird alle Regierungen auf der Erde ersetzen",
|
||
"Bibel-Verweis": "Ps. 2:7-9",
|
||
"Bibeltext": "Du bist mein Sohn; heute habe ich dich gezeugt … Zerbrich sie mit eisernem Zepter und zerschmettere sie.",
|
||
"Schluesselwoerter": ["Regierungen", "ersetzen"]
|
||
},
|
||
{
|
||
"Thema": "Reich Gottes",
|
||
"Kommentar": "Nur Gottes Reich kann die Probleme der Menschheit lösen",
|
||
"Bibel-Verweis": "Ps. 37:10-11",
|
||
"Bibeltext": "Nur noch eine kleine Weile, so ist der Gottlose nicht mehr; … die Sanftmütigen aber werden das Land erben und großen Frieden haben.",
|
||
"Schluesselwoerter": ["Frieden", "Lösung"]
|
||
},
|
||
{
|
||
"Thema": "Leid",
|
||
"Kommentar": "Gott ist nicht schuld, wenn wir leiden",
|
||
"Bibel-Verweis": "5. Mo. 32:4",
|
||
"Bibeltext": "Er ist ein Fels; vollkommen ist sein Tun, denn alle seine Wege sind recht; ein treuer Gott, ohne Falsch.",
|
||
"Schluesselwoerter": ["gerecht", "Schuld"]
|
||
},
|
||
{
|
||
"Thema": "Leid",
|
||
"Kommentar": "Diese Welt wird vom Teufel beherrscht",
|
||
"Bibel-Verweis": "Luk. 4:5-6",
|
||
"Bibeltext": "Da führte ihn der Teufel auf einen hohen Berg … Dir will ich alle Macht und Herrlichkeit dieser Reiche geben, denn sie ist mir übergeben.",
|
||
"Schluesselwoerter": ["Teufel", "Welt"]
|
||
},
|
||
{
|
||
"Thema": "Leid",
|
||
"Kommentar": "Gott sieht es, wenn Sie leiden, und möchte Ihnen helfen",
|
||
"Bibel-Verweis": "Ps. 34:17-19",
|
||
"Bibeltext": "Der HERR ist nahe denen, die zerbrochenen Herzens sind … Er erlöst sie aus allen ihren Nöten.",
|
||
"Schluesselwoerter": ["nah", "helfen"]
|
||
},
|
||
{
|
||
"Thema": "Leid",
|
||
"Kommentar": "Gott wird allem Leid bald ein Ende machen",
|
||
"Bibel-Verweis": "Jes. 65:17",
|
||
"Bibeltext": "Denn siehe, ich schaffe einen neuen Himmel und eine neue Erde …",
|
||
"Schluesselwoerter": ["neuer Himmel", "Ende"]
|
||
},
|
||
{
|
||
"Thema": "Tod",
|
||
"Kommentar": "Die Toten sind ohne jedes Bewusstsein und leiden auch nicht",
|
||
"Bibel-Verweis": "Pred. 9:5",
|
||
"Bibeltext": "Denn die Lebenden wissen, dass sie sterben; die Toten aber wissen nichts …",
|
||
"Schluesselwoerter": ["Toten", "Bewusstsein"]
|
||
},
|
||
{
|
||
"Thema": "Tod",
|
||
"Kommentar": "Die Toten können uns weder helfen noch uns schaden",
|
||
"Bibel-Verweis": "Ps. 146:4",
|
||
"Bibeltext": "Wenn ein Mensch stirbt, kehrt sein Geist zurück zur Erde; an demselben Tag sind alle seine Pläne zunichte.",
|
||
"Schluesselwoerter": ["helfen", "schaden"]
|
||
},
|
||
{
|
||
"Thema": "Tod",
|
||
"Kommentar": "Unsere geliebten Verstorbenen werden auferweckt",
|
||
"Bibel-Verweis": "Hiob 14:13-15",
|
||
"Bibeltext": "Wenn du mich nur im Totenreich verwahrtest … du würdest rufen, und ich würde dir antworten.",
|
||
"Schluesselwoerter": ["Auferweckung", "Hoffnung"]
|
||
},
|
||
{
|
||
"Thema": "Tod",
|
||
"Kommentar": "Den Tod wird es nicht mehr geben",
|
||
"Bibel-Verweis": "Offb. 21:3-4",
|
||
"Bibeltext": "Gott wird abwischen alle Tränen von ihren Augen; der Tod wird nicht mehr sein …",
|
||
"Schluesselwoerter": ["Tod", "nicht mehr"]
|
||
},
|
||
{
|
||
"Thema": "Religion",
|
||
"Kommentar": "Gott ist nicht mit allen Religionen einverstanden",
|
||
"Bibel-Verweis": "Jer. 7:11",
|
||
"Bibeltext": "Ist denn dieses Haus, das nach meinem Namen genannt ist, eine Räuberhöhle geworden in euren Augen?",
|
||
"Schluesselwoerter": ["Religion", "Räuberhöhle"]
|
||
},
|
||
{
|
||
"Thema": "Religion",
|
||
"Kommentar": "Gott hasst Heuchelei",
|
||
"Bibel-Verweis": "Jes. 29:13",
|
||
"Bibeltext": "Dieses Volk naht mir mit seinem Mund … aber ihr Herz ist fern von mir.",
|
||
"Schluesselwoerter": ["Heuchelei", "Herz"]
|
||
},
|
||
{
|
||
"Thema": "Religion",
|
||
"Kommentar": "Die wahre Religion zeichnet sich durch echte Liebe aus",
|
||
"Bibel-Verweis": "Joh. 13:34-35",
|
||
"Bibeltext": "Ein neues Gebot gebe ich euch: dass ihr einander liebt … Daran werden alle erkennen, dass ihr meine Jünger seid.",
|
||
"Schluesselwoerter": ["Liebe", "Gebot"]
|
||
}
|
||
];
|
||
const modeSelect = document.getElementById('mode-select');
|
||
const topicSelect = document.getElementById('topic-select');
|
||
const bookSelect = document.getElementById('book-select');
|
||
const commentHint = document.getElementById('comment-hint');
|
||
const keywordHint = document.getElementById('keyword-hint');
|
||
const themeHint = document.getElementById('theme-hint');
|
||
const cardEl = document.querySelector('.card');
|
||
const cardFrontSymbol = document.querySelector('.card-symbol');
|
||
const cardFrontRef = document.querySelector('.card-ref');
|
||
const cardFrontComment = document.querySelector('.card-comment');
|
||
const cardBackText = document.querySelector('.card-back .card-text');
|
||
const cardFrontKeywords = document.querySelector('.card-front .card-keywords');
|
||
const cardBackCounter = document.querySelector('.card-back .card-counter');
|
||
const correctBtn = document.getElementById('correct-btn');
|
||
const wrongBtn = document.getElementById('wrong-btn');
|
||
const counterDisplay = document.getElementById('counter');
|
||
const darkToggle = document.getElementById('dark-mode-toggle');
|
||
const splashScreen = document.getElementById('splash-screen');
|
||
const installBtn = document.getElementById('install-btn');
|
||
const continueBtn = document.getElementById('continue-btn');
|
||
|
||
// Mapping von Themen zu Symbolen und Farben
|
||
const topicMapping = {
|
||
'Zukunft': { color: '#B2E0F1', symbol: '⏳' },
|
||
'Familie': { color: '#FFEFA1', symbol: '👨👩👧👦' },
|
||
'Gott': { color: '#C3EACE', symbol: '🕊️' },
|
||
'Gebet': { color: '#F9B5C8', symbol: '🙏' },
|
||
'Jesus': { color: '#FFD0B5', symbol: '✝️' },
|
||
'Reich Gottes': { color: '#ADD7F6', symbol: '👑' },
|
||
'Leid': { color: '#D3C0E6', symbol: '😢' },
|
||
'Tod': { color: '#B7D4E7', symbol: '⚰️' },
|
||
'Religion': { color: '#FFC8BF', symbol: '⛪️' },
|
||
};
|
||
|
||
// Daten werden nach dem Laden der Seite geladen
|
||
let data = [];
|
||
let topics = {};
|
||
let uniqueBooks = [];
|
||
let deck = [];
|
||
let currentIndex = 0;
|
||
// Zähler für aktuelle Session
|
||
let correctCount = 0;
|
||
// Fortlaufende Statistik über alle Sessions hinweg nach Thema
|
||
let progressData = {};
|
||
// Statistik pro Karte (richtig/falsch)
|
||
let cardStats = {};
|
||
|
||
let deferredPrompt = null;
|
||
|
||
// Gruppiert Daten nach Thema und sammelt Buchlisten
|
||
function groupData() {
|
||
topics = {};
|
||
const booksSet = new Set();
|
||
data.forEach(item => {
|
||
const theme = item['Thema'];
|
||
if (!topics[theme]) {
|
||
topics[theme] = {
|
||
color: (topicMapping[theme] && topicMapping[theme].color) || '#CCCCCC',
|
||
symbol: (topicMapping[theme] && topicMapping[theme].symbol) || '📖',
|
||
items: [],
|
||
};
|
||
}
|
||
topics[theme].items.push(item);
|
||
// Extrahiere Buch zur Liste
|
||
const book = extractBook(item['Bibel-Verweis']);
|
||
booksSet.add(book);
|
||
});
|
||
uniqueBooks = Array.from(booksSet).sort((a, b) => a.localeCompare(b, 'de')); // sortiert nach deutschem Collation
|
||
}
|
||
|
||
// Extrahiert das Buch aus einem Verweis (z.B. "2. Tim. 3:1-5" -> "2. Tim.")
|
||
function extractBook(ref) {
|
||
const beforeColon = ref.split(':')[0].trim();
|
||
const parts = beforeColon.split(' ');
|
||
// Entferne die letzte Komponente (Kapitel)
|
||
if (parts.length > 1) parts.pop();
|
||
return parts.join(' ');
|
||
}
|
||
|
||
// Generiert einen eindeutigen Schlüssel für eine Karte. Wir verwenden Thema,
|
||
// den Bibel‑Verweis und den Kommentar, um Karten eindeutig zu identifizieren.
|
||
function getCardKey(item) {
|
||
const theme = item['Thema'] || '';
|
||
const ref = item['Bibel-Verweis'] || '';
|
||
const comment = item['Kommentar'] || '';
|
||
return `${theme}|${ref}|${comment}`;
|
||
}
|
||
|
||
// Füllt die Auswahlfelder für Thema und Buch
|
||
function populateSelects() {
|
||
// Themenauswahl
|
||
topicSelect.innerHTML = '';
|
||
Object.keys(topics).forEach(name => {
|
||
const option = document.createElement('option');
|
||
option.value = name;
|
||
option.textContent = name;
|
||
topicSelect.appendChild(option);
|
||
});
|
||
// Buchauswahl
|
||
bookSelect.innerHTML = '';
|
||
uniqueBooks.forEach(name => {
|
||
const option = document.createElement('option');
|
||
option.value = name;
|
||
option.textContent = name;
|
||
bookSelect.appendChild(option);
|
||
});
|
||
}
|
||
|
||
// Mischt ein Array (Fisher–Yates)
|
||
function shuffle(array) {
|
||
for (let i = array.length - 1; i > 0; i--) {
|
||
const j = Math.floor(Math.random() * (i + 1));
|
||
[array[i], array[j]] = [array[j], array[i]];
|
||
}
|
||
return array;
|
||
}
|
||
|
||
// Bereitet das Karten‑Deck entsprechend dem aktuellen Modus vor
|
||
function prepareDeck() {
|
||
const mode = modeSelect.value;
|
||
let items = [];
|
||
if (mode === 'random') {
|
||
// Alle Elemente
|
||
items = [...data];
|
||
} else if (mode === 'topic') {
|
||
const selectedTheme = topicSelect.value;
|
||
items = topics[selectedTheme] ? [...topics[selectedTheme].items] : [];
|
||
} else if (mode === 'book') {
|
||
const selectedBook = bookSelect.value;
|
||
items = data.filter(item => extractBook(item['Bibel-Verweis']) === selectedBook);
|
||
}
|
||
deck = shuffle(items);
|
||
currentIndex = 0;
|
||
correctCount = 0;
|
||
updateCounter();
|
||
}
|
||
|
||
// Aktualisiert die Anzeige der aktuellen Karte
|
||
function updateCard() {
|
||
if (deck.length === 0) {
|
||
cardFrontRef.textContent = 'Keine Karten';
|
||
cardBackText.textContent = '';
|
||
cardFrontSymbol.textContent = '';
|
||
cardEl.classList.remove('flipped');
|
||
return;
|
||
}
|
||
const item = deck[currentIndex];
|
||
const theme = item['Thema'];
|
||
const mapping = topicMapping[theme] || { color: '#CCCCCC', symbol: '📖' };
|
||
// Setze die Akzentfarbe über CSS‑Variable
|
||
cardFrontRef.parentElement.style.setProperty('--accent-color', mapping.color);
|
||
cardBackText.parentElement.style.setProperty('--accent-color', mapping.color);
|
||
// Thema als Text oder leer je nach Hint
|
||
if (themeHint && themeHint.checked) {
|
||
cardFrontSymbol.textContent = theme;
|
||
} else {
|
||
cardFrontSymbol.textContent = '';
|
||
}
|
||
// Referenz immer ohne Keywords anzeigen
|
||
cardFrontRef.textContent = item['Bibel-Verweis'];
|
||
// Kommentar sichtbar machen, wenn aktiviert
|
||
if (commentHint.checked) {
|
||
cardFrontComment.textContent = item['Kommentar'];
|
||
} else {
|
||
cardFrontComment.textContent = '';
|
||
}
|
||
// Setze Text der Rückseite
|
||
cardBackText.textContent = item['Bibeltext'];
|
||
// Aktualisiere die Per‑Karten‑Zähleranzeige
|
||
if (cardBackCounter) {
|
||
const key = getCardKey(item);
|
||
const stats = cardStats[key] || { correct: 0, wrong: 0 };
|
||
const correctVal = stats.correct || 0;
|
||
const wrongVal = stats.wrong || 0;
|
||
cardBackCounter.textContent = `Richtig: ${correctVal} | Falsch: ${wrongVal}`;
|
||
}
|
||
// Schlüsselwörter auf der Vorderseite, falls aktiviert
|
||
if (keywordHint && keywordHint.checked) {
|
||
const keywords = item['Schluesselwoerter'] || [];
|
||
cardFrontKeywords.textContent = keywords.join(', ');
|
||
} else {
|
||
cardFrontKeywords.textContent = '';
|
||
}
|
||
// Stellen Sie sicher, dass die Karte initial nicht umgedreht ist
|
||
cardEl.classList.remove('flipped');
|
||
}
|
||
|
||
// Aktualisiert den Counter oben rechts
|
||
function updateCounter() {
|
||
const total = deck.length;
|
||
counterDisplay.textContent = `${correctCount}/${total}`;
|
||
}
|
||
|
||
// Wechselt zur nächsten Karte im Stapel
|
||
function nextCard() {
|
||
if (deck.length === 0) return;
|
||
currentIndex = (currentIndex + 1) % deck.length;
|
||
updateCard();
|
||
updateCounter();
|
||
}
|
||
|
||
// Ereignis‑Listener für Dark‑Mode
|
||
function handleDarkModeChange() {
|
||
const dark = darkToggle.checked;
|
||
document.body.classList.toggle('dark', dark);
|
||
localStorage.setItem('darkMode', dark);
|
||
}
|
||
|
||
// Initialisiert die Splash‑Screen‑Logik
|
||
function initSplash() {
|
||
// Zeige Splash nur, wenn noch nicht gesehen
|
||
const dismissed = localStorage.getItem('splashDismissed');
|
||
if (dismissed) return;
|
||
splashScreen.classList.remove('hidden');
|
||
}
|
||
|
||
// Registriert Service Worker
|
||
function registerSW() {
|
||
if ('serviceWorker' in navigator) {
|
||
navigator.serviceWorker
|
||
.register('service-worker.js')
|
||
.catch(err => console.error('Service Worker registration failed:', err));
|
||
}
|
||
}
|
||
|
||
// Haupt‑Initialisierung
|
||
document.addEventListener('DOMContentLoaded', async () => {
|
||
// Lade Daten
|
||
try {
|
||
if (location.protocol === 'file:') {
|
||
// Beim direkten Öffnen über das Dateisystem schlägt fetch typischerweise fehl.
|
||
// Verwenden Sie in diesem Fall Fallback‑Daten aus dieser Datei.
|
||
data = fallbackData;
|
||
} else {
|
||
const res = await fetch('data.json');
|
||
if (!res.ok) throw new Error('Network response was not ok');
|
||
data = await res.json();
|
||
}
|
||
} catch (err) {
|
||
console.warn('Fehler beim Laden der Daten, verwende Fallback‑Daten:', err);
|
||
data = fallbackData;
|
||
}
|
||
// Lade gespeicherte Zähler aus localStorage
|
||
try {
|
||
const storedProgress = localStorage.getItem('progressData');
|
||
if (storedProgress) progressData = JSON.parse(storedProgress);
|
||
} catch (e) {
|
||
progressData = {};
|
||
}
|
||
try {
|
||
const storedStats = localStorage.getItem('cardStats');
|
||
if (storedStats) cardStats = JSON.parse(storedStats);
|
||
} catch (e) {
|
||
cardStats = {};
|
||
}
|
||
// Gruppiere Daten und fülle Auswahlfelder
|
||
groupData();
|
||
populateSelects();
|
||
// Auswahllisten je nach Modus initial ausblenden
|
||
topicSelect.classList.toggle('hidden', modeSelect.value !== 'topic');
|
||
bookSelect.classList.toggle('hidden', modeSelect.value !== 'book');
|
||
prepareDeck();
|
||
updateCard();
|
||
// Dark mode initial
|
||
const darkPref = localStorage.getItem('darkMode') === 'true';
|
||
darkToggle.checked = darkPref;
|
||
document.body.classList.toggle('dark', darkPref);
|
||
// Splash init
|
||
initSplash();
|
||
// Service Worker
|
||
registerSW();
|
||
});
|
||
|
||
// Event‑Listener für Mode‑Änderungen
|
||
modeSelect.addEventListener('change', () => {
|
||
const mode = modeSelect.value;
|
||
topicSelect.classList.toggle('hidden', mode !== 'topic');
|
||
bookSelect.classList.toggle('hidden', mode !== 'book');
|
||
prepareDeck();
|
||
updateCard();
|
||
});
|
||
|
||
topicSelect.addEventListener('change', () => {
|
||
prepareDeck();
|
||
updateCard();
|
||
});
|
||
bookSelect.addEventListener('change', () => {
|
||
prepareDeck();
|
||
updateCard();
|
||
});
|
||
|
||
// Hint toggles
|
||
commentHint.addEventListener('change', () => {
|
||
updateCard();
|
||
});
|
||
keywordHint.addEventListener('change', () => {
|
||
updateCard();
|
||
});
|
||
|
||
if (themeHint) {
|
||
themeHint.addEventListener('change', () => {
|
||
updateCard();
|
||
});
|
||
}
|
||
|
||
// Card click – flip
|
||
cardEl.addEventListener('click', () => {
|
||
if (deck.length === 0) return;
|
||
cardEl.classList.toggle('flipped');
|
||
});
|
||
|
||
// Korrekt/Wrong Buttons
|
||
correctBtn.addEventListener('click', () => {
|
||
if (deck.length === 0) return;
|
||
// Aktuelle Karte
|
||
const item = deck[currentIndex];
|
||
const theme = item['Thema'];
|
||
const key = getCardKey(item);
|
||
// Session‑Counter erhöhen
|
||
correctCount++;
|
||
// Fortschrittsdaten pro Thema aktualisieren
|
||
if (!progressData[theme]) progressData[theme] = { correct: 0, wrong: 0 };
|
||
progressData[theme].correct++;
|
||
// Per‑Karten‑Statistik aktualisieren
|
||
if (!cardStats[key]) cardStats[key] = { correct: 0, wrong: 0 };
|
||
cardStats[key].correct++;
|
||
// Speichern in localStorage
|
||
try {
|
||
localStorage.setItem('progressData', JSON.stringify(progressData));
|
||
localStorage.setItem('cardStats', JSON.stringify(cardStats));
|
||
} catch (e) {
|
||
console.warn('Speichern der Zählerdaten fehlgeschlagen:', e);
|
||
}
|
||
nextCard();
|
||
});
|
||
wrongBtn.addEventListener('click', () => {
|
||
if (deck.length === 0) return;
|
||
// Aktuelle Karte
|
||
const item = deck[currentIndex];
|
||
const theme = item['Thema'];
|
||
const key = getCardKey(item);
|
||
// Fortschrittsdaten pro Thema aktualisieren
|
||
if (!progressData[theme]) progressData[theme] = { correct: 0, wrong: 0 };
|
||
progressData[theme].wrong++;
|
||
// Per‑Karten‑Statistik aktualisieren
|
||
if (!cardStats[key]) cardStats[key] = { correct: 0, wrong: 0 };
|
||
cardStats[key].wrong++;
|
||
// Speichern in localStorage
|
||
try {
|
||
localStorage.setItem('progressData', JSON.stringify(progressData));
|
||
localStorage.setItem('cardStats', JSON.stringify(cardStats));
|
||
} catch (e) {
|
||
console.warn('Speichern der Zählerdaten fehlgeschlagen:', e);
|
||
}
|
||
nextCard();
|
||
});
|
||
|
||
// Dark mode toggle
|
||
darkToggle.addEventListener('change', handleDarkModeChange);
|
||
|
||
// Splash‑Screen Buttons
|
||
continueBtn.addEventListener('click', () => {
|
||
splashScreen.classList.add('hidden');
|
||
localStorage.setItem('splashDismissed', 'true');
|
||
});
|
||
installBtn.addEventListener('click', async () => {
|
||
if (deferredPrompt) {
|
||
deferredPrompt.prompt();
|
||
const result = await deferredPrompt.userChoice;
|
||
console.log('Install result:', result);
|
||
deferredPrompt = null;
|
||
}
|
||
splashScreen.classList.add('hidden');
|
||
localStorage.setItem('splashDismissed', 'true');
|
||
});
|
||
|
||
// beforeinstallprompt event
|
||
window.addEventListener('beforeinstallprompt', e => {
|
||
// Verhindere die Standard‑Banneranzeige
|
||
e.preventDefault();
|
||
deferredPrompt = e;
|
||
// Falls der Splash noch sichtbar ist, zeige Install‑Button
|
||
installBtn.style.display = 'inline-block';
|
||
});
|
||
})(); |