no matter what i try i cant get the function to run properly
ive tried checked that the inputs are numbers, and only the output is giving me NaN. ive tried putting parseInt around the inputs, but the inputs eem to be working correctly. its probably a small newb mistake, thanks for your time anyway!
const principle=parseInt(document.getElementsByClassName('principle').value);
const rate = parseInt(document.getElementsByClassName('.rate').value);
const payments = parseInt(document.getElementsByClassName('payments').value);
let interest;
function calculate() {
console.log(typeof(principle));
console.log(typeof(rate));
console.log(typeof(payments));
interest = (rate / payments) * principle;
console.log(interest);
};
<body>
<h1>interest calculator</h1>
<div class="container">
<div class="row">
<div class="col-4-md">
initial amount <input type="number" name="" value="" class="principle px-3">
</div>
<div class="col-4-md">
interest rate <input type="number" name="" value="" class="rate px-3">
</div>
<div class="col-4-md">
Number of payments <input type="number" name="" value="" class="payments px-3">
</div>
<button type="submit" name="button" onclick="calculate()">Submit</button>
</div>
</div>
i just want the output to be a number
Here is a working code after modifications/fixes:
<html>
<head>
<script>
let interest;
function calculate() {
const principle=parseInt((document.getElementsByClassName('principle')[0]).value);
const rate = parseInt((document.getElementsByClassName('rate')[0]).value);
const payments = parseInt((document.getElementsByClassName('payments')[0]).value);
console.log(typeof(principle));
console.log(principle);
console.log(typeof(rate));
console.log(rate);
console.log(typeof(payments));
console.log(payments);
interest = (rate / payments) * principle;
console.log(interest);
};
</script>
</head>
<body>
<h1>interest calculator</h1>
<div class="container">
<div class="row">
<div class="col-4-md">
initial amount <input type="number" name="" value="" class="principle px-3">
</div>
<div class="col-4-md">
interest rate <input type="number" name="" value="" class="rate px-3">
</div>
<div class="col-4-md">
Number of payments <input type="number" name="" value="" class="payments px-3">
</div>
<button type="submit" name="button" onclick="calculate()">Submit</button>
</div>
</div>
</body>
</html>
You have 2 mistakes in your JS.
1) getByClassName return an array of element, so you must select which element you want in your case, since you have only one element of each, you can easily do document.getElementsByClassName('rate')[0]
2) at the moment you load the page, you assign your values. but when you fill the document, and calculate, you don't check the value again. so they are still undefined.
if you fix everything you will get this JS
const principle$ = document.getElementsByClassName('principle')[0];
const rate$ = document.getElementsByClassName('rate')[0];
const payments$ = document.getElementsByClassName('payments')[0];
let interest;
function calculate() {
console.log(principle$, principle$.value)
const principle = parseInt(principle$.value);
const rate = parseInt(rate$.value);
const payments = parseInt(payments$.value);
interest = (rate / payments) * principle;
console.log(interest);
};
https://codepen.io/crocsx-the-styleful/pen/MWgOLgm
Becuase typeof NaN is also a number
console.log(typeof NaN)
When you JS code execute the variable are outside the function so the are calculated with as soon as your script load, during that time your inputs hold empty string
console.log(parseInt(''), typeof parseInt(''))
You need to move your variables inside the function so they will be evaluated when the submit button is pressed
function calculate() {
const principle = parseInt(document.getElementsByClassName('principle')[0].value);
const rate = parseInt(document.getElementsByClassName('rate')[0].value);
const payments = parseInt(document.getElementsByClassName('payments')[0].value);
let interest;
console.log(typeof(principle));
console.log(typeof(rate));
console.log(typeof(payments));
interest = (rate / payments) * principle;
console.log(interest);
};
<body>
<h1>interest calculator</h1>
<div class="container">
<div class="row">
<div class="col-4-md">
initial amount <input type="number" name="" value="" class="principle px-3">
</div>
<div class="col-4-md">
interest rate <input type="number" name="" value="" class="rate px-3">
</div>
<div class="col-4-md">
Number of payments <input type="number" name="" value="" class="payments px-3">
</div>
<button type="submit" name="button" onclick="calculate()">Submit</button>
</div>
</div>
Also you're using getElementsByClassName which returns a node list, you need to access particular node using index
Related
I am making a mortgage calculator and am trying to clear all the inputs when the clear button is presses. I can't seem to get it to work. Below is my html and JavaScript code, I have also tried setting the inputs = null and that didn't work.
HTML:
<div class="calculator">
<h1>Mortgage Calculator</h1>
<div class="input-container">
<label for="Loan-amount">Total Loan Amount</label>
<input type="number" name="Loan-amount" id="total" min="0">
</div>
<div class="input-container">
<label for="down-payment">Down payment</label>
<input type="number" name="Loan-amount" id="down" min="0">
</div>
<div class="input-container">
<label for="interest-rate">Interest rate %</label>
<input type="number" name="interest-rate" id="interest" min="0">
</div>
<div class="input-container">
<label for="loan-term">Loan Term (in years)</label>
<input type="number" name="loan-term" id="duration" min="0">
</div>
<div class="answer">
<h2>Estimated payment:</h2>
<p id="paragraph-value"></p>
</div>
<div class="button-container">
<button id="submitBtn">Calculate</button>
<button id="clearBtn">Clear</button>
</div>
<p id="alert"></p>
</div>
JavaScript:
const clearBtn = document.querySelector("#clearBtn");
clearBtn.addEventListener("click", function (e) {
let total = document.getElementById("total").value;
let interest = document.querySelector("#interest").value;
let duration = document.querySelector("#duration").value;
let downPayment = document.querySelector("#down").value;
total = "";
interest = "";
duration = "";
downPayment = "";
});
You're not setting a value to the inputs, you're just over-writing the value of a varable:
total = "";
To set the value of the input, you'd set the .value property on the input:
document.getElementById("total").value = "";
For example:
const clearBtn = document.querySelector("#clearBtn");
clearBtn.addEventListener("click", function (e) {
document.getElementById("total").value = "";
});
<input type="number" id="total" />
<button id="clearBtn">Reset</button>
At a more generic level, you seem to be confused about the difference between these two things:
var total = document.getElementById("total").value;
total = "";
and:
var total = document.getElementById("total");
total.value = "";
In the first case the variable holds a copy of the value itself, and you're re-assigning the variable to a new value. This does nothing to the element.
But in the second case the variable holds a reference to the element, and you're updating a property on that element.
I am currently trying to create a tip calculator app using JS, HTML, and CSS. My issue is that the input value is submitted when the button is clicked, but once submitted, the value just flashes for less than a second, then it vanishes. I would like for the value to stay on the screen once submitted.
let dinTotal = document.querySelector('#cost');
let dinService = document.querySelector('#service');
let dinSize = document.querySelector('#size');
let calcBtn = document.querySelector('button');
let total = 0;
let amount = document.querySelector('#amount')
calcBtn.addEventListener('click', function() {
if(dinTotal.value >= 50 && dinService.value < 5 && dinSize.value < 5) {
total = (dinTotal.value * 0.10) + dinTotal.value ;
amount.textContent = total;
}
})
<form>
<h1>Tip & Dip✌️</h1>
<hr>
<!-- Bill Section -->
<div>
<label for='cost'>Dinning amount</label>
</div>
<input name='cost' id='cost' type='number' placeholder='$' required>
<!-- Service Section-->
<div class='top-space'>
<label for='service'>How was the service</label>
</div>
<input name='service' id='service' type='number' placeholder='rate 1-10' required>
<!-- Party Size-->
<div class='top-space'>
<label for='size'>Party Size</label>
</div>
<div>
<input name='size' id='size' type='number' required>
</div>
<div class='top-space'>
<button>LET'S CALCULATE...</button>
</div>
<hr>
<h2>Total: $<span id='amount'>0</span></h2>
</form>
The default behavior of a button is to submit the form. When a form submits, if you don't stop it, it will unload the current page and submit the data to its action URL. With no action attribute, a form submits to the current page, causing your reload.
Set the type attribute on your button to button to prevent it from being a submit button.
<button type="button">LET'S CALCULATE...</button>
use the preventDefualt() method of the event callback
calcBtn.addEventListener('click', function(event) {
event.preventDefault()
}
Full working snippet (though it only updates for size and value of less than 5 and checks greater than 50 I hope you know)
let dinTotal = document.querySelector('#cost');
let dinService = document.querySelector('#service');
let dinSize = document.querySelector('#size');
let calcBtn = document.querySelector('button');
let total = 0;
let amount = document.querySelector('#amount')
calcBtn.addEventListener('click', function(event) {
event.preventDefault()
if(dinTotal.value >= 50 && dinService.value < 5 && dinSize.value < 5)
{
total = (dinTotal.value * 0.10) + dinTotal.value ;
console.log(total)
amount.textContent = total;
}
})
<form>
<h1>Tip & Dip✌️</h1>
<hr>
<div>
<label for='cost'>Dinning amount</label>
</div>
<input name='cost' id='cost' type='number' placeholder='$' required>
<div class='top-space'>
<label for='service'>How was the service</label>
</div>
<input name='service' id='service' type='number' placeholder='rate 1-10' required>
<div class='top-space'>
<label for='size'>Party Size</label>
</div>
<div>
<input name='size' id='size' type='number' required>
</div>
<div class='top-space'>
<button>LET'S CALCULATE...</button>
</div>
<hr>
<h2>Total: $<span id='amount'>0</span></h2>
</form>
So I have a form with two identical group of inputs that represent education info. There could be more than two as I want to include a button to create a new group so the user can put all his education background like in LinkedIn.
<form id="formCV" action="">
<div id="educationContainer">
<!-- First Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
<!-- Second Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
</div>
</form>
Now, if I use the FormData API to get the form data like this:
for(let entry of formData.entries()){
console.log(entry);
}
I get the following output:
(2) ["institutionName", "Harvard"]
(2) ["courseName", "Web Development"]
(2) ["startDate", "2000-11"]
(2) ["endDate", "2008-11"]
(2) ["institutionName", "Oxford"]
(2) ["courseName", "Business Management"]
(2) ["startDate", "2009-10"]
(2) ["endDate", "2010-05"]
What I want to achieve is to get the output in an organized way, like this:
education:[
{
institutionName:"Harvard",
courseName:"Web Development",
startDate:"2000-11",
endDate:"2008-11"
},
{
...
}
]
So I'm interested in knowing the best approach to achieve this. Thanks in advance for any help!
It does not make sense to have two equal forms, with one being sufficient.
In addition to the form you should have a list that shows each item added.
It's what I recommend.
Not sure whether this is the best approach, but you can achieve the desired structure like this:
const formCV = document.querySelector('#formCV');
const formData = new FormData(formCV);
function groupEducationData(inputGroupSize = 4) {
const result = [];
let educationObj = null;
let counter = 0;
for (const entry of formData.entries()) {
// Since the counter is divisible by the number of inputs in a group
// only if one form group finishes. And when one form group finishes,
// we need to add the object into the result array
if (counter % inputGroupSize === 0) {
// if this is the first iteration, the educationObj is null and
// we don't want to add it to the result array yet
// we only add the educationObj to the result array if it is
// an object containing the education info
if (educationObj) result.push(educationObj);
// initialize the educationObj at the start
// and after one form finishes
educationObj = {};
}
// add entry[0] as key to the object (e.g. 'institutionName')
// with the value of entry[1] (e.g. 'Harvard')
educationObj[entry[0]] = entry[1];
counter++;
}
return result.concat(educationObj);
}
console.log(groupEducationData());
<form id="formCV" action="">
<div id="educationContainer">
<!-- First Group -->
<div class="education">
<div>
<input type="text" name="institutionName" value="Harvard">
</div>
<div>
<input type="text" name="courseName" value="Web Development">
</div>
<div>
<input type="month" name="startDate" value="2000-11">
</div>
<div>
<input type="month" name="endDate" value="2008-11">
</div>
</div>
<!-- Second Group -->
<div class="education">
<div>
<input type="text" name="institutionName" value="Oxford">
</div>
<div>
<input type="text" name="courseName" value="Business Management">
</div>
<div>
<input type="month" name="startDate" value="2009-10">
</div>
<div>
<input type="month" name="endDate" value="2010-05">
</div>
</div>
</div>
</form>
You can try FormData.getAll() and iterate over each group entry.
const institutionNames = formData.getAll('institutionName');
const courseNames = formData.getAll('courseName');
...
const educations = [];
for (let i = 0; i < institutionNames.length; i++) {
educations.push({
institutionName: institutionNames[i],
courseName: courseNames[i],
...
});
}
This is also a way to populate your desired format data.
$(document).ready(function(){
$(":button").click(function(){
var educations=$("#formCV .education");
var data=[];
educations.each(function(i,education){
var set={}
$(education).find(":input").each(function(i,value){
set[$(value).attr("name")] = $(value).val();
});
data.push(set);
})
console.log("data",data)
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<form id="formCV" action="">
<div id="educationContainer">
<!-- First Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
<!-- Second Group -->
<div class="education">
<div>
<input type="text" name="institutionName">
</div>
<div>
<input type="text" name="courseName">
</div>
<div>
<input type="month" name="startDate">
</div>
<div>
<input type="month" name="endDate">
</div>
</div>
</div>
<input type="button" value="click me"/>
</form>
</body>
</html>
How do i automatically display every time I input number and calculate it.
Then the pick button will trigger to calculate the price, my base price would be 100. so if its 2 layers it will be 200 ,
<br> Layer <input type="number" min="1" id="cake_layer" name="cake_layer" /> <!-- onchange="updateTotal()" -->
<input type="button" value="Pick" id="choose" />
<br>
Layer inputed <div class="layer_display"> </div>
<br>
Layer Amount <div class="layer_amt"> </div>
I really need help. thank you !!!
Is this what you want to do?
var cakeLayer = document.getElementById("cake_layer"),
price = 100,
layerDisplay = document.getElementsByClassName("layer_display")[0],
layerAmt = document.getElementsByClassName("layer_amt")[0];
cakeLayer.onchange = function(event) {
var amount = this.value || 0,
totalPrice = amount * price;
layerDisplay.innerText = totalPrice;
layerAmt.innerText = amount;
}
<input type="number" min="1" id="cake_layer" name="cake_layer" />
<!-- onchange="updateTotal()" -->
<input type="button" value="Pick" id="choose" />
<br> total price
<div class="layer_display"> </div>
<br> Layer Amount
<div class="layer_amt"> </div>
You can achieve this by using JavaScript or jQuery. That's the only way to manipulate the DOM.
See this working jsfiddle I made:
https://jsfiddle.net/jw6q53fz/1/
HMTL
<div>
<label for="cake_layer">Layer</label>
<input type="number" class="cake_layer" name="cake_layer" id="cake_layer"/>
<button id="choose">Pick</button>
</div>
<div>
<p>Layer inputed: <span class="layer_display"> </span></p>
<p>Layer Amount: <span class="layer_amt"> </span></p>
</div>
jQuery
$('#choose').on('click', function(){
var cakeLayerValue = $('#cake_layer').val();
$('.layer_display').html(cakeLayerValue);
$('.layer_amt').html(cakeLayerValue * 100);
});
http://puu.sh/3r1jk.png
I have that code and recently implemented the slider. When the slider is moved it changes the win % as I want it to. But if I was to enter it in the input i.e. 60% it would update multiplier and profit. I want it to update multiplier and profit via the slider too.
Code to update inputs:
$(document).ready(functon() {
function updateValues() {
// Grab all the value just incase they're needed.
var chance = $('#chance').val();
var bet = $('#bet').val();
var pay = $('#pay').val();
var profit = $('#profit').val();
// Calculate the new payout.
pay = Math.floor((9900 / (parseFloat(chance) + 0.5)) * 100) / 10000;
// Calculate the new profit.
profit = bet * pay - bet;
profit = profit.toFixed(6);
$('#chance').val(chance);
$('#bet').val(bet);
$('#pay').val(pay);
$('#profit').val(profit);
}
parseFloat($('#chance').keyup(updateValues));
parseFloat($('#bet').keyup(updateValues));
parseFloat($('#pay').keyup(updateValues));
parseFloat($('#profit').keyup(updateValues));
});
Code to update win % via slider:
examples.push({
range: [.01, 98],
start: 49,
handles: 1,
connect: "lower",
serialization: {
to: [$(".exVal")]
}
});
HTML:
<div class="form-box">
<label for="bet">Bet Amount</label>
<input type="text" name="bet" id="bet" class="text" placeholder="amount" />
</div>
<div class="form-box">
<label for="pay">Multiplier</label>
<input type="text" name="pay" id="pay" class="text" placeholder="Payout - 2x Default" />
</div>
<div class="form-box last">
<label for="pay">Profit</label>
<input type="text" name="profit" id="profit" class="text" placeholder="Profit" />
</div>
<div class="clearfix"></div>
<div class="form-box">
<label for="chance">Win Chance (%)</label>
<input type="text" name="chance" id="chance" class="text exVal" value="50" placeholder="Win % - 50.5% Default" />
</div>
<p>Slide to choose win chance or enter it in the input!</p>
<div class="noUiSlider" id="chance" style="margin: 25px 100px 10px 220px; colour:#00aec8;"></div>
Why won't it update?
You have typo in first line "functon" instead of "function".
Also change
parseFloat($('#chance').keyup(updateValues));
parseFloat($('#bet').keyup(updateValues));
parseFloat($('#pay').keyup(updateValues));
parseFloat($('#profit').keyup(updateValues));
to
$('#chance').keyup(updateValues);
$('#bet').keyup(updateValues);
$('#pay').keyup(updateValues);
$('#profit').keyup(updateValues);
EDIT
This slider has no events, so click event handler seems to by only option
$('.noUiSlider, .noUiSlider *').click(updateValues);