<script>
// DOM Elements
const amountSlider = document.getElementById('amount');
const rateSlider = document.getElementById('rate');
const tenureSlider = document.getElementById('tenure');
const tenureToggle = document.getElementById('tenure-toggle');
const amountBtns = document.querySelectorAll('.amount-btn');
// Display Elements
const amountDisplay = document.getElementById('amount-display');
const rateDisplay = document.getElementById('rate-display');
const tenureDisplay = document.getElementById('tenure-display');
const tenureUnit = document.getElementById('tenure-unit');
// Result Elements
const emiResult = document.getElementById('emi-result');
const principalResult = document.getElementById('principal-result');
const interestResult = document.getElementById('interest-result');
const totalResult = document.getElementById('total-result');
let emiChart; // Keep track of our chart instance
// Function to format numbers in Indian currency format
const formatIndianCurrency = (num) => {
return new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: 'INR',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(num);
};
// Main EMI Calculation Logic
const calculateEMI = () => {
const P = parseFloat(amountSlider.value);
const annualRate = parseFloat(rateSlider.value);
const r = annualRate / 12 / 100; // Monthly interest rate
let n; // Tenure in months
if (tenureToggle.checked) { // Months selected
n = parseInt(tenureSlider.value);
} else { // Years selected
n = parseInt(tenureSlider.value) * 12;
}
// Update display values right away
amountDisplay.innerText = parseFloat(amountSlider.value).toLocaleString('en-IN');
rateDisplay.innerText = rateSlider.value;
tenureDisplay.innerText = tenureSlider.value;
if (P <= 0 || r <= 0 || n <= 0) {
emiResult.innerText = '₹ 0';
principalResult.innerText = formatIndianCurrency(P || 0);
interestResult.innerText = '₹ 0';
totalResult.innerText = formatIndianCurrency(P || 0);
updateChart(P || 0, 0);
return;
}
const emi = P * r * (Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
const totalPayment = emi * n;
const totalInterest = totalPayment - P;
// Update Results
emiResult.innerText = formatIndianCurrency(emi);
principalResult.innerText = formatIndianCurrency(P);
interestResult.innerText = formatIndianCurrency(totalInterest);
totalResult.innerText = formatIndianCurrency(totalPayment);
// Update Chart
updateChart(P, totalInterest);
};
// NEW: Resilient Chart Update Function
const updateChart = (principal, interest) => {
// Only try to update the chart if it exists
if (!emiChart) return;
try {
emiChart.data.datasets[0].data[0] = principal;
emiChart.data.datasets[0].data[1] = interest;
emiChart.update();
} catch (error) {
console.error("Error updating the chart:", error);
}
};
// NEW: Resilient Chart Initialization
const initializeChart = () => {
try {
const ctx = document.getElementById('emi-chart').getContext('2d');
emiChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Principal Amount', 'Total Interest'],
datasets: [{
data: [0, 0],
backgroundColor: ['#2563eb', '#dbeafe'],
borderColor: ['#ffffff'],
borderWidth: 4,
hoverOffset: 4
}]
},
options: {
responsive: true,
cutout: '75%',
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.label || '';
if (label) {
label += ': ';
}
if (context.parsed !== null) {
label += formatIndianCurrency(context.parsed);
}
return label;
}
}
}
}
}
});
} catch (error) {
console.error("Could not initialize Chart.js. Is the library loaded correctly?", error);
// Hide the chart canvas if it fails to load, so it doesn't look broken
const chartCanvas = document.getElementById('emi-chart');
if(chartCanvas) chartCanvas.style.display = 'none';
}
};
// Event Listeners for sliders
[amountSlider, rateSlider, tenureSlider].forEach(el => {
el.addEventListener('input', calculateEMI);
});
// Event Listener for amount buttons
amountBtns.forEach(btn => {
btn.addEventListener('click', () => {
amountSlider.value = btn.dataset.value;
amountSlider.dispatchEvent(new Event('input'));
});
// Style the buttons
btn.classList.add('w-full', 'py-1', 'text-sm', 'font-medium', 'text-blue-600', 'bg-blue-100', 'rounded-md', 'hover:bg-blue-200', 'transition-colors');
});
// Event Listener for Tenure Toggle (Years/Months)
tenureToggle.addEventListener('change', () => {
const currentValue = parseInt(tenureSlider.value);
const isMonths = tenureToggle.checked;
if (isMonths) {
tenureUnit.innerText = 'Months';
tenureSlider.min = 12;
tenureSlider.max = 360; // 30 years * 12 months
tenureSlider.step = 1;
// Convert current years value to months, capped at 360
tenureSlider.value = Math.min(currentValue * 12, 360);
} else {
tenureUnit.innerText = 'Years';
tenureSlider.min = 1;
tenureSlider.max = 30; // 30 years
tenureSlider.step = 1;
// Convert current months value to years, rounding to the nearest year
tenureSlider.value = Math.max(1, Math.round(currentValue / 12));
}
// Trigger calculation after changing tenure type
calculateEMI();
});
// Initial setup on page load
document.addEventListener('DOMContentLoaded', () => {
initializeChart();
calculateEMI(); // Run the first calculation
});
</script>