JavaScript newbie here.
I am tasked with calculating a user's monthly payment by using a given equation. I am having trouble with getting the values from the user.
const loanAmount = document.getElementById('loan-amount');
const loanYears = document.getElementById('loan-years');
const loanRate = document.getElementById('loan-Rate');
const span = document.querySelector('span');
const form = document.getElementById("calc-form");
form.addEventListener("submit", function (e) {
e.preventDefault();
console.log('hello')
makeLogo();
});
function makeLogo(loanAmount, loanYears, loanRate) {
const principle = loanAmount.value
const n = loanYears.value * 12;
const i = loanRate.value / 12;
const monthylPayment = (principle* i)/1-(1+ i)** -(n);
span.innerText = monthylPayment;
}
This is what I have so far and am getting an error for the variables in the makeLogo function.
It's a good idea to separate your inputs, calculations and rendering into separate functions. try to keep functions as simple as possible.
You will need to re-evaluate your monthly cost calculator, but here is a working example which takes input, calculates and then renders into form fields.
document.getElementById("calc-form").addEventListener('submit', (e) => {
e.preventDefault();
var loanAmount = document.getElementById('loan-amount').value;
console.log(loanAmount);
var loanYears = document.getElementById('loan-years').value;
var loanRate = document.getElementById('loan-rate').value;
var monthlyPayment = makeLogo( loanAmount, loanYears, loanRate );
console.log(monthlyPayment);
// the monthly has now been calculated, simply put it where you'd like
var calculated = document.getElementById('calculated');
calculated.value = monthlyPayment;
var totalRepayment = document.getElementById('totalRepayment');
totalRepayment.value = monthlyPayment * ( loanYears * 12 );
} );
function makeLogo( principle, loanYears, loanRate) {
var n = loanYears * 12;
var i = loanRate / 12;
var result = ( principle * i) / 1 - ( 1 + i )**-( n );
return result;
}
<html>
<form action='submit' id ='calc-form'>
Loan Amount:<input id ='loan-amount'></input><BR/>
Loan Years:<input id='loan-years'></input><BR/>
Loan Rate:<input id='loan-rate'></input><BR/>
<input type='submit'>
</form>
<span id='span-output'>
Monthly Payment :<input id='calculated' readonly><BR/>
Total Re-Payment :<input id='totalRepayment' readonly>
</span>
</html>
The error you are seeing is likely because the makeLogo function is trying to access the value property of the loanAmount, loanYears, and loanRate variables. Still, they are DOM elements and not their values.
You can fix this by accessing the value property of the DOM elements before passing them to the function like so:
form.addEventListener("submit", function (e) {
e.preventDefault();
console.log('hello')
const principle = loanAmount.value;
const n = loanYears.value * 12;
const i = loanRate.value / 12;
makeLogo(principle, n, i);
});
function makeLogo(principle, n, i) {
const monthylPayment = (principle* i)/1-(1+ i)** -(n);
span.innerText = monthylPayment;
}
This way, the makeLogo function receives the values of the input fields as arguments and can perform the calculation correctly.
Also, make sure that you are getting the right input from the user by checking the value of each element by doing the following:
console.log(loanAmount.value,loanYears.value,loanRate.value)
and check if they are the values that you are expecting.
Related
I would like to access variable from inside a function. The variable tip is innerText of different buttons (5, 6, 7...), but they are in %, so I converted them into numbers. However, the numbers are accessible only from inside the percentage function. When I try to call the function and log the variable, it shows NaN. I would like to use the tip for calculation in calc function always after clicking a respective button. How can I do that?
let tip = 0;
const billInput = document.querySelector(".bill__input");
const peopleInput = document.querySelector(".people__input");
const individualTip = document.querySelector(".conclusion__tip-person");
const individualTotal = document.querySelector(".conclusion__total-person");
const reset = document.querySelector(".conclusion__reset");
const buttons = document.querySelectorAll(".select-tip__button");
function percentage() {
tip = parseInt(this.innerText);
}
buttons.forEach((button) => {
button.addEventListener("click", percentage);
});
function calc() {
if (billInput !== "" && peopleInput === "") {
}
individualTip.textContent = (billInput.value / 100) * tip;
individualTotal.textContent =
"$" + (billInput.value / peopleInput.value).toFixed(2);
}
document.addEventListener("input", calc);
To make it little bit smaller:
I cant access numbers from variable tip, which innerText of buttons with different values (5%, 10%...). These numbers are converted from strings to numbers in the percentage function. I can access the correct tip values after clicking on buttons only if I log it directly inside the percentage function. I would like to use it outside the function, however.
let tip = 0;
function percentage() {
tip = parseInt(this.innerText);
}
buttons.forEach((button) => {
button.addEventListener("click", percentage);
});
you need change string to integer before you calculation
parseInt(peopleInput.value)
In the if (billInput !== "" && peopleInput === ""), you should return to not execute the reset of the function, Also the inputs values be as string format, you need to convert to number, you can use + operator.
let tip = 0;
const billInput = document.querySelector(".bill__input");
const peopleInput = document.querySelector(".people__input");
const individualTip = document.querySelector(".conclusion__tip-person");
const individualTotal = document.querySelector(".conclusion__total-person");
const reset = document.querySelector(".conclusion__reset");
const buttons = document.querySelectorAll(".select-tip__button");
function percentage() {
tip = parseInt(this.innerText);
}
buttons.forEach((button) => {
button.addEventListener("click", percentage);
});
function calc() {
if (billInput !== "" && peopleInput === "") {
// if there no value doesn't execute the rest of the function.
return
}
individualTip.textContent = (+billInput.value / 100) * tip;
individualTotal.textContent =
"$" + (+billInput.value / +peopleInput.value).toFixed(2);
}
document.addEventListener("input", calc);
So for anyone who would encounter similar problem, I solved this one. My variables and fucntions works properly. All I had to do was to put function calc() as the last line inside percentage() function. That did the trick. That's it.
So I made a button that creates an input placeholder every time it is clicked (limited to 4). The problem is, I am using post method, and doing .value in my code returns a TypeError, but not the default placeholders (eg: m1k1). The IDs are created, and they're similar to the default with the exception of a number that is generated in a for loop.
When I type in values in just the default placeholders, everything is fine.
Two elements
let m1k1 = document.querySelector('#mon1wk1')
let m1k2 = document.querySelector('#mon1wk2')
eventListener
let num = 1
function addWeek(e) {
e.preventDefault()
num++
let mkInput = document.createElement('input')
let forma = document.querySelector('#forma')
mkInput.placeholder = " "
mkInput.id = 'mon1wk' + num
mkInput.type = 'text'
forma.append(mkInput)
if (num === 4) {
addwk1.disabled = true;
Where values get stored into an object
pushMonths.firstMonth.Week1 = m1k1.value,
pushMonths.firstMonth.Week2 = m1k2.value,
Any help is appreciated
In the OP code the num equals 1, so when the id is assigned to a new <input> when the user clicks the <button>, the first <input> is assigned id="mon1wk1" and the second <input> is assigned id="mon1wk2". So now there's 2 pairs of <input> sharing the same id which is invalid plus the duplicates cannot be found by id since the browser quits searching as soon as it finds the first id, which explains why the static <input>s always worked.
In the example below, the object follows the following pattern:
Figure I
const obj = {
mw: [2, 1], // [2nd month, 1st week]
mon1: { // Each mon* object can have up to 4 wk* properties
wk1: mon1wk1.value,
⇓⇓⇓
wk4: mon1wk4.value
},
mon2: {
wk1: mon2wk1.value
}
};
Details are commented in example
// Reference <form>
const frm = document.forms.forma;
/**
* #param {object} obj - Used to keep data
* #param {array} obj.mw - Keeps count of current
* month at mw[0] and week at mw[1]
* #param {object} obj.mon* - Month holds 4 weeks
* #param {any} obj.wk* - Week holds associated
* <input> value
*/
const obj = {
mw: [1, 2],
mon1: {
wk1: 5,
wk2: 4
}
};
let m = obj.mw[0];
let w = obj.mw[1];
// Bind submit event to <form>
frm.onsubmit = addWeek;
function addWeek(e) {
// Stop <form> from killing page
e.preventDefault();
// Build new <input>
let mk = document.createElement('input');
mk.type = 'text';
frm.append(mk);
/*
Incerment 'w'
If 'w' is greater than 4...
...add a new 'mon*' object and assign it a new
'w'
*//*
Otherwise assign a new property to current 'mon*'
Assign id to new <input> with this pattern:
`mon${m}wk${w}`
*/
++w;
if (w > 4) {
++m;
w = 1;
obj['mon' + m] = {
['wk' + w]: 0
};
obj.mw[0] = m;
obj.mw[1] = 1;
} else {
obj['mon' + m]['wk' + w] = 0;
obj.mw[1] += 1;
}
mk.id = 'mon' + m + 'wk' + w;
console.log(obj);
}
// Bind input event to <form>
frm.oninput = saveData;
/*
When a user inputs a value into an <input>, assign
the value to the associated property of obj.
The value is coerced into a number: +mk.value
Remove the '+' if you want string instead.
*/
function saveData(e) {
const mk = e.target;
let id = mk.id;
obj[id.slice(0, 4)][id.slice(4)] = +mk.value;
console.log(obj);
}
form {
display: flex;
}
button,
input {
display: inline-block;
}
<form id='forma'>
<button id='addWk'>Add Week</button><br><hr>
<input id='mon1wk1' value='5'>
<input id='mon1wk2' value='4'>
</form>
I've created a calculator that requires a value in either months or years in order to perform a calculation. The calculator works with one exception: It is required that the two input fields update based on the value of each other. here's an example of the behavior I am attempting to recreate:
https://www.bankrate.com/calculators/mortgages/loan-calculator.aspx
I apologize in advance if the following example reads poorly, but here it goes:
If a user enters 72 'months', the 'years' input will divide months by 12 and display the result. After doing a little tooling around, I found that using [a, b] = [b*12, a/12] gets me halfway there. The problem I'm running into is that once values have been entered, the value of the most recently updated input is updated with the previous value (including the calculation). For example, User enters 60 months > years is populated with the value of 5 > user changes months to a value of 72 > years is populated with a value of 6 > months is automatically populated with a value of 60 (years remains at a value of 6)
Here's the JS:
const loan = () => {
let principal = document.getElementById('principal')
let interestRate = document.getElementById('interestRate')
let terms = document.getElementById('terms')
let termsInYears = document.getElementById('termsInYears')
let payment = document.getElementById('payment')
let total = document.getElementById('total')
let totalInterest = document.getElementById('totalInterest')
let closingCosts = document.getElementById('closingCosts')
let netAfterFees = document.getElementById('netAfterFees')
let totalFeesAndInterest = document.getElementById('totalFeesAndInterest')
let trueCost = document.getElementById('trueCost')
let amount = parseFloat(principal.value)
let interest = parseFloat(interestRate.value) / 100 / 12
let payments = parseFloat(terms.value)
let fees = parseFloat(closingCosts.value)
if(!fees) {
closingCosts.value = 0
}
[terms.value, termsInYears.value] = [termsInYears.value*12, terms.value/12]
let x = Math.pow(1 + interest, payments)
let monthly = (amount * x * interest) / (x-1)
let totalPay = (monthly * payments)
if (isFinite(monthly) && payment) {
payment.innerHTML = monthly.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
netAfterFees.innerHTML = (amount - fees).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
total.innerHTML = (totalPay).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
totalInterest.innerHTML = ((monthly * payments) - amount).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
totalFeesAndInterest.innerHTML = (totalPay - amount + fees).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
trueCost.innerHTML = (((totalPay - amount + fees) / amount)*100).toFixed(2)
} else {
payment.innerHTML = '0'
netAfterFees.innerHTML = '0'
total.innerHTML = '0'
totalInterest.innerHTML = '0'
totalFeesAndInterest.innerHTML = '0'
trueCost.innerHTML = '0'
}
}
I can't speak on the quality of the working calculator given my experience level. However, it does work. I'm just having one heck of a time getting past this [likely silly] input exchange.
Any help would be greatly appreciated!
I ended up solving this issue using querySelector and then adding an event listener for each input:
document.querySelector('#terms').addEventListener('input', (e) => {
termsInYears.value = e.target.value / 12
})
document.querySelector('#termsInYears').addEventListener('input', (e) => {
terms.value = e.target.value * 12
})
This question already has answers here:
How do I get the value of text input field using JavaScript?
(16 answers)
Closed 6 years ago.
I am trying to make a calculator that calculates the amount of calories that have been burned in a certain amount of time, but whenever I run it, I get 0 as the output. I have tried setting the calorieCountOut variable to an arbitrary number, and then it works fine, but every time I run it with this code here, I get 0. Here is my code:
const AGECONST = 0.2017;
const WEIGHTCONST = 0.09036;
const HRCONST = 0.6309;
const SUBTRACTCONST = 55.0969;
const TIMECONST = 4.184;
//var gender = document.getElementById("gender").innerHTML;
var gender = "male";
var weight = document.getElementById("weight");
var age = document.getElementById("age");
var time = document.getElementById("time");
var hr = 140;//dummy number
function calculate(){
if (gender = "male"){
var calorieCount = ((age * AGECONST) - (weight * WEIGHTCONST) + (hr * HRCONST) - SUBTRACTCONST) * time / TIMECONST;
}
//else if (gender = "female"){
//}
var calorieCountOut = calorieCount.toString();
document.getElementById("output").innerHTML = calorieCountOut;
}
Try getElementById('myId').value for the value inside the control instead of the control itself as an object.
Right now you assign a html object to a variable, but what you want (i assume) is the number stored in that html object.
I'm trying to create a paycheck calculator, but when I enter the hourly rate and number of hours and hit calculate, all I'm getting is undefined in my totals table. Here is my javascript:
var $ = function (id) {
return document.getElementById(id);
}
function updateTotal () {
var rate;
var hours = parseFloat( $("numHours").value);
var regularHours;
var overtime;
var doubletime;
//begin determine hourly rate
function checkJob () {
if ($('job').value == 'job0') {
rate = 0;
}
if ($('job').value == 'job1') {
rate = 12;
}
if ($('job').value == 'job2') {
rate = 10;
}
if ($('job').value == 'job3') {
rate = 11;
}
}
//calculate hours breakdown
function checkHours () {
if (hours.value <= 40) {
regularHours = hours.value;
overtime = 0;
doubletime = 0;
}
if (hours.value < 60) {
regularHours = 40;
overtime = hours.value-40;
doubletime=0;
}
if (hours.value >=60) {
regularHours = 40;
overtime = 20;
doubletime = hours.value-60;
}
}
checkJob();
checkHours();
var salary = (regularHours * rate) + (overtime * (rate * 1.5)) + (doubletime * (rate * 2))
//display amounts
$('regularHours').innerHTML = regularHours;
$('overtime').innerHTML = overtime;
$('doubletime').innerHTML = doubletime;
$('salary').innerHTML = "$ " + salary;
}
I'm sure I'm missing something silly, but I've been staring at this code for days and can't figure out what I'm doing wrong. Thanks for looking!
EDIT
The offending code is this:
hours.value
The problem with it is that hours is already a number, and number does not have the method value available to it. Changing all instances of hours.value to hours will solve the problem and properly output a calculated result.
See this demo: http://jsfiddle.net/gLthv/
The problem is the way you are implementing your jquery selectors. You should either use document.getElementById() instead, or remember that to select an id, you need to prefix the id name with a #
$("#id")
That is only the first part of the problem though. The next part is that you are using jquery, but expecting dom elements. To unwrap the jquery object, you need to use [0] with it to be able to access the contained dom element.
$("#id")[0]
Once you make these changes, you should be able to see the reflected calculations. For example, $('job').value should really be $('#job')[0].value or if you prefer to stick with jquery's implementation then you can use $('#job').val() to get the value.
Similar to this you may also access jquery's implementation of innerHTML. That would change this: $('overtime').innerHTML = overtime to $('#overtime').html(overtime)