CSuperCentral.org

Card-based Super Central Studying by Topic

Settings

Scenario Card

Front Card

Back Card

Global

Content: No Content Loaded Theme: Default Theme
// Global state let currentContentFileName = "Attempting to load LE5.JSON..."; let currentThemeFileName = "Default Theme"; let currentThemeIsCustom = false; // Path logic: index.html is in CardSuper/ and LE5.JSON is in CardSuper/public/ const getAssetPath = (filename) => { const currentPath = window.location.pathname; const directory = currentPath.substring(0, currentPath.lastIndexOf('/')); return `${directory}/public/${filename}`; }; const CONTENT_URL = getAssetPath('LE5.JSON'); const THEME_URL = getAssetPath('default3.thm'); // --- Core Card Logic --- function flipCard(cardElement) { const frontFace = cardElement.querySelector('.flashcard-front'); const backFace = cardElement.querySelector('.flashcard-back'); cardElement.classList.toggle('flipped'); setTimeout(() => { const isFlipped = cardElement.classList.contains('flipped'); if (frontFace) { frontFace.style.opacity = isFlipped ? '0' : '1'; frontFace.style.pointerEvents = isFlipped ? 'none' : 'auto'; } if (backFace) { backFace.style.opacity = isFlipped ? '1' : '0'; backFace.style.pointerEvents = isFlipped ? 'auto' : 'none'; } }, 300); } function renderDeck(contentData) { const mainContentArea = document.getElementById('main-content-area'); if (!mainContentArea) return; mainContentArea.innerHTML = ''; if (!contentData || contentData.length === 0) { mainContentArea.innerHTML = `
No content found at ${CONTENT_URL}
`; return; } contentData.forEach(section => { const physicsSection = document.createElement('div'); physicsSection.className = 'physics-section'; const scenarioBox = document.createElement('div'); scenarioBox.className = 'scenario-box scenario-toggle'; scenarioBox.innerHTML = `

${section.title} +

${section.description ? `

${section.description}

` : ''}`; physicsSection.appendChild(scenarioBox); const flashcardsGroup = document.createElement('div'); flashcardsGroup.className = 'flashcards-group'; section.cards.forEach(card => { const container = document.createElement('div'); container.className = 'flashcard-container'; const flashcard = document.createElement('div'); flashcard.className = 'flashcard'; flashcard.onclick = function() { flipCard(this); }; const createFace = (data, type) => { const face = document.createElement('div'); face.className = `flashcard-face flashcard-${type}`; face.innerHTML = `

${data.heading}

`; const contentDiv = document.createElement('div'); contentDiv.className = 'flashcard-content'; data.content.forEach(block => { if (block.type === 'paragraph') { const p = document.createElement('p'); p.innerHTML = block.text; contentDiv.appendChild(p); } else if (block.type === 'list') { const ul = document.createElement('ul'); block.items.forEach(item => ul.innerHTML += `
  • ${item}
  • `); contentDiv.appendChild(ul); } else if (block.type === 'equation') { const div = document.createElement('div'); div.className = 'latex-math'; div.innerHTML = block.latex; contentDiv.appendChild(div); } else if (block.type === 'image') { const img = document.createElement('img'); img.className = 'flashcard-image'; img.src = block.src; img.onerror = function() { this.src='https://placehold.co/600x400?text=Image+Not+Found'; }; contentDiv.appendChild(img); } }); face.appendChild(contentDiv); return face; }; flashcard.appendChild(createFace(card.front, 'front')); flashcard.appendChild(createFace(card.back, 'back')); container.appendChild(flashcard); flashcardsGroup.appendChild(container); }); physicsSection.appendChild(flashcardsGroup); mainContentArea.appendChild(physicsSection); scenarioBox.addEventListener('click', () => { physicsSection.classList.toggle('expanded'); scenarioBox.querySelector('.expand-icon').textContent = physicsSection.classList.contains('expanded') ? '−' : '+'; }); }); if (window.MathJax) MathJax.typesetPromise().catch(err => console.log(err)); } // --- Theme and Data Fetching --- async function initStartup() { // Load Theme try { const tRes = await fetch(THEME_URL); if (tRes.ok) { const theme = await tRes.json(); applyTheme(theme); currentThemeFileName = "default3"; } } catch (e) { console.error("Theme load failed"); } // Load Content try { const cRes = await fetch(CONTENT_URL); if (!cRes.ok) throw new Error("Fetch failed"); const content = await cRes.json(); renderDeck(content); currentContentFileName = "LE5"; } catch (e) { console.error("Content load failed:", e); currentContentFileName = "LE5.JSON missing in public/"; renderDeck([]); } updateFileNameDisplays(); } function applyTheme(theme) { const root = document.documentElement; const vars = { 'globalTextColor': '--global-text-color', 'globalBgColor': '--global-background-color', 'scenarioTextColor': '--scenario-box-text-color', 'scenarioBgColor': '--scenario-box-bg-color', 'frontCardTextColor': '--flashcard-front-text-color', 'frontCardBgColor': '--flashcard-front-bg-color', 'frontCardBorderColor': '--flashcard-front-border-color', 'backCardTextColor': '--flashcard-back-text-color', 'backCardBgColor': '--flashcard-back-bg-color', 'backCardBorderColor': '--flashcard-back-border-color' }; Object.keys(vars).forEach(key => { if (theme[key]) { root.style.setProperty(vars[key], theme[key]); if (document.getElementById(key)) document.getElementById(key).value = theme[key]; } }); if (theme.textSize) { document.getElementById('textSize').value = theme.textSize; updateFontSizes(); } } function updateFontSizes() { const val = document.getElementById('textSize').value; const size = 16 + (64 - 16) * ((val - 100) / 300); document.documentElement.style.fontSize = `${size}px`; } function updateFileNameDisplays() { document.getElementById('loadedContentFileName').textContent = currentContentFileName; document.getElementById('currentThemeName').textContent = currentThemeIsCustom ? "Custom" : currentThemeFileName; } // --- Event Listeners --- document.addEventListener('DOMContentLoaded', () => { const inputs = ['globalTextColor','globalBgColor','scenarioTextColor','scenarioBgColor','frontCardTextColor','frontCardBgColor','frontCardBorderColor','backCardTextColor','backCardBgColor','backCardBorderColor']; inputs.forEach(id => { document.getElementById(id).addEventListener('input', (e) => { const prop = `--${id.replace(/[A-Z]/g, m => "-" + m.toLowerCase())}`; document.documentElement.style.setProperty(prop, e.target.value); currentThemeIsCustom = true; updateFileNameDisplays(); }); }); document.getElementById('textSize').addEventListener('input', () => { updateFontSizes(); currentThemeIsCustom = true; updateFileNameDisplays(); }); document.getElementById('loadContentBtn').addEventListener('click', () => document.getElementById('contentFileInput').click()); document.getElementById('contentFileInput').addEventListener('change', (e) => { const reader = new FileReader(); reader.onload = (ev) => { renderDeck(JSON.parse(ev.target.result)); currentContentFileName = e.target.files[0].name; updateFileNameDisplays(); }; reader.readAsText(e.target.files[0]); }); document.getElementById('loadThemeBtn').addEventListener('click', () => document.getElementById('themeFileInput').click()); document.getElementById('themeFileInput').addEventListener('change', (e) => { const reader = new FileReader(); reader.onload = (ev) => { applyTheme(JSON.parse(ev.target.result)); currentThemeFileName = e.target.files[0].name; currentThemeIsCustom = false; updateFileNameDisplays(); }; reader.readAsText(e.target.files[0]); }); document.getElementById('saveThemeBtn').addEventListener('click', () => { const theme = { textSize: document.getElementById('textSize').value }; inputs.forEach(id => theme[id] = document.getElementById(id).value); const a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([JSON.stringify(theme, null, 2)], {type: 'application/json'})); a.download = "theme.thm"; a.click(); }); document.getElementById('settings-toggle').addEventListener('click', () => { document.getElementById('settings-section').classList.toggle('expanded'); document.querySelector('#settings-toggle .expand-icon').textContent = document.getElementById('settings-section').classList.contains('expanded') ? '−' : '+'; }); document.getElementById('returnToTopBtn').addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' })); // Start everything initStartup(); document.getElementById('settings-section').classList.add('expanded'); });