Scientific Discovery Tracker Generator

Scientific Discovery Tracker Generator

Discovery Log (Editable)

# Name/Title Year Scientist(s) Field Impact Summary Action

Add New Discovery Entry

Current Entries in State

No discoveries added yet.

"; return; } discoveries.forEach(d => { const itemEl = document.createElement("div"); itemEl.className = "sdtg-config-list-item"; itemEl.dataset.id = d.id; itemEl.innerHTML = ` [${d.year}] ${escapeHTML(d.name)} (${escapeHTML(d.field)}) `; configList.appendChild(itemEl); }); } // --- Dashboard Management --- function renderDashboard() { if (!dashboardTbody) return; dashboardTbody.innerHTML = ""; // Clear if (discoveries.length === 0) { dashboardTbody.innerHTML = ` No discoveries logged yet. Add an entry in the Configuration tab. `; return; } discoveries.forEach((d, index) => { const tr = document.createElement('tr'); tr.dataset.id = d.id; tr.innerHTML = ` ${index + 1} `; dashboardTbody.appendChild(tr); }); setupDashboardListeners(); } /** * Attaches listeners to the dashboard table elements */ function setupDashboardListeners() { const table = dashboardTbody; if (!table) return; // Event delegation for removal table.addEventListener('click', (e) => { if (e.target.dataset.action === 'remove-dash-item') { const tr = e.target.closest('tr'); discoveries.splice(discoveries.findIndex(d => d.id === tr.dataset.id), 1); // Re-render entirely to renumber and update state renderDashboard(); updateConfigListDisplay(); } }); // Event delegation for input/change updates table.addEventListener('input', handleDashboardUpdate); table.addEventListener('change', handleDashboardUpdate); } /** * Handles updates made directly to the dashboard table cells */ function handleDashboardUpdate(e) { const target = e.target; const tr = target.closest('tr'); if (!tr) return; const dId = tr.dataset.id; const discovery = discoveries.find(d => d.id === dId); if (!discovery) return; const field = target.dataset.field; if (!field) return; // Update the master state array if (field === 'year') { discovery[field] = parseInt(target.value) || discovery[field]; } else { discovery[field] = target.value; } // Optional: Update config list display immediately updateConfigListDisplay(); } /** * Generates a PDF report from the dashboard data */ function downloadPDF() { if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF.autoTable === 'undefined') { alert("Error: PDF libraries could not be loaded. Please try again."); return; } if (discoveries.length === 0) { alert("The log is empty. Please add discoveries before downloading."); return; } try { const { jsPDF } = window.jspdf; const doc = new jsPDF("l", "pt", "a4"); // Landscape for wide table const margin = 40; doc.setFontSize(18); doc.setFont(undefined, 'bold'); doc.text("Scientific Discovery Log", margin, margin); doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.text(`Generated on: ${new Date().toLocaleDateString('en-US')}`, margin, margin + 20); const tableHead = [['#', 'Name/Title', 'Year', 'Scientist(s)', 'Field', 'Impact Summary']]; // Use the current state of the 'discoveries' array (which is kept in sync with the dashboard) const tableBody = discoveries.map((d, index) => [ index + 1, d.name, d.year, d.scientist, d.field, d.impact ]); doc.autoTable({ startY: margin + 40, head: tableHead, body: tableBody, theme: 'striped', headStyles: { fillColor: [0, 115, 230], textColor: [255, 255, 255], fontSize: 9 }, styles: { fontSize: 8, cellPadding: 3, overflow: 'linebreak' }, columnStyles: { 0: { cellWidth: 20, halign: 'center' }, 1: { cellWidth: 120 }, 2: { cellWidth: 40, halign: 'center' }, 3: { cellWidth: 100 }, 4: { cellWidth: 80 }, 5: { cellWidth: 'auto' } }, margin: { left: margin, right: margin } }); doc.save("Scientific_Discovery_Log.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 (addDiscoveryForm) { addDiscoveryForm.addEventListener("submit", handleAddDiscovery); } if (configList) { configList.addEventListener("click", handleRemoveConfigItem); } // PDF Button if (pdfBtn) { pdfBtn.addEventListener("click", downloadPDF); } // Initial config list display updateConfigListDisplay(); // Initial State: Generate dashboard with samples renderDashboard(); showTab("sdtg-tab-dashboard"); });
Scroll to Top