Javascript calculate / update total onclick multiple form elements - javascript

Im helping a friend building a basic site. My javascript skills leaves much to be desired so I am learning I started with Javascript instead of Jquery library (sidenote: should I just go with Jquery from the start...?)
So I have the following:
Form with 3 radio buttons value low(1), medium(2), high(3)
Slider with amount
Select with duration.
The formula is calculated by user selecting risk (radio btns) amount (slider) duration (dropdowm)
When the user changes risk, or amount, or duration the total should get updated, and a button displayed.
So I came up with the following javascript:
JAVASCRIPT:
function getReturn(){
var risk = document.forms[0];
var years = document.getElementById("investmentDuration").value;
var slideAmount = document.getElementById("slideAmount").value;
var txt;
var returns;
var i;
for(i = 0; i < risk.length; i++){
if(risk[i].checked){
txt = risk[i].value;
//for
if(txt == 1){
returns = (slideAmount * 0.06)*years;
returns = Math.ceil(returns); // NO decimals
}
if(txt == 2){
returns = slideAmount * 0.11;
returns = Math.ceil(returns)*years; // NO decimals
}
if(txt == 3){
returns = slideAmount *0.17;
returns = Math.ceil(returns)*years; // NO decimals
}
}//if
}//for
I then added the getReturn() function to each element in the form...
I get the following when I try and run it, here is my JS FIDDLE
ERROR: getReturn() is not defined
HTML (note the on click function on each element)
<h2>SELECT INVESTMENT RISK LEVEL</h2>
<section>
<div>
<input type="radio" id="control_01" onclick="getReturn()" name="risk" value="1" checked>
<label for="control_01">
<h2>LOW RISK</h2>
<p>Slow & Steady. An Product Focused On Low Risk But Long term Gains</p>
</label>
</div>
<div>
<input type="radio" id="control_02" name="risk" onclick="getReturn()" value="2">
<label for="control_02">
<h2>MEDIUM</h2>
<p>Prepare For Glory. Medium To High Returns, Over A Medium To Long Period.</p>
</label>
</div>
<div>
<input type="radio" id="control_03" name="risk" onclick="getReturn()" value="3">
<label for="control_03">
<h2>High Risk</h2>
<p>Hardcore Investor. Tailored Based Package Focused on High Returns Over Short Periods</p>
</label>
</div>
</section>
<h4 style="color: black;">INVESTMENT AMOUNT:</h4>
<input type="range" id="slideAmount" name="slideAmount" onchange="getReturn()" value="6500" step="25" min="1000" max="10000">
<p>Number Of Years</p>
<select name="investmentDuration" id="investmentDuration" onclick="getReturn()">
<option value="1" selected>1 Year</option>
<option value="2">2 Years</option>
<option value="3">3 Years</option>
<option value="4">4 Years</option>
<option value="5">5 Years</option>
</select>
UPDATE
I got it to work however I feel
Having a onclick() / onchange = function() on each element seems inefficient.
I feel the code is prone to bugs if the page should get larger and expanded on.
Any constructive criticism and / or advice appreciated on how I can work and improve on this. Many Thanks

You get the
getReturn() is not defined
error because your code is inside an onLoad event (that is the default in jsfiddle)
You need to change this setting as shown in the image so that your function is in the global scope and thus callable from the DOM.
Then you also need to add the #returns element in your html.
A final improvement might be to use the oninput event on the range element so that is updates while you slide
All fixes: https://jsfiddle.net/gaby/o1zmvmL9/2/

Related

why does my submit button not do anything?

I have created two html pages; main info, and Entrance page. the Entrance page is supposed to act similar to a password so that under aged users do not enter the page. problem is my submit button is not doing anything. I would highly appreciate if somebody could help me get it to work since I need to finish it today.
Here is the code I have so far:
<html>
<head>
<!-- this is how you add a code comment-->
<title> Entrance Page </title>
</head>
<body bgcolor="#CEF6F5">
<form>
<h2 align=center><u> Please fill out the following information to proceed to the festival: </u></h2>
<br><br>First Name:<input type="text" name="First Name" id="first"> Last Name:<input type="text"
name="Last Name" id="last">
<br><br> age:<select name="age" id="age">
<option value="1"> below 10 </option>
<option value="2"> 10 </option>
<option value="3"> 11 </option>
<option value="4"> 12 </option>
<option value="5"> 13 </option>
<option value="6"> 14 </option>
<option value="7"> 15 </option>
<option value="8"> 16 </option>
<option value="9"> 17 </option>
<option value="10"> 18 </option>
<option value="11"> 19 </option>
<option value="12"> 20 </option>
<option value="13"> above 20 </option>
</select>
</form>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<p align="center"> <button type="submit" onclick="run()"> Submit </button> </p>
<p><p id="p1"> </p>
<script>
var firstName = document.getElementById("first").value
var lastName = document.getElementById("last").value
var age = document.getElementById("age").value
var isNum = " ";
isNum = isNum + isNaN(firstName)
function run() {
var firstName = document.getElementById("first").value
var lastName = document.getElementById("last").value
if (age < 10 ) {
window.alert("your too young to enter in this event!")//go back to Entrance page
} else if (age > 10) {
window.alert("welcome to the Oktoberfest website!");
window.location.replace("Cost%20of%20an%20Event.html");//go to main website
} else if (age == 10) {
window.alert("lucky! you are just barely old enough to join!")
window.location.replace("Cost%20of%20an%20Event.html");//go to main website
}
}
if (isNum == true) {
window.alert("your name cannot be a number");
}//go back to Entrance page
while (firstName.length ==0) {
window.alert ("you didn't enter a first name ")
document.getElementById("block").value//go back to Entrance page
while (lastNamet.length ==0) {
window.alert ("you didn't enter a last name ")
document.getElementById("block").value//go back to Entrance page
</script>
</body>
</html>
Because your submit button is outside of your form element. This is allowed, but you'd need to add form="id of form here" to associate it with the form.
Even if you fix this issue, all that will happen is that your page will refresh because you also need to specify an action and a method for your form so that it knows how and where to submit the form data.
Learn about the form element here.
You've also got several other problems:
You don't have closing brackets at the end of each of your while
blocks. Your while loops run immediately (before the user has had a
chance to input anything into the form) and so they immediately cause
alert() messages and get you into an infinite loop. You should
probably stay away from while and just check the input in the
submit event of the form and if the input isn't right, display
your error - - no need for a loop.
And your use of HTML is incorrect in several places:
The bgcolor and align attributes are deprecated. All formatting
should be done with CSS, not HTML.
The heading elements (h1, h2, etc.) are for defining sections of
the document. They should not be used because of the formatting
applied to the text within them. As such, you shouldn't have an h2
if you aren't creating a sub-section of an h1, which you are not.
The <br> element should not be used to create artificial vertical
white space. Again, CSS is for layout and styling. br is meant to
force a line break between content, not for introducing blank lines.

Number showing as NaN in <input> when set with jQuery .val() [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to set the value of an input field with jQuery val()
$('[name="paytype1"]').change(function(){
var total = big_total();
total = parseFloat(total);
total = total.toFixed(2);
console.log(total);
if(isNaN(total)) {
alert(total);
}
$('[name="pay1amt"]').val(total);
})
And all that is being shown in the browser is NaN.
Running console.log(total) shows a number, e.g. 61.00, and no alert is being triggered.
The big_total() function is returning the number correctly (it calculates from numbers in other input fields).
function big_total() {
var big_total = 0;
$('.total').each(function(i){
big_total = big_total + parseFloat($(this).val());
});
big_total = big_total.toFixed(2)
return big_total;
}
The inputs with the class total are being added to the page dynamically by jQuery after an ajax call. This is the html that is inserted:
<div class="grid_12 alpha omega line-items">
<div class="grid_1">CH02<input type="hidden" name="item_code[]" value="CH02">
<input type="hidden" name="item_id[]" value="1458">
</div>
<div class="grid_3">
DVA Regular consult
<input type="hidden" name="item_desc[]" value="Subsequent consultation">
<input type="hidden" name="type[]" value="Service">
</div>
<div class="grid_1">
<input type="text" size="3" name="qty[]" value="1" class="qty" max-length="3">
</div>
<div class="grid_2">
<input type="text" size="7" name="sub_total[]" value="61.00" class="sub-total">
</div>
<div class="grid_1">
<select name="tax[]">
<option value="$taxitems[ID]">0%</option>
<option value="$taxitems[ID]">10%</option>
</select>
</div>
<div class="grid_2">
<input type="text" size="7" name="total[]" value="61.00" class="total" readonly="">
</div>
<div class="grid_1 omega">
<div class="remove_stock_line"><img src="images/collapse.png"></div>
</div>
</div>
This is the drop down triggering the function:
<div class="grid_8 alpha omega">
<div class="grid_3 alpha">
<select name="paytype1" class="pay_type">
<option default="" value="nill"></option>
<option value="cash">cash</option>
<option value="HICAPs">HICAPs</option>
<option value="EFTPOS">EFTPOS</option>
<option value="Visa">Visa</option>
<option value="Mastercard">Mastercard</option>
<option value="American Express">American Express</option>
<option value="Other card">Other card</option>
<option value="EFT">EFT</option>
<option value="Cheque">Cheque</option>
</select>
</div>
<div class="grid_3 omega">
<input type="text" size="10" name="pay1amt" value="" onclick="select();" class="pay_values">
</div>
</div>
Thoughts?
There is nothing wrong with this function. But since we cannot see your full source code and you haven't shared your big_total function we can only speculate. From my personal experience I see only two possible scenarios.
big_total() returns a non-numeric value or has leading non-numeric character like $4339, because parseFloat() ignores trailing non-numeric characters except period(.) eg: 83483a;lsdfad will not give you an error. But since you don't see any error in the console or an alert, this scenario can be ruled out.
The only other explanation is that, some other part of the code is overwriting the value set by this function.
If I were you I would follow these steps to debug.
I would replace:
var total = big_total()
with:
var total = 1234.56;
If you see the result in $('[name="pay1amt"]') then the problem is in big_total. If you still see NaN then I would look elsewhere in the code to see where the value is getting overwritten.
This is not related to the question but is very important.
Do not use the variable name big_total inside the function big_total(). Javascript does not differentiate between functions and variables when storing and retrieving them from the stack. Parenthesis directs the interpreter to execute the function while the absence of parenthesis directs the interpreter to reference it as a variable (without executing it).
//Try this code
function hi(){
//without parenthesis it is treated as a variable
alert('without ()\n\n'+hi);
return 6;
}
//with parenthesis it is executed as a function
alert('With () \n'+ hi());
this is working
function big_total() {
var bg_total = 0;
$('.total').each(function(i){
bg_total = bg_total + parseFloat($(this).val());
});
big_total = bg_total.toFixed(2)
return bg_total;
}
$(document).ready(function(){
$("[name='paytype1']").change(function(){
var total = big_total();
total = parseFloat(total);
total = total.toFixed(2);
console.log(total);
if(isNaN(total)) {
alert(total);
}
$('input[name="pay1amt"]').val(total);
});
});
UPDATE
in your big_total() function, $('.total') element is only a class of an input which occurrence is one. why are you using $.each for it
$('.total').each(function(i){
big_total = big_total + parseFloat($(this).val());
});
//you can just replace the use of .each above to this in the big_total function, except you have special reason for that
bg_total = bg_total + parseFloat(".total").val());
<input type="text" size="7" name="total[]" value="61.00" class="total" readonly="">
When you said in the question And all that is being shown in the browser is NaN. Running console.log(total) shows a number, e.g. 61.00, and no alert is being triggered.
NaN will only be shown to when the value of the input with class .total starts with non-numeric. that is only when you should expect the if(isNaN(total)) {alert(total);} to work.
yes the console.log(total) is showing the value 61.00 because The big_total() function is returning the number correctly, but this is what i dont know if you have taken care of (it calculates from numbers in other input fields)
Apart from these your problem should be solved.

how do i make my onchange function generic?

My Javascript function checks for radio button selection and displays the appropriate drop down box. but this code is not generic, i tried using "this" but it doesn't help.. can this actually be generic?
CODE:
function change(s)
{
if(document.getElementById("viewstate").checked==true)
{
document.getElementById("state").style.display="inline";
document.getElementById("cat").style.display="none";
}
else
{
document.getElementById("state").style.display="none";
if(document.getElementById("viewcat").checked==true)
{
document.getElementById("cat").style.display="inline";
}
else
document.getElementById("cat").style.display="none";
}
}
Front end radio button
<input type="radio" name="viewrecord" value="viewstate" onchange="change('state')" required="" id="viewstate"> View by State
<select name="stat" id="state" style="display:none;">
<option selected disabled>Select State</option>
<input type="radio" name="viewrecord" value="viewcat" required="" onchange="change('cat')" id="viewcat">View By Agency
<select id="cat" name="che" style="display:none" required="">
You can try with this snippet
JS
document.addEventListener('click',function(event){
var tar = event.target.id;
if(tar ==="viewstate"){
document.getElementById("state").style.display="inline";
document.getElementById("cat").style.display="none";
}
else if(tar==="viewcat"){
document.getElementById("state").style.display="none";
document.getElementById("cat").style.display="inline";
}
},false)
WORKING COPY
What else I tried?
My primary idea was to add a class to next select tag. For example if you select radio#viewstate it will add a class to closest select element. Then just loop through all the select tag and whoever dont have this class , hide them.
But since you are using display:none nextSibling will not work.For why nextSibling wont work you can take a look at difference between it visibility:hidden
Also note in the demo that I have used label tag with input
If by generic you mean to make the function to be able to work for any similar selection process without depending on the hard-coded values of the selection inputs, this is one way I thought of doing it :
function change(selectorId, selectorClass) {
// Get all the selector elements you use.
var rS = document.getElementsByClassName( selectorClass );
// Out of the elements you fetched above, make the one with
// id = selectorId visible, rest hidden.
for(var i = 0; i < rS.length; ++i)
rS[i].style.display = (rS[i].id == selectorId) ? "inline" : "none";
}
In the HTML part add a class to every select input you want to use with the radio values:
<input type="radio" name="viewrecord" value="viewstate" onchange="change('state', 'record-selector')" required="" id="viewstate"> View by State
<select class='record-selector' name="stat" id="state" style="display:none;">
<option selected disabled>Select State</option>
<input type="radio" name="viewrecord" value="viewcat" required="" onchange="change('cat', 'record-selector')" id="viewcat">View By Agency
<select class='record-selector' id="cat" name="che" style="display:none" required="">
With this you can use the same function for similar selection process on different forms.

Checkboxes and <select> options don't persist in HTML 5 local storage

I'm coming to an unexpected conclusion regarding HTML5 local storage persistence and inputs. When I use < input type="text" > or < input type="textarea" >, then the data persists in local storage and on page load loads back into fields at the push of a button. But when I use type="radio" type="checkbox" or < select > options, none of those types of data persists.
Is this behavior by design, and I'm pushing against a brick wall trying to make it work, or is it my form element scripting that needs an overhaul? If it's by design, then you can answer yes. If not, you can check the details of my work below to give it a checkup and any feedback.
The user enters data into textarea fields like this:
<textarea name="s1frontTowerShockMtgOther" id="s1frontTowerShockMtgOther" cols="20" rows="4">
Then they tap on the save button coded like this:
<input type="button" value="Save Settings" onclick="persistData()" style="background-color:red; font-weight:bold">
The Javascript page does its magic:
function persistData()
{
if (html5StorageSupported())
{
var s1frontTowerShockMtgOther = document.form1["s1frontTowerShockMtgOther"].value;
var storageIndex = "practicelog.html.s1frontTowerShockMtgOther";
localStorage[storageIndex] = s1frontTowerShockMtgOther;
document.form1.numStored.value = determineNumberStoredElements();
}
}
When the user returns to the page, he taps on this button to populate the fields on that page:
<input class="loadButton" type="button" value="Load Data First" onclick="loadData()">
The Javascript is called:
function loadData()
{
document.form1["s1frontTowerShockMtgOther"].value = localStorage["practicelog.html.s1frontTowerShockMtgOther"];
}
That's it. The following does not work:
<select size="1" name="frontTowerMtgShock" id="frontTowerMtgShock">
<option value="">Tap to choose</option>
<option value="0 spacers">3-outer</option>
<option value="1 spacer">2-middle</option>
<option value="2 spacers">1-inner</option>
<option value="other">See notes</option>
</select>
The following type="checkbox" does not work. It doesn't work if "checkbox" was replaced by "radio" either:
<input type="checkbox" name="s1frontTowerMtgShock3" id="s1frontTowerMtgShock3" value="3-outer">
I am doing this project for the iPhone with HTML, CSS, and Javascript through PhoneGap 1.0 integration.
The following works fine for me:
function persistData()
{
var s1frontTowerShockMtgOther = document.form1["s1frontTowerShockMtgOther"].value;
var storageIndex = "practicelog.html.s1frontTowerShockMtgOther";
localStorage[storageIndex] = s1frontTowerShockMtgOther;
storageIndex = "practicelog.html.frontTowerMtgShock";
var frontTowerMtgShock = document.form1["frontTowerMtgShock"].value;
localStorage[storageIndex] = frontTowerMtgShock;
}
function loadData()
{
alert(localStorage["practicelog.html.frontTowerMtgShock"]);
document.form1["frontTowerMtgShock"].value = localStorage["practicelog.html.frontTowerMtgShock"];
}
Have you double checked your storage keys when setting and retrieving?

how to change color of text following function in javascript

Ok before i make spaghetti of this code i thought id ask around here. ive made a quiz for an online site.
The answers are stored in an array, and ive a function that checks the answers array to what youve clicked. then it counts them and gives you your score.
but i want to change the clor of the right answer wen the user clicks the score button. so the correct answers are highlighted. something like this https://www.shutterpoint.com/Home-Quiz.cfm (just hit submit at the bottom, no need to do the quiz).
the little answer icon at the side looks flashy but id rather just have the text change color. heres how my questions are formatted
<p>Film speed refers to:</p>
<p id = "question1">
<input type="radio" name="question1" id="Wrong" value = "a" onClick = "recordAnswer(1,this.value)"/>How long it takes to develop film. <br/>
<input type="radio" name="question1" id="Wrong" value = "b" onClick = "recordAnswer(1,this.value)"/>How fast film moves through film-transport system. <br/>
<input type="radio" name="question1" id="Answer" value = "c" onClick = "recordAnswer(1,this.value)"/> How sensitive the film is to light. <br/>
<input type="radio" name="question1" id="Wrong" value = "d" onClick = "recordAnswer(1,this.value)"/> None of these makes sense. <br/></p>
and these are the two functions that are called throughout. record answer is called every time the user clicks a button
function recordAnswer(question,answer)
{
answers[question-1] = answer;
}
this is the final button which calculates the score
function scoreQuiz()
{
var totalCorrect = 0;
for(var count = 0; count<correctAnswers.length;count++)
{
if(answers[count]== correctAnswers[count])
totalCorrect++;
}
<!--
alert("You scored " + totalCorrect + " out of 12 correct!");
-->
}
another function is best i think. ive already made attempts at it and know i have to set the color using
document.getElementById('Answer').style.color = '#0000ff';
onyl problem is 'Answer' doesnt seem to be registering. anyone shed some light?
ok so i cant have two or more of the same ids.
what about
if(value == correctAnswers[])
{
// change the color.
}
QUICK RESPONCE:
USE <P>
<p>
<input type="radio" name="question_1" class="wrong" value="a" />
How long it takes to develop film.
</p>
THEN
if(value == correctAnswers[])
{
YOUR_ELEMENT.parentNode.style.color = 'green';
}
IMPROVEMENT
DEMO: http://jsbin.com/aceze/26
hi Overtone!
first of all you need to restyle a litte your HTML schema!
you have multiple id="Wrong" instead of class="Wrong"
then here how your code should look:
var answers = { 1:'a' , 2:'f' , 3:'h' };
function checkQuestions() {
var form_elements = document.question_form.elements.length;
for ( var i = 0; i < form_elements; i++ )
{
var type = question_form.elements[i].type;
if ( type == "radio" ){
var quest = question_form.elements[i];
//if ( quest.checked ) {
var question_index = parseInt(quest.name.split('_')[1]);
//}
if ( quest.value == answers[question_index] ) {
quest.parentNode.style.border = '1px solid green';
quest.parentNode.style.color = 'green';
} else {
//quest.parentNode.style.border = '1px solid red';
quest.parentNode.style.color = 'red';
}
}
}
}
USE a FORM and one time SUBMIT BUTTON instead of adding onclick to each RADIO like this
<form name="question_form" id="question_form" method="POST" action='#'>
<div id="question_1"> <H4>QUESTIONS TIME 1</H4>
</div>
<p>
<input type="radio" name="question_1" class="wrong" value="a" />
How long it takes to develop film.
</p>
<p>
<input type="radio" name="question_1" class="wrong" value="b" />
How fast film moves through film-transport system.
</p>
<p>
<input type="radio" name="question_1" class="answer" value="c" />
How sensitive the film is to light.
</p>
<p>
<input type="radio" name="question_1" class="wrong" value="d" />
None of these makes sense.
</p>
...
...
<input type="radio" name="question_2" class="wrong" value="h" />
<span>None of these makes sense.
</span>
</p>
<input type="submit" name="submit" onclick="checkQuestions();return false;" value="submit"/>
</form>
PS: demo example updated with style... for sake!
You should format your ids in a more usable way.. I'd suggest something similar to questionNUMBER_answerVALUE.
Then it'd be a simple matter of...
for (var i=0; i<correctAnswers;i++) {
document.getElementById("question" + (i+1) + "_answer" + correctAnswers[i].toUpperCase()).style.color = "#0000FF";
};
Just check I've got your zero/non-zero indexing correct with regard to question/ answer numbers.
Instead of using a <p> I would consider using a <label for='question1_answerA'>How long it takes to develop film.</label>. You can still use a jQuery selector to find it and it feels more semantically correct. You will then also be able to select the option by clicking the text.
Although your other HTML isn't semantically correct. You need to give each radio a unique ID.
Obligatory jquery solution:
var highlightCorrect = function(){
$(".Answer").css("color", "#00FF00");
}
This is all assuming that you fix your HTML to use classes rather than IDs for "Wrong" and "Answer".

Categories

Resources