`;
} else {
sections.forEach(sectionTitle => {
const section = document.createElement('div');
section.className = 'apg-poster-section';
section.innerHTML = `
${apg_escapeHTML(sectionTitle) || 'Untitled Section'}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam...
`; column.appendChild(section); }); } body.appendChild(column); } targetDiv.appendChild(body); } /** * Reads all values from the config tab and updates the apg_data object */ function apg_updateDataFromConfig() { if (!apg_inputTitle) return; apg_data.title = apg_inputTitle.value; apg_data.authors = apg_inputAuthors.value; apg_data.columnCount = parseInt(apg_inputColumns.value, 10); apg_data.columns = []; const columnBuckets = apg_columnConfigContainer.querySelectorAll('.apg-sections-list'); columnBuckets.forEach(bucket => { const colIndex = parseInt(bucket.getAttribute('data-col-index'), 10); apg_data.columns[colIndex] = []; const inputs = bucket.querySelectorAll('.apg-section-input'); inputs.forEach(input => { if (input.value) { apg_data.columns[colIndex].push(input.value); } }); }); } /** * Generates and downloads a PDF of the dashboard */ async function apg_downloadPDF() { // Check for required libraries if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') { console.error("APG Tool Error: jsPDF or html2canvas library not loaded."); alert("Error: PDF libraries failed to load. Please check console."); return; } // 1. Create a high-res, off-screen clone const pdfClone = document.createElement('div'); document.body.appendChild(pdfClone); // 2. Render the full-size poster into the clone apg_renderDashboard(pdfClone, true); const { jsPDF } = window.jspdf; // Poster dimensions (16:9) const posterWidth = 1600; const posterHeight = 900; try { // 3. Render canvas from the clone const canvas = await html2canvas(pdfClone, { scale: 2, // Use 2x scale on 1600px for 3200px image useCORS: true, width: posterWidth, height: posterHeight, windowWidth: posterWidth, windowHeight: posterHeight }); const imgData = canvas.toDataURL('image/png'); // 4. Create a landscape PDF // Use 'px' units, and match the dimensions. // A4 landscape is approx 842 x 595 pt. // Let's use a standard 16:9 ratio in 'pt' const pdfWidth = 842; const pdfHeight = (842 * 9) / 16; // 473.625 const pdf = new jsPDF({ orientation: 'l', // landscape unit: 'pt', format: [pdfWidth, pdfHeight] }); // 5. Add image to PDF, covering the whole page pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight); const safeName = (apg_data.title || 'poster_layout').replace(/[^a-z0-9]/gi, '_').toLowerCase(); pdf.save(`${safeName}.pdf`); } catch (error) { console.error("APG Tool Error: PDF generation failed.", error); alert("An error occurred while generating the PDF. Please try again."); } finally { // 6. Remove the clone document.body.removeChild(pdfClone); } } /** * Utility to escape HTML for display */ function apg_escapeHTML(str) { if (typeof str !== 'string') return ''; return str.replace(/[&<>"']/g, function(m) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m]; }); } // --- EVENT LISTENERS --- // Tab link clicks apg_tabLinks.forEach((link, index) => { link.addEventListener('click', () => apg_switchTab(index)); }); // Next/Prev button clicks if (apg_prevButton) { apg_prevButton.addEventListener('click', () => { if (apg_currentTab > 0) apg_switchTab(apg_currentTab - 1); }); } if (apg_nextButton) { apg_nextButton.addEventListener('click', () => { if (apg_currentTab < apg_tabLinks.length - 1) apg_switchTab(apg_currentTab + 1); }); } // PDF download if (apg_downloadPdfButton) { apg_downloadPdfButton.addEventListener('click', apg_downloadPDF); } // Column count change if (apg_inputColumns) { apg_inputColumns.addEventListener('change', () => { apg_updateDataFromConfig(); // Save what we have apg_data.columnCount = parseInt(apg_inputColumns.value, 10); // Update count apg_renderConfig(); // Re-render config buckets }); } // Auto-update dashboard on config changes if (apg_configTab) { apg_configTab.addEventListener('change', () => { apg_updateDataFromConfig(); if (apg_currentTab === 0) { apg_renderDashboard(); } }); // Also listen for 'keyup' for faster feedback on text inputs apg_configTab.addEventListener('keyup', (e) => { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') { apg_updateDataFromConfig(); if (apg_currentTab === 0) { apg_renderDashboard(); } } }); } // --- INITIALIZATION --- apg_initSampleData(); apg_renderConfig(); apg_renderDashboard(); });