`;
let scheduleTableHtml = `# Date Payment Principal Interest Balance Cum. Int. `;
schedule.forEach(row => {
scheduleTableHtml += `${row.month} ${row.date} ${frm_formatCurrency(row.payment)}
${frm_formatCurrency(row.principal)} ${frm_formatCurrency(row.interest)}
${frm_formatCurrency(row.balance)} ${frm_formatCurrency(row.cumulativeInterest)} `;
});
scheduleTableHtml += `Totals
${frm_formatCurrency(summary.totalPIPayments)}
${frm_formatCurrency(inputs.loanPrincipal)}
${frm_formatCurrency(summary.totalInterestPaid)}
`;
const interpretationNote_pdf = `Estimates based on inputs. Actual taxes/insurance can change. Consult lenders for precise terms.`;
pdfContentEl.innerHTML = `
${scheduleTableHtml}
Fixed-Rate Mortgage Analysis
${summaryHtmlPdf}
Amortization Schedule
Note: ${interpretationNote_pdf}
`;
document.body.appendChild(pdfContentEl);
// Check if table might need landscape
let orientation = 'p';
const tableElementForCheck = pdfContentEl.querySelector('.pdf-table');
if (tableElementForCheck && tableElementForCheck.offsetWidth > 550 && schedule.length > 15) { // Arbitrary check if table is wide and long
orientation = 'l';
pdf = new jsPDF(orientation, 'pt', 'a4'); // Re-init with landscape
pdfContentEl.style.width = pdf.internal.pageSize.getWidth() - 80 + 'pt';
}
html2canvas(pdfContentEl, { scale: 2, useCORS: true, logging:true, width: pdfContentEl.scrollWidth, windowHeight: pdfContentEl.scrollHeight }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdfPageWidth = pdf.internal.pageSize.getWidth();
const pdfPageHeight = pdf.internal.pageSize.getHeight();
const pageMargin = 30;
const contentWidth = pdfPageWidth - 2 * pageMargin;
// Calculate how much of the canvas height corresponds to one PDF page height, maintaining aspect ratio
const singlePageCanvasHeightEquivalent = (pdfPageHeight - 2 * pageMargin) * (canvas.width / contentWidth);
let numPages = Math.ceil(canvas.height / singlePageCanvasHeightEquivalent);
for (let i = 0; i < numPages; i++) {
if (i > 0) pdf.addPage();
let sourceY = i * singlePageCanvasHeightEquivalent;
// Ensure sourceHeight doesn't exceed the actual canvas height remaining
let sourceHeight = Math.min(singlePageCanvasHeightEquivalent, canvas.height - sourceY);
// Create a temporary canvas for the current page's slice
const pageCanvas = document.createElement('canvas');
pageCanvas.width = canvas.width;
pageCanvas.height = sourceHeight;
const ctx = pageCanvas.getContext('2d');
ctx.drawImage(canvas, 0, sourceY, canvas.width, sourceHeight, 0, 0, canvas.width, sourceHeight);
const pageImgData = pageCanvas.toDataURL('image/png');
// Calculate the height of this image slice when fit to PDF page width
const pageImgHeight = (sourceHeight * contentWidth) / canvas.width;
pdf.addImage(pageImgData, 'PNG', pageMargin, pageMargin, contentWidth, pageImgHeight, undefined, 'FAST');
}
pdf.save('Fixed_Rate_Mortgage_Analysis.pdf');
if(document.body.contains(pdfContentEl)) document.body.removeChild(pdfContentEl);
}).catch(err => {
console.error("FRM PDF Error:", err); alert("Error generating PDF. See console.");
if(document.body.contains(pdfContentEl)) document.body.removeChild(pdfContentEl);
});
}
document.addEventListener('DOMContentLoaded', function() {
frm_handleLoanTermChange(); // Initialize custom term field visibility
frm_updateDpInputLabel(); // Initialize DP input placeholder
// Default some values for quicker testing
const homePriceEl = document.getElementById('frm_homePrice');
if (homePriceEl && !homePriceEl.value) homePriceEl.value = '300000';
const dpValueEl = document.getElementById('frm_dpValue');
if (dpValueEl && !dpValueEl.value) dpValueEl.value = '20'; // Assuming %
const rateEl = document.getElementById('frm_annualInterestRate');
if (rateEl && !rateEl.value) rateEl.value = '6.5';
const taxesEl = document.getElementById('frm_annualPropertyTaxes');
if (taxesEl && !taxesEl.value) taxesEl.value = '3600';
const insuranceEl = document.getElementById('frm_annualHomeInsurance');
if (insuranceEl && !insuranceEl.value) insuranceEl.value = '1200';
const startDateEl = document.getElementById('frm_loanStartDate');
if (startDateEl && !startDateEl.value) {
const today = new Date();
const nextMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1);
startDateEl.value = nextMonth.toISOString().split('T')[0];
}
if (!document.getElementById('frm_homePrice')) {
console.error("Critical input 'frm_homePrice' not found.");
}
});
