Science Class Syllabus Generator

Science Class Syllabus Generator

Course Syllabus

Go to the "Configuration" tab to input details and generate the syllabus.

Course Information

Units & Modules Breakdown

Current Modules

No units added yet.

"; return; } modules.forEach(m => { const itemEl = document.createElement("div"); itemEl.className = "scsg-config-list-item"; itemEl.dataset.id = m.id; itemEl.innerHTML = ` ${escapeHTML(m.title)} (${m.duration} Weeks) `; configModuleList.appendChild(itemEl); }); } // --- Dashboard Management --- function renderDashboard() { // Get all editable content from config inputs const data = { courseName: configCourseName.value || "[Course Name]", teacher: configTeacher.value || "[Teacher Name]", room: configRoom.value || "[Room/Period]", year: configYear.value || "[Year]", desc: configDesc.value || "[Course Description]", grading: configGrading.value || "[Grading Policy]", objectives: configObjectives.value || "[Learning Objectives]", }; // --- Build Dashboard HTML --- dashboardOutput.innerHTML = `

${escapeHTML(data.courseName)} Syllabus (${escapeHTML(data.year)})

Unit Breakdown & Timeline

Unit/Module Duration (Weeks) Major Assessment Action
`; // Populate Unit Table const tbody = dashboardOutput.querySelector('#scsg-dash-units tbody'); modules.forEach(m => { const tr = document.createElement('tr'); tr.dataset.id = m.id; tr.innerHTML = ` `; tbody.appendChild(tr); }); setupDashboardListeners(); showTab('scsg-tab-dashboard'); } /** * Attaches listeners to the newly rendered dashboard elements for editing/removal */ function setupDashboardListeners() { const table = dashboardOutput.querySelector('#scsg-dash-units'); if (!table) return; // Event delegation for removal table.addEventListener('click', (e) => { if (e.target.dataset.action === 'remove-module') { const tr = e.target.closest('tr'); modules.splice(modules.findIndex(m => m.id === tr.dataset.id), 1); // Re-render dashboard to update the table entirely renderDashboard(); updateConfigModuleDisplay(); } }); // Event delegation for input/change updates table.addEventListener('input', handleDashboardUpdate); table.addEventListener('change', handleDashboardUpdate); } /** * Handles updates made directly to the dashboard inputs/textareas/table cells */ function handleDashboardUpdate(e) { const target = e.target; const field = target.dataset.field; // 1. Handle Module Table Updates if (target.closest('#scsg-dash-units')) { const tr = target.closest('tr'); const moduleId = tr.dataset.id; const module = modules.find(m => m.id === moduleId); if (module && field) { module[field] = target.type === 'number' ? parseInt(target.value) : target.value; } return; } // 2. Handle Simple Textarea/Input Updates const map = { 'scsg-dash-teacher': configTeacher, 'scsg-dash-room': configRoom, 'scsg-dash-desc': configDesc, 'scsg-dash-objectives': configObjectives, 'scsg-dash-grading': configGrading }; const configInput = map[target.id]; if (configInput) { configInput.value = target.value; } } /** * Generates a PDF report from the dashboard data */ function downloadPDF() { if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF.autoTable === 'undefined') { alert("Error: PDF library could not be loaded. Please try again."); return; } try { const { jsPDF } = window.jspdf; const doc = new jsPDF("p", "pt", "a4"); const margin = 40; let yPos = margin; // Get final edited data from the dashboard inputs/textareas const courseName = configCourseName.value || "Course Syllabus"; const courseYear = configYear.value || "Year"; const teacher = dashboardOutput.querySelector("#scsg-dash-teacher")?.value || ""; const room = dashboardOutput.querySelector("#scsg-dash-room")?.value || ""; const desc = dashboardOutput.querySelector("#scsg-dash-desc")?.value || "N/A"; const objectives = dashboardOutput.querySelector("#scsg-dash-objectives")?.value || "N/A"; const grading = dashboardOutput.querySelector("#scsg-dash-grading")?.value || "N/A"; // Get Table Data const tableBody = Array.from(dashboardOutput.querySelectorAll('#scsg-dash-units tbody tr')).map(tr => [ tr.querySelector('[data-field="title"]')?.value || '', tr.querySelector('[data-field="duration"]')?.value || '', tr.querySelector('[data-field="assessment"]')?.value || '' ]); // --- PDF Title & Header --- doc.setFontSize(20); doc.setFont(undefined, 'bold'); doc.text(courseName, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 20; doc.setFontSize(14); doc.text(`Syllabus (${courseYear})`, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 30; doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.text(`Teacher: ${teacher}`, margin, yPos); doc.text(`Room/Period: ${room}`, margin + 200, yPos); yPos += 25; // Function to add a section with title and text function addSection(title, content) { const textLines = doc.splitTextToSize(content, doc.internal.pageSize.getWidth() - margin * 2); const textHeight = textLines.length * 12; if (yPos > doc.internal.pageSize.getHeight() - 80) { doc.addPage(); yPos = margin; } doc.setFontSize(14); doc.setFont(undefined, 'bold'); doc.text(title, margin, yPos); yPos += 18; doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.text(textLines, margin, yPos); yPos += textHeight + 15; } // 1. Course Description addSection('Course Description', desc); // 2. Learning Objectives addSection('Learning Objectives', objectives); // 3. Grading Policy addSection('Grading Policy', grading); // 4. Unit Breakdown Table if (tableBody.length > 0) { if (yPos > doc.internal.pageSize.getHeight() - 150) { doc.addPage(); yPos = margin; } doc.setFontSize(14); doc.setFont(undefined, 'bold'); doc.text('Unit Breakdown & Timeline', margin, yPos); yPos += 20; doc.autoTable({ startY: yPos, head: [['Unit/Module', 'Duration (Weeks)', 'Major Assessment']], body: tableBody, theme: 'striped', headStyles: { fillColor: [0, 115, 230], textColor: [255, 255, 255], fontSize: 10 }, styles: { fontSize: 9, cellPadding: 4, overflow: 'linebreak' }, columnStyles: { 0: { cellWidth: 180 }, 1: { cellWidth: 80, halign: 'center' }, 2: { cellWidth: 'auto' } }, margin: { left: margin, right: margin } }); } doc.save(`${courseName.replace(/ /g,"_")}_Syllabus_${courseYear}.pdf`); } catch (error) { console.error("PDF Generation Error:", error); alert("An error occurred during PDF creation. Please ensure all data fields are filled correctly."); } } /** * Helper to escape HTML */ function escapeHTML(str) { if (!str) return ""; return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // --- 4. INITIALIZATION & EVENT LISTENERS --- // Tab Listeners tabButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); navButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); // Config Tab Listeners if (addModuleForm) { addModuleForm.addEventListener("submit", handleAddModule); } if (configModuleList) { configModuleList.addEventListener("click", handleRemoveModule); } if (generateBtn) { generateBtn.addEventListener("click", renderDashboard); } // PDF Button if (pdfBtn) { pdfBtn.addEventListener("click", downloadPDF); } // Initial config list display updateConfigModuleDisplay(); // Initial State: Generate dashboard with samples renderDashboard(); showTab("scsg-tab-dashboard"); });
Scroll to Top