/** * Export dashboard as PDF by capturing a screenshot of #dashboard-content * and assembling it into a multi-page PDF (html2canvas + jsPDF). */ function exportDashboardToPdf() { var el = document.getElementById('dashboard-content'); if (!el) { if (typeof console !== 'undefined' && console.warn) { console.warn('export-pdf: #dashboard-content not found'); } return; } var btn = document.getElementById('pdf-export-btn'); var originalText = btn ? btn.innerHTML : ''; if (btn) { btn.disabled = true; btn.innerHTML = 'Generating PDF…'; } var regionEl = document.getElementById('regionBadge'); var region = regionEl ? (regionEl.textContent || '').trim() : ''; if (typeof html2canvas === 'undefined' || typeof jspdf === 'undefined') { if (btn) { btn.disabled = false; btn.innerHTML = originalText; } alert('PDF export requires html2canvas and jsPDF. Please refresh the page.'); return; } var JsPDFConstructor = (typeof jspdf !== 'undefined' && jspdf.jsPDF) ? jspdf.jsPDF : jspdf; var auditSection = el.querySelector('section[aria-label="Audit analysis"]'); var auditSectionDisplay = ''; if (auditSection) { auditSectionDisplay = auditSection.style.display; auditSection.style.display = 'none'; } function restoreAuditSection() { if (auditSection) { auditSection.style.display = auditSectionDisplay; } } html2canvas(el, { scale: 2, useCORS: true, allowTaint: true, logging: false }).then(function(canvas) { var imgW = canvas.width; var imgH = canvas.height; var dataUrl = canvas.toDataURL('image/png'); var doc = new JsPDFConstructor({ orientation: 'portrait', unit: 'mm', format: 'a4' }); var pageW = 210; var pageH = 297; var margin = 10; var contentW = pageW - 2 * margin; var headerH = 14; var firstPageImgTop = margin + headerH; var firstPageImgH = pageH - firstPageImgTop - margin; var otherPageImgH = pageH - 2 * margin; var imgWmm = contentW; var imgHmm = contentW * (imgH / imgW); doc.setFontSize(14); doc.text('Dashboard report', margin, margin + 6); doc.setFontSize(10); doc.text(region ? 'Region: ' + region : '', margin, margin + 12); var shown = 0; var totalH = imgHmm; var pageNum = 0; var imgYmm = firstPageImgTop; while (shown < totalH) { if (pageNum > 0) { doc.addPage(); imgYmm = margin; } var sliceH = pageNum === 0 ? firstPageImgH : otherPageImgH; var yOffset = -shown; doc.addImage(dataUrl, 'PNG', margin, imgYmm + yOffset, imgWmm, imgHmm); shown += sliceH; pageNum += 1; } doc.save('dashboard-report.pdf'); restoreAuditSection(); if (btn) { btn.disabled = false; btn.innerHTML = originalText; } }).catch(function (err) { if (typeof console !== 'undefined' && console.error) { console.error('export-pdf:', err); } restoreAuditSection(); if (btn) { btn.disabled = false; btn.innerHTML = originalText; } alert('Failed to generate PDF. Please try again.'); }); }