Display running total

I have the following form segment:

			<table width="90%" border = "0" style="margin-left:40px; 	font-family: helvetica, ariel, sans-serif; font-size: 0.95em; color: #2D8AB9;">
				<tr style="height:3em">
					<td width="2em"><input type="checkbox" name="skipperReg" value="<?php echo $skipperFee ?>" /></td>
					<td width="12em">Registration Fee</td>
					<td width="4em" style="text-align:right">$<input type="text" name="total" readonly="readonly" size ="2" value="<?php echo $skipperFee ?>" /></td>
					<td width ="20em">&nbsp;</td>
				</tr>
				<tr>
					<td ><input type="checkbox" name="guestReg" value="<?php echo $guestFee ?>" /></td>
					<td>Guest Fee</td><td style="text-align:right">$<input type="text" name="total" readonly="readonly" size ="2" value="<?php echo $guestFee ?>" /></td>
					<td>&nbsp;&nbsp;# Guests&nbsp;<input type="text" name="GuestQty" size="2" /></td>
				</tr>
				<tr>
					<td ><input type="checkbox" name="miscAmt"/></td>
					<td>Misc</td><td style="text-align:right">$<input type="text" name="miscTotal" size ="2" /></td>
					<td>&nbsp;&nbsp;List details&nbsp;<input type="text" name="miscDetails" size="15" /></td>
				</tr>
				<tr style="height:2em"><td >&nbsp;</td>
					<td>Total</td><td style="text-align:right">$<input type="text" name="total" readonly="readonly" size ="2"></td>
				</tr>
			</table>

I need a JavaScript that will
• If skipperReg is checked, add skipperFee value to the total
• If guestReg is checked, add guestFee value times guestQty to the total
• If miscAmt is checked, add miscTotal value to the total
• Display the new total each time the other inputs are changed.

TIA,
–Doug

You can attach a function to the form that will be run whenever something in the form changes.

So if the form had an id of “booking”, such as:


<form id="booking" ...>
    ...
</form>

you could then attach a function to whenever the form changes, with:


var updateForm = function () {
    ...
};
var form = document.getElementById('booking');
form.onchange = updateForm;

That way, you can specify what needs to be done within that function, for example:


var updateForm = function () {
    var form = this,
        total = 0;
    if (form.elements.skipperReg.checked) {
        total += Number(form.elements.skipperReg.value);
    }
    ...
    form.elements.total = total;
};

There’s also other ways of doing this with less repetition, such as placing the boxes to be checked in an array and looping through that array adding the appropriate results to the total.


var updateForm = function () {
    var form = this,
        total = 0,
        fieldsToCheck = ['skipperReg', ...],
        i,
        checkbox;
    for (i = 0; i < fieldsToCheck.length; i += 1) {
        checkbox = form.elements[fieldsToCheck[i]];
        if (checkbox.checked) {
            total += Number(checkbox.value);
        }
    }
    form.elements.total = total;
};

Or if you have access to JavaScript 1.6 (or you can use the compatibility code from Array.forEach()) you can simplify this even further with:


var updateForm = function () {
    var form = this,
        fieldsToCheck = ['skipperReg', ...],
        total = 0;
    fieldsToCheck.forEach(function () {
        var checkbox = form.elements[this];
        total += (checkbox.checked) ? Number(checkbox.value) : 0;
    });
    form.elements.total = total;
};

Or if you have access to JavaScript 1.8 you can use Array.reduce() on the array instead (helped by the compatibility code for lesser web browsers):


var updateForm = function () {
    this.elements.total =  ['skipperReg', ...].reduce(function () {
        var checkbox = form.elements[this];
        return (checkbox.checked) ? Number(checkbox.value) : 0;
    }, 0);
};

There’s pretty much a vast number of ways of doing this.

Thanks, Paul, for the information.
I added the following script to my page:

<script type="text/javascript">
var updateForm = function () {
    var form = this,
        total = 0;
    if (form.elements.skipperReg.checked) {
        total += Number(form.elements.skipperReg.value);
		document.write("Skipper Registration")
    }
/*    if (form.elements.guestReg.checked) {
        total += Number(form.elements.guestReg.value) * Number(form.elements.guestQty.value);
    }*/
    if (form.elements.miscAmt.checked) {
        total += Number(form.elements.miscAmt.value);
    }
    form.elements.total = total;
};

var form = document.getElementById("theform")
form.onchange = updateForm;
</script>

If the commented line is left in, I get a blank page. If left out, I see my page correctly, but the expected change from the JS is not seen.

I put in the document.write line to see if I could make the script do anything.

Is there something obviously wrong that you can see in my script? What is the best way to troubleshoot the problem?

–Doug

The best way to troubleshoot is to check your assumptions about the form. Are the form fields that you’re trying to access actually called what you think they are?

I realize that you are trying to “teach” me, rather than “tell” me, and I appreciate that. But, unfortunately, my knowledge level is so low, I can’t process your last hint. Could you make it a little more specific? Thanks.

–Doug

Sure thing.

<input type="text" name="[color="red"]G[/color]uestQty" size="2" />

...

... * Number(form.elements.[color="red"]g[/color]uestQty.value);