Reputation: 9
So I've managed to put together some JavaScript (with some help from others) which is basically a form that allows you to change the quantity of an item and add its value to the total if its checkbox is ticked (total displays in text field at bottom).
I understand some of it, its just the more complex parts of it that are confusing me (such as the logic). Could somebody talk me through or perhaps comment the main parts of my code so it can help me in understanding how the code is working.
<script type="text/javascript">
function bump( which, bywhat ) {
var form = document.items;
var qty = form["qty" + which];
qty.value = Number(qty.value) + bywhat;
TotalCheckedValues( ); // in case user bumped an already checked line
}
function TotalCheckedValues( ) {
var form = document.items;
var total = 0;
for ( var n = 1; n <= 4; ++n )
{
if ( form["cb"+n].checked ) // if the checkbox of the item is ticked
{
total += form["cb"+n].value * form["qty"+n].value; //
}
}
form.Total.value = total.toFixed(2);
}
function validate(evt) {
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
var regex = /[0-9]|\./;
key = String.fromCharCode( key );
if(!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault) {
theEvent.preventDefault();
}
}
}
</script>
</head>
<body>
<form name="items">
Item <input type="text" onkeypress='validate(event)'name="qty1" value="0"/>
<input type="button" onclick="bump(1,1)" value="+"/>
<input type="button" onclick="bump(1,-1)" value="-"/>
<input type="checkbox" name="cb1" value="20.00"
onClick="TotalCheckedValues()" />Service 1 (£20.00) <br />
Item <input type="text" onkeypress='validate(event)' name="qty2" value="0"/>
<input type="button" onclick="bump(2,1)" value="+"/>
<input type="button" onclick="bump(2,-1)" value="-"/>
<input type="checkbox" name="cb2" value="20.00"
onClick="TotalCheckedValues()" />Service 2 (£20.00) <br />
Item <input type="text" onkeypress='validate(event)' name="qty3" value="0"/>
<input type="button" onclick="bump(3,1)" value="+"/>
<input type="button" onclick="bump(3,-1)" value="-"/>
<input type="checkbox" name="cb3" value="20.00"
onClick="TotalCheckedValues()" />Service 3 (£20.00) <br />
Item <input type="text" onkeypress='validate(event)' name="qty4" value="0"/>
<input type="button" onclick="bump(4,1)" value="+"/>
<input type="button" onclick="bump(4,-1)" value="-"/>
<input type="checkbox" name="cb4" value="10.00"
onClick="TotalCheckedValues()" />Service 4 (£10.00) <br />
Total: <input type="text" name="Total" readonly size="5" />
<input type="reset" name="reset" value="Clear Selected">
</form>
</body>
</html>
Upvotes: -1
Views: 341
Reputation: 1815
// Also going to be cleaning up the code a little - no offense, I'm just anal
// One more note: I'll be specifying types in my function documentation - but remember
// that JS doesn't really *do* types
/**
* Grab a quantity and increase it by a given value
* @param int which Number of the field to target (comes out as 'qty1/2/3/4/etc')
* @param int bywhat Number to increase the value found with 'which' by
*/
function bump(which, bywhat) {
// Find the form child named 'qtyn', where n is a number
// Notice only one var definition here - no need to define form if
// you can just get to your target element/attribute/etc.
var qty = document.items['qty' + which].value;
qty = Number(qty) + bywhat; // Add bywhat to the form value
TotalCheckedValues(); // in case user bumped an already checked line
}
/**
* Iterate through all check boxes (cb) on the form and multiply quantities (qty)
* against values on checked boxes.
*/
function TotalCheckedValues() {
// Some consider it best practice to put all vars in the top of the method,
// in a comma-separated list using one "var" keyword.
var form = document.items,
total = 0,
checkbox = null,
n = 1;
for(n; n <= 4; ++n)
{
checkbox = "cb"+n; // make your code easier to read
if(form[checkbox].checked) // if the checkbox of the item is ticked
{
// If the checkbox is checked, multiply it's value to that of each qty field
total += form[checkbox].value * form["qty"+n].value;
}
}
form.Total.value = total.toFixed(2); // Shorten 'total' to 2 decimal places
}
/**
* Test for a valid key
* @param event evt The key-related event
*/
function validate(evt) {
/*
* In javascript, the OR operator || is used as a way of setting defaults. So,
* keep trying values until one that's considered "true" is found:
* var something = false;
* var foo = null;
* var bar = 'abc';
* var which = something || foo || bar; // value of 'which' is 'abc'
*/
var theEvent = evt || window.event,
key = theEvent.keyCode || theEvent.which,
regex = /[0-9]|\./; // Regex that matches 0-9 and '.'
key = String.fromCharCode( key ); // Convert from key code to something usable
// I almost think you could do...
// var ... key = String.fromCharCode(theEvent.keyCode || theEvent.which)
// but I'm not sure.
// If our key event's code doesn't pass our regex test
if(!regex.test(key)) {
theEvent.returnValue = false;
if(theEvent.preventDefault)
theEvent.preventDefault();
}
}
Some Other Advice
Some other pointers I'd like to share, perhaps just some suggestions to consider:
Relying on hardcoded limits (the '4' in the for loop in TotalCheckedValues()) makes your code less reusable. Instead, you should iterate over all matching children to the parent node. With jQuery it'd be something like $('#MyFormId input[type="checkbox"]).each(...)
This makes the code flexible and doesn't need updating just because you added another checkbox.
Use an ID on your form element to make selecting more obvious - relying on document[name] is ok but may not play well everywhere.
which, bywhat, evt - Variable names are great because they can be anything, so keep that in mind when deciding what to call your variables. Descriptive names 1) help you remember what's happening when you come back to the code 2 months later and 2) help anyone else who has to go through your code, for whatever reason, to understand what is happening.
Consistency is key: Your function names are mixed in style: bumb vs TotalCheckedValues vs validate - you should pick one way for your code and stick to it.
Visit JSLint sometime if you really want something that will nitpick your code...and make you cry. But just reading the "How does JSLint work?" page about how and why they pick apart certain parts of your code can be valuable in learning Javascript and some of the Best Practices © for JS.
Upvotes: -1
Reputation: 10094
First, I'm not sure that's the kind of javascript from which you should learn... But, i'll try to give you some hints
There are 3 functions : validate
, bump
and TotalCheckedValues
Validate
is th easiest to understand. Note the call to this function in each onkeypress
attribute. Validate is called to verify if the key that has just been pressed to type into the input is a number between 0 and 9 (included) or a dot. (the regex checks that)
bump
has been made to record the clicks on the + and - buttons on each item (to keep track of the quantity). It relies on the call to the document.items
form that gives its items
which are named by ascending order and are identified by the number in their names (name="qty1"
for the first item). The function take as parameters the index of the item and the amount to increase or decrease its value (bump(3,1)
for the + button of the 3rd item which means : take the 3rd item and add 1 to its value ). The function ends with a call to the 3rd function
TotalCheckedValues
is there to recalculate the total amount (sum(quantity*price)
for each item if the checkbox is checked for this item ). This function retriver the items, iterate on these, check if the checkbox is checked and if so, take the price and the quantity, multiply them and add them to the total
Upvotes: 0