I am attempting to make my first attempt at Javascript taking user input and then changing the html of an element to spit out a value. It's a calorie calculator. Here's my HTML, my javascript, and an explanation of what I think is SUPPOSED to happen with my limited knowledge:
<center>
<p>Fill out the form below.</p>
<input type="radio" name="female" value="665.09" oninput="calsPerDay" ><p>Female</p>
<input type="radio" name="male" value="66.47" oninput="calsPerDay" ><p>Male</p>
<input id="age" type="number" oninput="calsPerDay"><p>Age</p><br>
<input id="height" type="number" oninput="calsPerDay"><p> Height- In Inches (12 inches=1 foot)</p>
<input id="weight" type="number" oninput="calsPerDay"><p> Weight (in pounds)</p><br>
</center>
<p id="totalCals"> </p> <p>kcal per day</p>
function calsPerDay() {
var age=document.getElementById("age").value;
var height=document.getElementById("height").value;
var weight=document.getElementById("weight").value;
var female=document.getElementsByName("female").value;
var male=document.getElementsByName("male").value;
if (document.getElementsByName("male").checked) {
var maleCals = male+ (13.75 * weight/2.2) + (5.0 * (height * 2.54) - (6.75 x age);
document.getElementById("totalCals").innerHTML = maleCals;
} else (document.getElementsByName("female").checked) {
var femaleCals = female + (9.56 * weight/2.2) + (1.84 * (height * 2.54) - (4.67 x age);
document.getElementById("totalCals").innerHTML = femaleCals;
}
}
What I expect to happen is that the function will first check if the user has checked off male or female. Then if they check off male, it creates a new variable (not sure if this would be the most optimal way to do this anyway0 where it adds male (because I put var male = document.getElementsByName("male").value and its a radio type input, I read that it would read what you put as the value so I assumed that "male" in the variable maleCals would bee that value, 66.47. Then I assumed the height and weight would be read as whatever the number the user puts in the input forms and then be spit out as a paragraph for the <p>
element with the id of totalCals.
Here's a JS fiddle for it: /
My dilemma is that it simply isn't working, when you put in values, nothing's being written in the <p>
tags.
Any suggestions would be helpful.
I am attempting to make my first attempt at Javascript taking user input and then changing the html of an element to spit out a value. It's a calorie calculator. Here's my HTML, my javascript, and an explanation of what I think is SUPPOSED to happen with my limited knowledge:
<center>
<p>Fill out the form below.</p>
<input type="radio" name="female" value="665.09" oninput="calsPerDay" ><p>Female</p>
<input type="radio" name="male" value="66.47" oninput="calsPerDay" ><p>Male</p>
<input id="age" type="number" oninput="calsPerDay"><p>Age</p><br>
<input id="height" type="number" oninput="calsPerDay"><p> Height- In Inches (12 inches=1 foot)</p>
<input id="weight" type="number" oninput="calsPerDay"><p> Weight (in pounds)</p><br>
</center>
<p id="totalCals"> </p> <p>kcal per day</p>
function calsPerDay() {
var age=document.getElementById("age").value;
var height=document.getElementById("height").value;
var weight=document.getElementById("weight").value;
var female=document.getElementsByName("female").value;
var male=document.getElementsByName("male").value;
if (document.getElementsByName("male").checked) {
var maleCals = male+ (13.75 * weight/2.2) + (5.0 * (height * 2.54) - (6.75 x age);
document.getElementById("totalCals").innerHTML = maleCals;
} else (document.getElementsByName("female").checked) {
var femaleCals = female + (9.56 * weight/2.2) + (1.84 * (height * 2.54) - (4.67 x age);
document.getElementById("totalCals").innerHTML = femaleCals;
}
}
What I expect to happen is that the function will first check if the user has checked off male or female. Then if they check off male, it creates a new variable (not sure if this would be the most optimal way to do this anyway0 where it adds male (because I put var male = document.getElementsByName("male").value and its a radio type input, I read that it would read what you put as the value so I assumed that "male" in the variable maleCals would bee that value, 66.47. Then I assumed the height and weight would be read as whatever the number the user puts in the input forms and then be spit out as a paragraph for the <p>
element with the id of totalCals.
Here's a JS fiddle for it: https://jsfiddle/oafu54x3/
My dilemma is that it simply isn't working, when you put in values, nothing's being written in the <p>
tags.
Any suggestions would be helpful.
Share Improve this question edited Jan 24, 2016 at 11:57 Mr Lister 46.6k15 gold badges113 silver badges155 bronze badges asked Jan 17, 2016 at 23:45 zasmanzasman 4861 gold badge9 silver badges32 bronze badges 2- Well you should change your approach, instead of defining new variables, use coefficients for each gender. I am also sending an answer below. – st. Commented Jan 17, 2016 at 23:48
- Ok great, I will look up how to use coefficients. Thank you! – zasman Commented Jan 18, 2016 at 0:12
2 Answers
Reset to default 4The problem is when you use getElementsByName
, it returns an object array not the object you are looking for.
You should use getElementById
for those too.
There are numerous problems.
Lets's start by cleaning up the HTML:-
<h1>Fill out the form below.</h1>
<label>Female:
<input id="female" type="radio" name="gender" onchange="calsPerDay()">
</label>
<label>Male:
<input id="male" type="radio" name="gender" onchange="calsPerDay()" checked>
</label>
<label>Age:
<input id="age" type="number" oninput="calsPerDay()" value="50">
years
</label>
<label>Height:
<input id="height" type="number" oninput="calsPerDay()" value="70">
in inches (12 inches=1 foot)
</label>
<label>Weight:
<input id="weight" type="number" oninput="calsPerDay()" value="225">
in pounds
</label>
<label>
Base metabolic rate: <span id="totalCals"></span> kcal per day
</label>
By placing the input
elements inside label
tags, the user can now click anywhere in the label to give the contained input
element focus.
Note also that both the radio buttons need to have the same name
attribute. So in order to differentiate between them, they need to have different id
attributes.
On some browsers you need to place ()
at the end of each event handler name. If you can't predict which browser will be used by the client, then it is better to play it safe. So always include them.
To make testing easier, I have added a selected
attribute to the male radio button, and default value
attributes to the other input
elements. Please feel free to remove them before deployment.
The value
attributes on the radio buttons are really things that belong in the model (i.e. javascript) not in the view (i.e. html).
Now add a bit of style in CSS:-
label {
display: block;
box-shadow: 0.1em 0.1em 0.2em #888;
margin: 1em;
border-radius: 1ex;
padding: 1ex 1em;
}
input[type=number] {
text-align: right;
border: none;
}
input {
float: right;
}
span {
font-weight: bold;
}
And finally clean up the Javascript:-
function calsPerDay() {
function find(id) { return document.getElementById(id) }
var age = find("age").value
var height = find("height").value * 2.54
var weight = find("weight").value / 2.2
var result = 0
if (find("male").checked)
result = 66.47 + (13.75 * weight) + (5.0 * height - (6.75 * age))
else if (find("female").checked)
result = 665.09 + (9.56 * weight) + (1.84 * height - (4.67 * age))
find("totalCals").innerHTML = Math.round( result )
}
calsPerDay()
I know many people won't agree but I personally find code duplication distracting. In your code document.getElementById(id)
is repeated often. So I have extracted that behaviour out into a little helper function find
. Now the rest of the code reads so much better.
Because you apply the same scaling factor to weight, height regardless of the gender, I moved that scaling out, and now it is no longer duplicated.
Notice that I assumed the missing closing braces should go at the end of the formulae. I can't check this as I don't have access to the source document where you discovered these formulae.
You also used "x" inside a formula instead of "*". This is a mon mistake as one transitions from written algebra to puter algorithms. Take care on this one.
Lastly I have removed all those unnecessary (and distracting) semicolons. In Javascript there are only a few rare occasions where you actually must use semicolons.
You can see a working CodePen here