Scientific Biography Sheet Generator

Scientific Biography Sheet Generator

Scientific Biography Sheet Generator

Compile key personal, academic, and professional details for any scientist.

Review the structured biography sheet below. It's organized into four key sections for comprehensive documentation.

${legacyFormatted || 'N/A'}

`; } function sbg_renderDashboard(targetDiv = sbg_dashboardOutput, isPDF = false) { if (!targetDiv) return; targetDiv.innerHTML = sbg_generateBiographyHTML(sbg_data); } // --- PDF Generation and Management --- function sbg_renderPdfClone() { const biographyHTML = sbg_generateBiographyHTML(sbg_data); sbg_pdfRenderClone.innerHTML = `
${biographyHTML}
`; } /** * Generates and downloads a PDF of the biography sheet */ async function sbg_downloadPDF() { if (!sbg_data.fullName) { alert("Please enter the scientist's full name before downloading."); return; } if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') { alert("Error: PDF libraries failed to load."); return; } sbg_renderPdfClone(); const { jsPDF } = window.jspdf; try { const contentDiv = sbg_pdfRenderClone.querySelector('.pdf-content'); if (!contentDiv) return; const canvas = await html2canvas(contentDiv, { scale: 1.5, useCORS: true }); const imgData = canvas.toDataURL('image/png'); const imgProps = { width: canvas.width, height: canvas.height }; const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const margin = 40; const contentWidth = pdfWidth - (margin * 2); const contentHeight = (contentWidth * imgProps.height) / imgProps.width; let heightLeft = contentHeight; let position = 0; pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight); heightLeft -= (pdfHeight - margin * 2); while (heightLeft > 0) { position -= (pdfHeight - margin * 2); pdf.addPage(); pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight); heightLeft -= (pdfHeight - margin * 2); } const safeName = (sbg_data.fullName || 'scientist').replace(/[^a-z0-9]/gi, '_').toLowerCase(); pdf.save(`${safeName}_Biography.pdf`); } catch (error) { console.error("PDF generation failed:", error); alert("An error occurred while generating the PDF."); } } // --- EVENT LISTENERS --- // Tab link clicks sbg_tabLinks.forEach((link, index) => { link.addEventListener('click', () => sbg_switchTab(index)); }); // Next/Prev button clicks if (sbg_prevButton) { sbg_prevButton.addEventListener('click', () => { if (sbg_currentTab > 0) sbg_switchTab(sbg_currentTab - 1); }); } if (sbg_nextButton) { sbg_nextButton.addEventListener('click', () => { if (sbg_currentTab === sbg_tabLinks.length - 1) { sbg_updateDataFromConfig(); sbg_switchTab(0); } else { if (sbg_currentTab < sbg_tabLinks.length - 1) sbg_switchTab(sbg_currentTab + 1); } }); } // PDF download if (sbg_downloadPdfButton) { sbg_downloadPdfButton.addEventListener('click', sbg_downloadPDF); } // --- Config Tab Listeners (Contributions) --- if (sbg_addContributionButton) { sbg_addContributionButton.addEventListener('click', () => { sbg_contributionsContainer.appendChild(sbg_createContributionInput()); }); } // --- Config Tab Listeners (Degrees) --- if (sbg_addDegreeButton) { sbg_addDegreeButton.addEventListener('click', () => { sbg_degreesContainer.appendChild(sbg_createDegreeInput()); }); } if (sbg_configTab) { // Handle remove for contributions and degrees sbg_configTab.addEventListener('click', (e) => { const removeButton = e.target.closest('.sbg-remove-item'); if (removeButton) { removeButton.closest('.sbg-input-item').remove(); } }); } // --- INITIALIZATION --- sbg_renderConfig(); sbg_renderDashboard(); // Set initial tab state sbg_tabPanes.forEach((pane, index) => { pane.classList.toggle('hidden', index !== 0); pane.classList.toggle('sbg-active', index === 0); }); sbg_tabLinks.forEach((link, index) => { TAB_CLASSES.active.forEach(cls => link.classList.remove(cls)); TAB_CLASSES.inactive.forEach(cls => link.classList.remove(cls)); if (index === 0) { TAB_CLASSES.active.forEach(cls => link.classList.add(cls)); } else { TAB_CLASSES.inactive.forEach(cls => link.classList.add(cls)); } }); });
Scroll to Top