I have a mortgage calculator that I've built out. Everything seems to be working great except for one small bug. There are two input fields with a button that takes both integers and runs them through a bunch of calculations to find many properties of the mortgage (ie. monthly payments, remaining loan balances etc...).
Now the issue that I've come across is only in the downpayment field. If I consecutively put in two integers than It will not process the new monthly payment. If I do either two percentages or integer - {calculate} - percentage - {calculate} - integer - {calculate} it will calculate correctly.
Here is the code I feel is in question:
// User Data Object
var userData = {};
// Gather User Data from form than display results above form
function calculateUserMontlyPayments() {
userData.salePrice = 0;
userData.downPayment = 0;
userData.salePrice = document.getElementById("userHomePrice").value;
userData.downPayment = document.getElementById("userDownPayment").value;
//MortgageCalculator.calculateMortgage().calculateLoanAmount(userData.downPayment);
var results = MortgageCalculator.calculateMortgage(userData);
document.getElementById("userPayments").innerHTML = '$' + results.fullMonthlyPayment;
document.getElementById("allInfo").innerHTML = results.downPayment;
};
var MortgageCalculator = {
calculateMortgage: function(options) {
Date.isLeapYear = function(year) {
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
console.log('Leap Year');
};
Date.getDaysInMonth = function(year, month) {
return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};
Date.prototype.isLeapYear = function() {
var y = this.getFullYear();
return (((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0));
};
Date.prototype.getDaysInMonth = function() {
return Date.getDaysInMonth(this.getFullYear(), this.getMonth());
};
Date.prototype.addMonths = function(value) {
var n = this.getDate();
this.setDate(1);
this.setMonth(this.getMonth() + value);
this.setDate(Math.min(n, this.getDaysInMonth()));
return this;
};
function initOptions(options) {
var mortgage = {};
mortgage.loanTermMonths = options.loanTermMonths || 12 * 30;
mortgage.salePrice = options.salePrice || 500000;
mortgage.interestRate = options.interestRate || 5.00;
mortgage.downPayment = options.downPayment || '20%';
mortgage.salePrice = options.salePrice || 500000;
mortgage.extras = options.extras || [];
mortgage.propertyTaxRate = options.propertyTaxRate || .78;
mortgage.homeInsurance = options.homeInsurance || 0.22;
mortgage.adjustFixedRateMonths = options.adjustFixedRateMonths || 0;
mortgage.adjustInitialCap = options.adjustInitialCap || 0;
mortgage.adjustPeriodicCap = options.adjustPeriodicCap || 0;
mortgage.adjustLifetimeCap = options.adjustLifetimeCap || 0;
mortgage.adjustIntervalMonths = options.adjustIntervalMonths || 12;
mortgage.startDate = options.startDate || new Date();
return mortgage;
}
function calculateLoanAmount(mortgage) {
var loanAmount;
if (typeof mortgage.downPayment == 'string') {
var downPercent = mortgage.downPayment.substr(0, mortgage.downPayment.indexOf('%'));
loanAmount = mortgage.salePrice - (mortgage.salePrice * (downPercent / 100));
} else {
loanAmount = mortgage.salePrice - mortgage.downPayment;
}
return loanAmount;
}
function roundDecimals(num) {
var decimals = 2;
return Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals);
}
function roundAmortizationValues(amortization) {
amortization.monthlyPayment = roundDecimals(amortization.monthlyPayment);
amortization.interest = roundDecimals(amortization.interest);
amortization.interestToDate = roundDecimals(amortization.interestToDate);
amortization.interestLoanYearToDate = roundDecimals(amortization.interestLoanYearToDate);
amortization.principal = roundDecimals(amortization.principal);
amortization.principalLoanYearToDate = roundDecimals(amortization.principalLoanYearToDate);
amortization.principalToDate = roundDecimals(amortization.principalToDate);
amortization.extra = roundDecimals(amortization.extra);
amortization.principalTotal = roundDecimals(amortization.principalTotal);
amortization.paymentTotal = roundDecimals(amortization.paymentTotal);
return amortization;
}
function calculateExtraPayment(mortgage, loanMonth) {
var totalExtra = 0;
if (mortgage.extras) {
for (var i in mortgage.extras) {
var extra = mortgage.extras[i];
if (loanMonth >= extra.startMonth && loanMonth <= extra.endMonth) {
if ((loanMonth - extra.startMonth) % extra.extraIntervalMonths == 0) {
totalExtra += extra.extraAmount * 100;
}
}
}
}
return totalExtra;
}
function aprToMonthlyInterest(apr) {
return apr / (12 * 100);
}
function calculatePropertyTax(mortgage) {
var monthlyPropertyTax;
if (mortgage.propertyTaxRate && mortgage.propertyTaxRate > 0) {
monthlyPropertyTax = (mortgage.salePrice * 100 * (mortgage.propertyTaxRate / 100)) / 12;
} else {
monthlyPropertyTax = 0;
}
return monthlyPropertyTax;
}
function calculateHomeInsurance(mortgage) {
var monthlyHomeInsurance;
if (mortgage.homeInsurance && mortgage.homeInsurance > 0) {
monthlyHomeInsurance = (mortgage.salePrice * 100 * (mortgage.homeInsurance / 100)) / 12;
} else {
monthlyHomeInsurance = 0;
}
return monthlyHomeInsurance;
}
/**
* Mortgage needs reset if this mortgage is ARM and current loam month falls into
* new interest period.
*
* @param mortgage
* @param loanMonth
*/
function needsInterestReset(mortgage, loanMonth) {
if (mortgage.adjustFixedRateMonths <= 0 || loanMonth <= mortgage.adjustFixedRateMonths) {
return false;
}
return (loanMonth - mortgage.adjustFixedRateMonths - 1) % mortgage.adjustIntervalMonths == 0;
}
function calculateInterestRate(mortgage, loanMonth) {
if (mortgage.adjustFixedRateMonths <= 0 || loanMonth <= mortgage.adjustFixedRateMonths) {
return mortgage.interestRate;
}
var armInterestRate = mortgage.interestRate + mortgage.adjustInitialCap;
if (loanMonth > mortgage.adjustFixedRateMonths + 1) {
for (var i = mortgage.adjustFixedRateMonths + mortgage.adjustIntervalMonths; i <= loanMonth; i += mortgage.adjustIntervalMonths) {
armInterestRate += mortgage.adjustPeriodicCap;
}
}
armInterestRate = Math.min(armInterestRate, mortgage.adjustLifetimeCap + mortgage.interestRate)
return armInterestRate;
}
function calculateMonthlyPayment(loanAmount, loanTermMonths, interestRate) {
var monthlyInterestRate = aprToMonthlyInterest(interestRate);
var monthlyPayment = loanAmount * (monthlyInterestRate * Math.pow(1 + monthlyInterestRate, loanTermMonths)) /
(Math.pow(1 + monthlyInterestRate, loanTermMonths) - 1);
return monthlyPayment;
}
function calculateAmortizations(mortgage) {
//To avoid rounding errors, all dollars will be converted to cents and converted back to dollars
//to response objects.
var remainingLoanAmountInCents = mortgage.loanAmount * 100;
var loanAmountInCents = mortgage.loanAmount * 100;
var monthlyPropertyTaxInCents = calculatePropertyTax(mortgage);
var monthlyHomeInsuranceInCents = calculateHomeInsurance(mortgage);
var amortizations = [];
var previousAmortization;
var loanMonth = 0;
var loanYear = 1;
var loanYearRollUpSummary = {};
var currentInterestRate = calculateInterestRate(mortgage, 1);
var currentMonthlyPaymentInCents = calculateMonthlyPayment(remainingLoanAmountInCents, mortgage.loanTermMonths, currentInterestRate);
var rollupSummaryFields = ['interest', 'principal', 'extra', 'principalTotal', 'propertyTax', 'paymentTotal'];
while (remainingLoanAmountInCents >= 1) {
loanMonth++
var amortization = {};
if (needsInterestReset(mortgage, loanMonth)) {
currentInterestRate = calculateInterestRate(mortgage, loanMonth);
currentMonthlyPaymentInCents = calculateMonthlyPayment(remainingLoanAmountInCents, mortgage.loanTermMonths + 1 - loanMonth, currentInterestRate);
}
amortization.interestRate = currentInterestRate;
amortization.scheduledMonthlyPayment = currentMonthlyPaymentInCents;
amortization.interest = remainingLoanAmountInCents * aprToMonthlyInterest(amortization.interestRate);
amortization.principal = currentMonthlyPaymentInCents - amortization.interest;
if (remainingLoanAmountInCents < amortization.principal) {
amortization.principal = remainingLoanAmountInCents;
amortization.extra = 0;
} else {
amortization.extra = calculateExtraPayment(mortgage, loanMonth);
}
amortization.principalTotal = amortization.principal + amortization.extra;
amortization.propertyTax = monthlyPropertyTaxInCents;
amortization.homeInsurance = monthlyHomeInsuranceInCents;
amortization.paymentTotal = amortization.interest + amortization.principalTotal + monthlyPropertyTaxInCents + monthlyHomeInsuranceInCents;
//amortization.paymentDate = new Date(mortgage.startDate.getTime()).addMonths(loanMonth);
remainingLoanAmountInCents -= amortization.principalTotal;
//If remaining loan amount is less than zero, then set it to zero.
if (remainingLoanAmountInCents < 0) {
remainingLoanAmountInCents = 0;
}
amortization.remainingLoanBalnce = remainingLoanAmountInCents;
amortization.loanMonth = loanMonth;
amortization.loanYear = loanYear;
rollupSummaryFields.map(function(field) {
if (loanYearRollUpSummary[field]) {
loanYearRollUpSummary[field] += amortization[field];
} else {
loanYearRollUpSummary[field] = amortization[field];
}
amortization[field + 'LoanYearToDate'] = loanYearRollUpSummary[field];
});
if (loanMonth % 12 === 0) {
loanYearRollUpSummary = {};
loanYear++;
}
rollupSummaryFields.map(function(field) {
if (previousAmortization) {
amortization[field + 'ToDate'] = previousAmortization[field + 'ToDate'] + amortization[field];
} else {
amortization[field + 'ToDate'] = amortization[field];
}
});
previousAmortization = amortization;
amortizations.push(amortization);
}
//Round all amortization values to dollars.
mortgage.totalLoanCost = 0;
var additionalFieldsToProcess = ['scheduledMonthlyPayment', 'remainingLoanBalnce'];
for (var i = 0; i < amortizations.length; i++) {
var amortization = amortizations[i];
rollupSummaryFields.map(function(field) {
amortization[field] = roundDecimals(amortization[field] / 100);
amortization[field + 'ToDate'] = roundDecimals(amortization[field + 'ToDate'] / 100);
amortization[field + 'LoanYearToDate'] = roundDecimals(amortization[field + 'LoanYearToDate'] / 100);
});
additionalFieldsToProcess.map(function(field) {
amortization[field] = roundDecimals(amortization[field] / 100);
});
mortgage.totalLoanCost += amortization.interest;
}
mortgage.totalLoanCost = roundDecimals(mortgage.totalLoanCost);
mortgage.paymentSchedule = amortizations;
mortgage.numberOfPayments = mortgage.paymentSchedule.length;
mortgage.monthlyPayment = mortgage.paymentSchedule[0].scheduledMonthlyPayment;
mortgage.fullMonthlyPayment = amortization.paymentTotal;
}
var mortgage = initOptions(options);
mortgage.loanAmount = calculateLoanAmount(mortgage);
calculateAmortizations(mortgage);
return mortgage;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mortgage Calculator</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style media="screen">
input:focus {
outline: none;
}
</style>
</head>
<body>
<div class="row">
<div class="col-sm-12 push-20 text-center">
<h5 class="push-10">Monthly Payments</h5>
<h2 id="userPayments">$0</h2>
</div>
<div class="col-sm-offset-2 col-sm-4 text-center">
<input id="userHomePrice" type="text" name="Home Price" value="538000" placeholder="Home Price">
</div>
<div class="col-sm-4 text-center">
<input id="userDownPayment" type="text" name="Interest Price" value="20%" placeholder="Down Payment">
</div>
<div class="col-sm-12 push-20 text-center">
<button onclick="calculateUserMontlyPayments()">Submit</button>
</div>
<div class="col-sm-12 text-center">
<h5>results.downPayment</h5>
</div>
<div class="col-sm-12 text-center">
<p id="allInfo"></p>
</div>
</div>
<script type="text/javascript" src="mortgage-calculator.js"></script>
</body>
</html>
I am still very green when it comes to javascript and I am only now finally to the point where I can implement raw source code and plug it into the project so if I am wording something incorrectly or if this is a common mistake made I apologize. I couldn't seem to word a question well enough to find an answer already written online.