PDA

View Full Version : Auto-totaling order form using radio buttons



monstrotanker
08-24-2005, 08:47 PM
Hi ya'll, I'm working on an order form that will allow me to use radio buttons to customize products. I would like it to automatically total each radio button as it is checked. I have this part down. The problem is that each time I click a radio button, it adds to the total, though in some cases (e.g. when the user wants to change an option in the current radio group, the javascript needs to subtract the hiddenpriorradio.value and then add the new one). I have been working on this for a couple days and have come to the realization that I'm not going to get it figured out. I would tremendously appreciate some help. I have attached what I have thus far as a text file. Thanks much, //mt

mattster
08-25-2005, 11:56 AM
I have done a few similar forms of this type before and the way i generally get round this is to have a hidden field for each group of radio buttons. By selecting a radion button you change the value of the hidden field associated to that group, then all you need to do is SUM the hidden fields. Much easier. ;)

monstrotanker
08-26-2005, 03:34 AM
Thanks mattster. I took your good advice and am adding the values to hidden fields and plan on totalling these fields. This is where my next problem starts. :confused: I think I am having a problem totaling the currency values. I'm going to reattach my updated page as a text file hoping someone can take a look and give some advice on calculating all the hidden fields into the grand total. thanks

mattster
08-26-2005, 10:58 AM
Unfortunately i found it somewhat tricky reading through all your code as you seem to have lots of other things going on there. Look at this code and see if it helps, it should point you in the right direction:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body>

<SCRIPT language="javascript">
function cent(amount) {
return (amount == Math.floor(amount)) ? amount + '.00' : ( (amount*10 == Math.floor(amount*10)) ? amount + '0' : amount);
}

function calculate() {
var p1, p2, p3;
p1 = test.price1.value * 1;
p2 = test.price2.value * 1;
p3 = test.price3.value * 1;
total_price = p1 + p2 + p3;
test.total_price.value = cent(Math.round(total_price*Math.pow(10,2))/Math.pow(10,2));
}

</SCRIPT>

<form name="test" method="post" action="">
<p>
<input name="1" type="radio" value="0" onclick="this.form.price1.value='0.00';calculate();">0.00<br />
<input name="1" type="radio" value="10" onclick="this.form.price1.value='10.00';calculate();">10.00<br />
<input name="1" type="radio" value="20" onclick="this.form.price1.value='20.00';calculate();">20.00<br />
<input name="1" type="radio" value="30" onclick="this.form.price1.value='30.00';calculate();">30.00<br />
<input type="hidden" name="price1">
</p>
<p>
<input name="2" type="radio" value="0" onclick="this.form.price2.value='0.00';calculate();">0.00<br />
<input name="2" type="radio" value="10" onclick="this.form.price2.value='10.00';calculate();">10.00<br />
<input name="2" type="radio" value="20" onclick="this.form.price2.value='20.00';calculate();">20.00<br />
<input name="2" type="radio" value="30" onclick="this.form.price2.value='30.00';calculate();">30.00<br />
<input type="hidden" name="price2">
</p>
<p>
<input name="3" type="radio" value="0" onclick="this.form.price3.value='0.00';calculate();">0.00<br />
<input name="3" type="radio" value="10" onclick="this.form.price3.value='10.00';calculate();">10.00<br />
<input name="3" type="radio" value="20" onclick="this.form.price3.value='20.00';calculate();">20.00<br />
<input name="3" type="radio" value="30" onclick="this.form.price3.value='30.00';calculate();">30.00<br />
<input type="hidden" name="price3">
</p>
<p>&nbsp;</p>
<p>Total: <input type="textfield" name="total_price"></p>
</form>

</body>
</html>

It's not the best code but it works.

mwinter
08-26-2005, 10:19 PM
Using hidden form controls are totally unnecessary and just add junk into the markup (and form data).


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html lang="en" dir="ltr">
<head>
<title>Order form</title>

<style type="text/css">
@media screen {
body {
font: 100% sans-serif;
}
h1 {
font: 130% normal sans-serif;
text-align: center;
}
fieldset {
border-style: none;
margin: 0 0 1em;
padding: 0.5ex;
}
label {
display: block;
margin-left: 1em;
width: 12em;
}
legend {
font-weight: bold;
margin: 0;
padding: 0;
}
#order {
position: relative;
}
#total {
display: block;
margin-left: auto;
margin-right: auto;
width: 6em;
}
#total-group {
border-style: none;
text-align: center;
position: fixed;
right: 10%;
top: 20%;
width: 8em;
}
#total-group legend {
display: none;
}
#total-label {
margin-bottom: 0.75em;
margin-left: 0;
width: auto;
}
}
</style>
</head>

<body>
<h1>Computer A</h1>
<form id="order" action="" method="post">
<fieldset><legend>Processor</legend>
<label><input name="processor" type="radio" value="0" checked>
Default option</label>
<label><input name="processor" type="radio" value="50">
Upgrade 1 ($50.00)</label>
<label><input name="processor" type="radio" value="100">
Upgrade 2 ($100.00)</label>
</fieldset>
<fieldset><legend>Memory</legend>
<label><input name="memory" type="radio" value="0" checked>
Default option</label>
<label><input name="memory" type="radio" value="50">
Upgrade 1 ($50.00)</label>
<label><input name="memory" type="radio" value="100">
Upgrade 2 ($100.00)</label>
</fieldset>
<fieldset><legend>Hard Drive</legend>
<label><input name="hard-drive" type="radio" value="0" checked>
Default option</label>
<label><input name="hard-drive" type="radio" value="50">
Upgrade 1 ($50.00)</label>
<label><input name="hard-drive" type="radio" value="100">
Upgrade 2 ($100.00)</label>
</fieldset>
<fieldset id="total-group"><legend>Total</legend>
<label id="total-label">Your total:
<input id="total" type="text" value="$0.00"></label>
<input type="submit" value="Send">
<input type="reset" value="Reset">
</fieldset>
</form>
<script type="text/javascript">
Number.prototype.toCurrency = function(c, t, d) {
var n = +this,
s = (0 > n) ? '-' : '',
m = String(Math.round(Math.abs(n))),
i = '',
j, f;
c = c || '';
t = t || '';
d = d || '.';

while (m.length < 3) {m = '0' + m;}
f = m.substring((j = m.length - 2));
while (j > 3) {i = t + m.substring(j - 3, j) + i; j -= 3;}
i = m.substring(0, j) + i;
return s + c + i + d + f;
};

if(document.getElementsByName) {
(function() {
var E = document.forms.order.elements,
T = E.total;

function calculateTotal() {
var t = 0,
e, v;

if((e = getChecked('processor', this.form, 'radio'))) {t += +e.value;}
if((e = getChecked('memory', this.form, 'radio'))) {t += +e.value;}
if((e = getChecked('hard-drive', this.form, 'radio'))) {t += +e.value;}

T.value = (t * 100).toCurrency('$');
}
function getChecked(gN, f, t) {
var g = document.getElementsByName(gN);
t = t || 'checkbox';

for(var i = 0, n = g.length, c; i < n; ++i) {
if((t == (c = g[i]).type) && c.checked && (f == c.form)) {return c;}
}
}

for(var i = 0, n = E.length; i < n; ++i) {
if('radio' == E[i].type) {
E[i].onchange = calculateTotal;
}
}
E = null;
})();
}
</script>
</body>
</html>Of course, you should export the style sheet and script into external files.

You may notice that the calculateTotal function expects numbers, not product identifiers. The simplest and cleanest way to adapt the script is to include the prices as script data. So, taking processors as an example, you would include something like:


var processors = {
'P4_3.2' : 0,
'P4_3.4' : 10,
'P4_3.6' : 20,
'P4_3.8' : 30,
'P4_4.0' : 40
};and alter calculateTotal to:


function calculateTotal() {
var t = 0,
e, v;

if((e = getChecked('processor', this.form, 'radio'))) {t += processors[e.value];}
if((e = getChecked('memory', this.form, 'radio'))) {t += +e.value;}
if((e = getChecked('hard-drive', this.form, 'radio'))) {t += +e.value;}

T.value = (t * 100).toCurrency('$');
}The other components follow suit.

Hope that helps,
Mike

monstrotanker
08-29-2005, 04:31 AM
:D Thanks a bunch Mike. This is working great.

te(X)en
06-06-2006, 10:16 PM
I'm sorry for bringing back up this old topic, but the code Mike is suggesting works perfectly for my problem when I try it in Firefox. Only when I try it in Internet Explorer (6.0) the total doesn't add up automatically.
After I click a radio button, I first have to click somewhere else before the total value changes.

I copied the code into this HTML file:
http://www.texen.nl/test/total.html

Since I'm just a beginner in JavaScript, I couldn't find the solution for this, so I'm hoping one of you knows how to solve this.
Thanks in advance!

djr33
06-07-2006, 03:44 AM
Doesn't work in Safari either. Not sure what's going on, sorry.


One idea, though, is to call your javascript function for every radio button markup using onChange="function()" as an attribute.

That should do it when you change any of the radio buttons.

Even onClick might help.

raindog
09-03-2009, 07:10 PM
Thanks Mike for the excellent code suggestion - I'm a javascript rookie & would like to use more than one calculator script on the same page (to calculate several groups of values separately) and I'd like to show a total of those calculations as well. Can you suggest the easiest/best way to do that?

Thanks again!


Using hidden form controls are totally unnecessary and just add junk into the markup (and form data).


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html lang="en" dir="ltr">
<head>
<title>Order form</title>

<style type="text/css">
@media screen {
body {
font: 100% sans-serif;
}
h1 {
font: 130% normal sans-serif;
text-align: center;
}
fieldset {
border-style: none;
margin: 0 0 1em;
padding: 0.5ex;
}
label {
display: block;
margin-left: 1em;
width: 12em;
}
legend {
font-weight: bold;
margin: 0;
padding: 0;
}
#order {
position: relative;
}
#total {
display: block;
margin-left: auto;
margin-right: auto;
width: 6em;
}
#total-group {
border-style: none;
text-align: center;
position: fixed;
right: 10%;
top: 20%;
width: 8em;
}
#total-group legend {
display: none;
}
#total-label {
margin-bottom: 0.75em;
margin-left: 0;
width: auto;
}
}
</style>
</head>

<body>
<h1>Computer A</h1>
<form id="order" action="" method="post">
<fieldset><legend>Processor</legend>
<label><input name="processor" type="radio" value="0" checked>
Default option</label>
<label><input name="processor" type="radio" value="50">
Upgrade 1 ($50.00)</label>
<label><input name="processor" type="radio" value="100">
Upgrade 2 ($100.00)</label>
</fieldset>
<fieldset><legend>Memory</legend>
<label><input name="memory" type="radio" value="0" checked>
Default option</label>
<label><input name="memory" type="radio" value="50">
Upgrade 1 ($50.00)</label>
<label><input name="memory" type="radio" value="100">
Upgrade 2 ($100.00)</label>
</fieldset>
<fieldset><legend>Hard Drive</legend>
<label><input name="hard-drive" type="radio" value="0" checked>
Default option</label>
<label><input name="hard-drive" type="radio" value="50">
Upgrade 1 ($50.00)</label>
<label><input name="hard-drive" type="radio" value="100">
Upgrade 2 ($100.00)</label>
</fieldset>
<fieldset id="total-group"><legend>Total</legend>
<label id="total-label">Your total:
<input id="total" type="text" value="$0.00"></label>
<input type="submit" value="Send">
<input type="reset" value="Reset">
</fieldset>
</form>
<script type="text/javascript">
Number.prototype.toCurrency = function(c, t, d) {
var n = +this,
s = (0 > n) ? '-' : '',
m = String(Math.round(Math.abs(n))),
i = '',
j, f;
c = c || '';
t = t || '';
d = d || '.';

while (m.length < 3) {m = '0' + m;}
f = m.substring((j = m.length - 2));
while (j > 3) {i = t + m.substring(j - 3, j) + i; j -= 3;}
i = m.substring(0, j) + i;
return s + c + i + d + f;
};

if(document.getElementsByName) {
(function() {
var E = document.forms.order.elements,
T = E.total;

function calculateTotal() {
var t = 0,
e, v;

if((e = getChecked('processor', this.form, 'radio'))) {t += +e.value;}
if((e = getChecked('memory', this.form, 'radio'))) {t += +e.value;}
if((e = getChecked('hard-drive', this.form, 'radio'))) {t += +e.value;}

T.value = (t * 100).toCurrency('$');
}
function getChecked(gN, f, t) {
var g = document.getElementsByName(gN);
t = t || 'checkbox';

for(var i = 0, n = g.length, c; i < n; ++i) {
if((t == (c = g[i]).type) && c.checked && (f == c.form)) {return c;}
}
}

for(var i = 0, n = E.length; i < n; ++i) {
if('radio' == E[i].type) {
E[i].onchange = calculateTotal;
}
}
E = null;
})();
}
</script>
</body>
</html>Of course, you should export the style sheet and script into external files.

You may notice that the calculateTotal function expects numbers, not product identifiers. The simplest and cleanest way to adapt the script is to include the prices as script data. So, taking processors as an example, you would include something like:


var processors = {
'P4_3.2' : 0,
'P4_3.4' : 10,
'P4_3.6' : 20,
'P4_3.8' : 30,
'P4_4.0' : 40
};and alter calculateTotal to:


function calculateTotal() {
var t = 0,
e, v;

if((e = getChecked('processor', this.form, 'radio'))) {t += processors[e.value];}
if((e = getChecked('memory', this.form, 'radio'))) {t += +e.value;}
if((e = getChecked('hard-drive', this.form, 'radio'))) {t += +e.value;}

T.value = (t * 100).toCurrency('$');
}The other components follow suit.

Hope that helps,
Mike