Simple loan calulator, just run in the browser
Last active
July 11, 2020 18:28
-
-
Save idmontie/b75878a16f09a9ca83cf6ba7aae18174 to your computer and use it in GitHub Desktop.
Simple Loan Calculator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="./main.js"></script> | |
<link type="text/css" rel="stylesheet" href="./main.css" /> | |
</head> | |
<body> | |
<table> | |
<tr> | |
<th>Enter Loan Data:</th> | |
<td></td> | |
<th>Loan Balance, Cumulative Equity, and Interest Payments</th> | |
</tr> | |
<tr> | |
<td>Amount of the Loan ($):</td> | |
<td><input id="amount" onchange="calculate();" /></td> | |
<td rowspan=8> | |
<canvas id="graph" width="400" height="250"></canvas> | |
</td> | |
</tr> | |
<tr> | |
<td>Annual interest (%):</td> | |
<td><input id="apr" onchange="calculate();" /></td> | |
</tr> | |
<tr> | |
<td>Repayment period (years):</td> | |
<td><input id="years" onchange="calculate();" /></td> | |
</tr> | |
<tr> | |
<td>Zipcode (to find lenders):</td> | |
<td><input id="zipcode" onchange="calculate();" /></td> | |
</tr> | |
<tr> | |
<th>Approximate Payments:</th> | |
<td><button onclick="calculate();">Calculate</button></td> | |
</tr> | |
<tr> | |
<td>Monthly Payment:</td> | |
<td>$<span classn="output" id="payment"></span></td> | |
</tr> | |
<tr> | |
<td>Total Payment:</td> | |
<td>$<span classn="output" id="total"></span></td> | |
</tr> | |
<tr> | |
<td>Total Interest:</td> | |
<td>$<span classn="output" id="totalinterest"></span></td> | |
</tr> | |
</table> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.output { | |
font-weight: bold; | |
} | |
#payment { | |
text-decoration: underline; | |
} | |
#graph { | |
border: solid black 1px; | |
} | |
th, td { | |
vertical-align: top; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
function calculate() { | |
var amount = document.getElementById('amount'); | |
var apr = document.getElementById('apr'); | |
var years = document.getElementById('years'); | |
var zipcode = document.getElementById('zipcode'); | |
var payment = document.getElementById('payment'); | |
var total = document.getElementById('total'); | |
var totalInterest = document.getElementById('totalinterest'); | |
var principal = parseFloat(amount.value); | |
var interest = parseFloat(apr.value) / 100 / 12; | |
var payments = parseFloat(years.value) * 12; | |
var x = Math.pow(1 + interest, payments); | |
var monthly = (principal * x * interest) / (x - 1); | |
if (isFinite(monthly)) { | |
payment.innerHTML = monthly.toFixed(2); | |
total.innerHTML = (monthly * payments).toFixed(2); | |
totalInterest.innerHTML = ((monthly * payments) - principal).toFixed(2); | |
save(amount.value, apr.value, years.value, zipcode.value); | |
try { | |
getLenders(amount.value, apr.value, years.value, zipcode.value); | |
} catch (e) {} | |
chart(principal, interest, monthly, payments); | |
} else { | |
payment.innerHTML = ''; | |
total.innerHTML = ''; | |
totalInterest.innerHTML = ''; | |
chart(); | |
} | |
} | |
function save(amount, apr, years, zipcode) { | |
if (window.localStorage) { | |
localStorage.loan_amount = amount; | |
localStorage.loan_apr = apr; | |
localStorage.loan_years = years; | |
localStorage.loan_zipcode = zipcode; | |
} | |
} | |
window.onload = function () { | |
if (window.localStorage && localStorage.loan_amount) { | |
document.getElementById('amount').value = localStorage.loan_amount; | |
document.getElementById('apr').value = localStorage.loan_apr; | |
document.getElementById('years').value = localStorage.loan_years; | |
document.getElementById('zipcode').value = localStorage.loan_zipcode; | |
} | |
} | |
function getLenders(amount, apr, years, zipcode) { | |
if (! window.XMLHttpRequest) return; | |
var ad = document.getElementById('lenders'); | |
if (! ad) return; | |
// ... | |
} | |
function chart(principal, interest, monthly, payments) { | |
var graph = document.getElementById('graph'); | |
graph.width = graph.width; // Magically clear the canvas | |
if (arguments.length === 0 || !graph.getContext) return; | |
var g = graph.getContext('2d'); | |
var width = graph.width, height = graph.height; | |
function paymentToX(n) { return n * width / payments; } | |
function amountToY(a) { return height - ( a * height / (monthly * payments * 1.05 ) ); } | |
g.moveTo(paymentToX(0), amountToY(0)); | |
g.lineTo(paymentToX(payments), amountToY(monthly * payments)); | |
g.lineTo(paymentToX(payments), amountToY(0)); | |
g.closePath(); | |
g.fillStyle = '#f88'; | |
g.fill(); | |
g.font = 'bold 12px sans-serif'; | |
g.fillText('Total Interest Payments', 20, 20); | |
var equity = 0; | |
g.beginPath(); | |
g.moveTo(paymentToX(0), amountToY(0)); | |
for (var p = 1; p <= payments; p++) { | |
var thisMonthsInterest = (principal - equity) * interest; | |
equity += (monthly - thisMonthsInterest); | |
g.lineTo(paymentToX(p), amountToY(equity)); | |
} | |
g.lineTo(paymentToX(payments), amountToY(0)); | |
g.closePath(); | |
g.fillStyle = 'green'; | |
g.fill(); | |
g.fillText('Total Equity', 20, 35); | |
var bal = principal; | |
g.beginPath(); | |
g.moveTo(paymentToX(0), amountToY(0)); | |
for (var p = 1; p <= payments; p++) { | |
var thisMonthsInterest = bal * interest; | |
bal -= (monthly - thisMonthsInterest); | |
g.lineTo(paymentToX(p), amountToY(bal)); | |
} | |
g.lineWidth = 3; | |
g.stroke(); | |
g.fillStyle = 'black'; | |
g.fillText('Loan Balance', 20, 50); | |
g.textAlign = 'center'; | |
var y = amountToY(0); | |
for (var year = 1; year * 12 <= payments; year ++) { | |
var x = paymentToX(year * 12); | |
g.fillRect(x - 0.5, y - 3, 1, 3); | |
if ( year === 1 ) g.fillText("Year", x, y - 5); | |
if ( year % 5 === 0 && year * 12 !== payments) { | |
g.fillText(String(year), x, y - 5); | |
} | |
} | |
g.textAlign = 'right'; | |
g.textBaseline = 'middle'; | |
var ticks = [monthly * payments, principal]; | |
var rightEdge = paymentToX(payments); | |
for ( var i = 0; i < ticks.length; i++) { | |
var y = amountToY(ticks[i]); | |
g.fillRect(rightEdge - 2, y - 0.5, 3, 1); | |
g.fillText(String(ticks[i].toFixed(0)), rightEdge - 5, y); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment