/** * js/curso.js * Lógica del visor de curso: sidebar, carga de markdown y navegación. * Depende de: js/temas.js + marked.js (CDN) */ // ── Estado ────────────────────────────────────────────────── let currentBloque = 1; let currentTema = 1; // ── Init ──────────────────────────────────────────────────── document.addEventListener('DOMContentLoaded', () => { const params = new URLSearchParams(location.search); currentBloque = parseInt(params.get('bloque') || '1', 10); currentTema = parseInt(params.get('tema') || '1', 10); buildSidebar(); loadTema(currentBloque, currentTema); }); // ── Build sidebar ─────────────────────────────────────────── function buildSidebar() { const sidebar = document.querySelector('.sidebar'); if (!sidebar) return; let html = ''; for (const bloque of TEMARIO) { const isOpenBloque = (bloque.id === currentBloque); html += `
Bloque ${toRoman(bloque.id)}
`; for (const tema of bloque.temas) { const isActive = (bloque.id === currentBloque && tema.num === currentTema); const shortTitle = shortTemaTitle(tema.titulo); html += ` `; } html += `
`; } sidebar.innerHTML = html; } // ── Toggle bloque ──────────────────────────────────────────── function toggleBloque(id) { const group = document.getElementById(`bloque-group-${id}`); if (group) group.classList.toggle('open'); } // ── Navigate ───────────────────────────────────────────────── function navigateTo(bloqueId, temaNum) { currentBloque = bloqueId; currentTema = temaNum; const url = new URL(location.href); url.searchParams.set('bloque', bloqueId); url.searchParams.set('tema', temaNum); history.pushState({}, '', url.toString()); updateSidebarActive(); loadTema(bloqueId, temaNum); // Cerrar sidebar en móvil document.querySelector('.sidebar')?.classList.remove('open'); } // ── Load markdown ───────────────────────────────────────────── async function loadTema(bloqueId, temaNum) { const bloque = TEMARIO.find(b => b.id === bloqueId); if (!bloque) return showError('Bloque no encontrado.'); const tema = bloque.temas.find(t => t.num === temaNum); if (!tema) return showError('Tema no encontrado.'); const content = document.getElementById('lesson-content'); if (!content) return; content.innerHTML = '
'; try { const resp = await fetch(tema.archivo); if (!resp.ok) throw new Error(`HTTP ${resp.status}`); const md = await resp.text(); renderMarkdown(md, tema, bloque, bloqueId, temaNum); } catch (e) { showError(`No se ha podido cargar ${tema.archivo}.
${e.message}`); } } function renderMarkdown(md, tema, bloque, bloqueId, temaNum) { const { prev, next, pos, total } = getNavigation(bloqueId, temaNum); const prevBtn = prev ? `` : ``; const nextBtn = next ? `` : ``; const html = marked.parse(md); document.getElementById('lesson-content').innerHTML = `
${html}
`; // Actualizar título de pestaña document.title = `T${temaNum} – Bloque ${toRoman(bloqueId)} | TAI–AGE`; // Scroll arriba document.querySelector('.content-pane')?.scrollTo(0, 0); // Actualizar progress en topbar updateTopbarProgress(pos, total); } function showError(msg) { document.getElementById('lesson-content').innerHTML = `

Error cargando el tema

${msg}

`; } // ── Sidebar active ──────────────────────────────────────────── function updateSidebarActive() { document.querySelectorAll('.sidebar-item').forEach(el => el.classList.remove('active')); const el = document.getElementById(`item-${currentBloque}-${currentTema}`); if (el) { el.classList.add('active'); el.scrollIntoView({ block: 'nearest' }); } // Abrir bloque activo document.querySelectorAll('.bloque-group').forEach(g => g.classList.remove('open')); document.getElementById(`bloque-group-${currentBloque}`)?.classList.add('open'); } // ── Topbar progress ─────────────────────────────────────────── function updateTopbarProgress(pos, total) { const el = document.querySelector('.topbar-progress'); if (el) el.textContent = `${pos} / ${total}`; } // ── Hamburger (móvil) ───────────────────────────────────────── document.addEventListener('DOMContentLoaded', () => { const toggle = document.getElementById('menu-toggle'); if (toggle) { toggle.addEventListener('click', () => { document.querySelector('.sidebar').classList.toggle('open'); }); } // Cerrar sidebar al pulsar fuera (móvil) document.addEventListener('click', e => { if (window.innerWidth > 768) return; const sidebar = document.querySelector('.sidebar'); if (sidebar && !sidebar.contains(e.target) && e.target.id !== 'menu-toggle') { sidebar.classList.remove('open'); } }); }); // ── broswer back/forward ────────────────────────────────────── window.addEventListener('popstate', () => { const params = new URLSearchParams(location.search); currentBloque = parseInt(params.get('bloque') || '1', 10); currentTema = parseInt(params.get('tema') || '1', 10); updateSidebarActive(); loadTema(currentBloque, currentTema); }); // ── Helpers ─────────────────────────────────────────────────── function toRoman(n) { return ['', 'I', 'II', 'III', 'IV', 'V'][n] ?? n; } /** * Acorta el título del tema al primer fragmento antes de "." o ":" (máx 55 chars). */ function shortTemaTitle(titulo) { const first = titulo.split(/[.:–]/)[0].trim(); return first.length > 55 ? first.slice(0, 53) + '…' : first; }