let chartInstance = null; document.querySelectorAll('[data-dollar]').forEach(function (input) { input.addEventListener('input', function () { var raw = this.value.replace(/[^0-9]/g, ''); if (raw === '') { this.value = ''; return; } this.value = parseInt(raw, 10).toLocaleString('en-US'); }); input.addEventListener('blur', function () { var raw = this.value.replace(/[^0-9]/g, ''); if (raw === '') { this.value = '0'; } else { this.value = parseInt(raw, 10).toLocaleString('en-US'); } }); }); document.getElementById('calculator-form').addEventListener('submit', function (e) { e.preventDefault(); const resultsInflation = runProjection(true); const resultsNoInflation = runProjection(false); renderTable(resultsInflation, 'results-table-inflation'); renderTable(resultsNoInflation, 'results-table-noinflation'); renderChart(resultsInflation); document.getElementById('results').classList.remove('hidden'); }); function getVal(id) { var el = document.getElementById(id); var raw = el.value.replace(/[^0-9.]/g, ''); return parseFloat(raw) || 0; } function fmt(n) { return n.toLocaleString('en-US', { minimumFractionDigits: 0, maximumFractionDigits: 0 }); } function runProjection(useInflation) { const years = 30; const inflationFactor = useInflation ? 1 + getVal('inflation') / 100 : 1; const growthFactor = 1 + getVal('ror') / 100; const taxRate = getVal('tax-rate') / 100; let pretax = getVal('pretax-value'); let aftertax = getVal('aftertax-value'); let roth = getVal('roth-value'); let realEstate = getVal('realestate-value'); let pretaxSpend = getVal('pretax-spending'); let aftertaxSpend = getVal('aftertax-spending'); let rothSpend = getVal('roth-spending'); const rows = []; for (let y = 0; y <= years; y++) { const total = Math.round(pretax + aftertax + roth + realEstate); const prevTotal = rows.length > 0 ? rows[rows.length - 1].total : total; rows.push({ year: y, pretax: Math.round(pretax), aftertax: Math.round(aftertax), roth: Math.round(roth), realEstate: Math.round(realEstate), total: total, yoyGrowth: Math.round(total - prevTotal), pretaxSpend: Math.round(pretaxSpend), aftertaxSpend: Math.round(aftertaxSpend), rothSpend: Math.round(rothSpend), }); if (y === years) break; pretax = pretax * growthFactor; aftertax = aftertax * growthFactor; roth = roth * growthFactor; realEstate = realEstate * growthFactor; pretaxSpend = Math.min(pretaxSpend, pretax * (1 - taxRate)); pretax -= pretaxSpend / (1 - taxRate); pretax = Math.max(0, pretax); aftertaxSpend = Math.min(aftertaxSpend, aftertax); aftertax -= aftertaxSpend; aftertax = Math.max(0, aftertax); rothSpend = Math.min(rothSpend, roth); roth -= rothSpend; roth = Math.max(0, roth); pretaxSpend *= inflationFactor; aftertaxSpend *= inflationFactor; rothSpend *= inflationFactor; } return rows; } function renderTable(rows, tableId) { const tbody = document.querySelector('#' + tableId + ' tbody'); tbody.innerHTML = ''; rows.forEach(function (r) { const growthColor = r.yoyGrowth >= 0 ? 'color:#16a34a' : 'color:#dc2626'; const growthPrefix = r.yoyGrowth >= 0 ? '+$' : '-$'; const growthStr = r.year === 0 ? '—' : '' + growthPrefix + fmt(Math.abs(r.yoyGrowth)) + ''; const tr = document.createElement('tr'); tr.innerHTML = '