// รายการบทเรียนและไฟล์ที่สอดคล้องกัน
const lessons = [
{id: 'intro', title: 'บทนำ', file: 'lessons/00-intro.html'},
{id: 'html', title: 'HTML', file: 'lessons/01-html.html'},
{id: 'css', title: 'CSS', file: 'lessons/02-css.html'},
{id: 'javascript', title: 'JavaScript', file: 'lessons/03-javascript.html'},
{id: 'tools', title: 'Tools', file: 'lessons/04-tools.html'},
{id: 'database', title: 'ฐานข้อมูล', file: 'lessons/05-database.html'},
{id: 'responsive', title: 'Responsive Design', file: 'lessons/06-responsive.html'},
{id: 'next-steps', title: 'ก้าวต่อไป', file: 'lessons/07-next-steps.html'},
{id: 'api-fetch', title: 'API & Fetch', file: 'lessons/13-api-fetch.html'},
{id: 'accessibility', title: 'Accessibility', file: 'lessons/14-accessibility.html'}
];
// ฟังก์ชันสำหรับโหลดเนื้อหา
/* eslint-env browser */
/* global SyntaxHighlighterComponent, QuizEngine */
async function loadLesson(sectionId) {
const lesson = lessons.find(l => l.id === sectionId);
if (!lesson) {
console.error('ไม่พบบทเรียน:', sectionId);
return;
}
try {
const response = await fetch(lesson.file);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const content = await response.text();
// โหลดเนื้อหา
const contentLoader = document.getElementById('content-loader');
contentLoader.innerHTML = content;
// store the lesson file as base for resolving relative URLs inside the lesson
contentLoader.dataset.lessonFile = lesson.file || '';
// Playground: extract any <style> blocks from the lesson content and move them to <head>
try {
// remove previous lesson style if present
const prev = document.getElementById('lesson-inline-style');
if (prev) prev.remove();
const styleBlocks = contentLoader.querySelectorAll('style');
if (styleBlocks && styleBlocks.length) {
const combined = Array.from(styleBlocks).map(s => s.textContent).join('\n\n');
const styleEl = document.createElement('style');
styleEl.id = 'lesson-inline-style';
styleEl.dataset.lesson = lesson.id || '';
styleEl.appendChild(document.createTextNode(combined));
document.head.appendChild(styleEl);
// remove original style tags from content area to avoid duplication
styleBlocks.forEach(s => s.parentNode && s.parentNode.removeChild(s));
}
} catch (e) {
console.warn('Error extracting lesson styles:', e);
}
// อัปเดต Sidebar
updateSidebar(sectionId);
// อัปเดต Progress Bar
updateProgressBar(sectionId);
// Scroll ไปที่ด้านบน
document.querySelector('.main-content').scrollTop = 0;
// เพิ่ม Event Listener สำหรับปุ่มนำทาง
attachNavigationListeners();
// Initialize SyntaxHighlighterComponent for loaded content if available
if (window.SyntaxHighlighterComponent && typeof SyntaxHighlighterComponent.init === 'function') {
// small delay to ensure DOM elements are parsed
setTimeout(() => {
SyntaxHighlighterComponent.init();
}, 20);
}
// Inject Open-in-Editor / Run buttons under code blocks and quiz placeholders
try {
const codeBlocks = document.querySelectorAll('#content-loader pre > code');
codeBlocks.forEach(codeEl => {
const pre = codeEl.parentNode;
// Avoid adding duplicate buttons
if (pre.nextElementSibling && pre.nextElementSibling.classList.contains('code-actions')) return;
const actions = document.createElement('div');
actions.className = 'code-actions';
// If the code block has data-quiz attribute, create a holder for the quiz
if (codeEl.dataset.quiz) {
const quizHolder = document.createElement('div');
quizHolder.className = 'quiz-holder';
quizHolder.setAttribute('data-quiz-src', codeEl.dataset.quiz);
actions.appendChild(quizHolder);
}
pre.parentNode.insertBefore(actions, pre.nextSibling);
});
// Render quizzes for any quiz placeholders (fetch JSON and call renderQuiz)
const holders = document.querySelectorAll('#content-loader [data-quiz-src]');
holders.forEach(holder => {
const src = holder.getAttribute('data-quiz-src');
if (!src) return;
if (!window.QuizEngine || typeof QuizEngine.renderQuiz !== 'function') {
holder.innerHTML = '<div class="quiz-error">Quiz engine not available</div>';
return;
}
// resolve relative quiz paths against the lesson file
const baseFile = contentLoader.dataset.lessonFile || window.location.href;
let resolved;
try {
resolved = new URL(src, new URL(baseFile, window.location.href)).href;
} catch (e) {
// fallback to simple resolution
resolved = src;
}
console.debug('Loading quiz', src, 'resolved->', resolved);
fetch(resolved).then(r => {
if (!r.ok) throw new Error(`Failed to load quiz (${r.status})`);
return r.json();
}).then(data => {
QuizEngine.renderQuiz(holder, data);
}).catch(err => {
console.warn('Quiz load failed', err);
holder.innerHTML = '<div class="quiz-error">ไม่สามารถโหลดแบบทดสอบได้</div>';
});
});
} catch (e) {
console.warn('Error injecting editor buttons or quizzes', e);
}
} catch (error) {
console.error('Error loading lesson:', error);
document.getElementById('content-loader').innerHTML = `
<div class="warning">
<strong>⚠️ ข้อผิดพลาด:</strong> ไม่สามารถโหลดบทเรียนได้ กรุณาลองใหม่อีกครั้ง
</div>
`;
}
}
// ฟังก์ชันสำหรับอัปเดต Sidebar
function updateSidebar(sectionId) {
const sidebarItems = document.querySelectorAll('.sidebar-item');
sidebarItems.forEach(item => {
item.classList.remove('active');
});
const activeItem = document.querySelector(`[data-section="${sectionId}"]`);
if (activeItem) {
activeItem.classList.add('active');
}
}
// ฟังก์ชันสำหรับอัปเดต Progress Bar
function updateProgressBar(sectionId) {
const currentIndex = lessons.findIndex(l => l.id === sectionId);
const progress = ((currentIndex + 1) / lessons.length) * 100;
const progressFill = document.getElementById('progressFill');
progressFill.style.width = progress + '%';
}
// ฟังก์ชันสำหรับเพิ่ม Event Listener สำหรับปุ่มนำทาง
function attachNavigationListeners() {
const prevBtn = document.getElementById('prev-btn');
const nextBtn = document.getElementById('next-btn');
if (prevBtn) {
prevBtn.onclick = function(e) {
e.preventDefault();
const currentId = this.getAttribute('data-current');
const currentIndex = lessons.findIndex(l => l.id === currentId);
if (currentIndex > 0) {
loadLesson(lessons[currentIndex - 1].id);
}
};
}
if (nextBtn) {
nextBtn.onclick = function(e) {
e.preventDefault();
const currentId = this.getAttribute('data-current');
const currentIndex = lessons.findIndex(l => l.id === currentId);
if (currentIndex < lessons.length - 1) {
loadLesson(lessons[currentIndex + 1].id);
}
};
}
}
// Render sidebar dynamically from `lessons` array and attach handlers
function renderSidebar(activeId) {
const sidebar = document.getElementById('sidebar');
if (!sidebar) return;
sidebar.innerHTML = '';
lessons.forEach(lesson => {
const el = document.createElement('div');
el.className = 'sidebar-item';
el.setAttribute('data-section', lesson.id);
el.setAttribute('role', 'button');
el.setAttribute('tabindex', '0');
el.textContent = lesson.title || lesson.id;
if (lesson.id === activeId) el.classList.add('active');
// click handler
el.addEventListener('click', () => loadLesson(lesson.id));
// keyboard accessibility (Enter / Space)
el.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
loadLesson(lesson.id);
}
});
sidebar.appendChild(el);
});
}
// โหลดบทนำเมื่อหน้าเพจโหลด
document.addEventListener('DOMContentLoaded', function() {
// render the sidebar dynamically and load the intro lesson
renderSidebar('intro');
loadLesson('intro');
// Initialize SyntaxHighlighterComponent globally if available
if (window.SyntaxHighlighterComponent && typeof SyntaxHighlighterComponent.init === 'function') {
SyntaxHighlighterComponent.init();
}
});