JavaScript

An Introduction (cont.)


 

 

Part VI: Form Validation

1. Next is an example of a form that uses JavaScript to calculate totals. You'll use this to add validation, which let's you check the submissions before they are sent off to a CGI script.

Below is the entire script, without validation (copy and paste this "as is" into a text editor):

<HTML>
<HEAD><TITLE>Order Form</TITLE>
<SCRIPT>
// function to calculate the total cost field
function Total() {
  var tot = 0
  tot += (40.00 * document.order.qty1.value);
  tot += (69.95 * document.order.qty2.value);
  tot += (99.95 * document.order.qty3.value);
  tot += (4.95 * document.order.qty4.value);
  document.order.totalcost.value = tot;
}

// function to update cost when quantity is changed
function UpdateCost(number, unitcost) {
  costname = "cost" + number;
  qtyname = "qty" + number;
  var q = document.order[qtyname].value;
  document.order[costname].value = q * unitcost;
  Total();
}

</SCRIPT>
</HEAD>
<BODY>
<H1>Order Form</H1>
<FORM NAME="order">
<B>Name:</B><INPUT TYPE="text" NAME="name1" SIZE=20>
<B>Phone:</B><INPUT TYPE="text" NAME="phone" SIZE=15>
<B>Email:</B><INPUT TYPE="text" NAME="email" SIZE=20><BR>
<B>Shipping Address:</B><BR>
<TEXTAREA NAME="billto" COLS=40 ROWS=4></TEXTAREA>
<B>Products to Order:</B><BR>
QTY: <INPUT TYPE="text" NAME="qty1" VALUE="0" SIZE=4 
onChange = "UpdateCost(1, 40.00);">
Cost: <INPUT TYPE="text" NAME="cost1" VALUE="0" SIZE=6>
($40.00 ea) Fictional Spreadsheet 7.0<BR>
QTY: <INPUT TYPE="text" NAME="qty2" VALUE="0" SIZE=4 
onChange = "UpdateCost(2, 69.95);">
Cost: <INPUT TYPE="text" NAME="cost2" VALUE="0" SIZE=6>
($69.95 ea) Fictional Word Processor 6.0<BR>
QTY: <INPUT TYPE="text" NAME="qty3" VALUE="0" SIZE=4 
onChange = "UpdateCost(3, 99.95);">
Cost: <INPUT TYPE="text" NAME="cost3" VALUE="0" SIZE=6>
($99.95 ea) Fictional Database 7.0<BR>
QTY: <INPUT TYPE="text" NAME="qty4" VALUE="0" SIZE=4 
onChange = "UpdateCost(4, 4.95);">
Cost: <INPUT TYPE="text" NAME="cost4" VALUE="0" SIZE=6>
($4.95 ea) Instructional Booklet<HR>
<B> Total Cost:</B>
<INPUT TYPE="text" NAME="totalcost" SIZE=8><HR>
<INPUT TYPE="submit" NAME="submit" VALUE="Send Your Order">
<INPUT TYPE="reset" VALUE="Start Over">
</FORM>
</BODY>
</HTML>

 

It includes a Total function to add up the submissions and an UpdateCost function to calculate the total cost whenever a number is changed in the qty text boxes. Notice the onChange event handlers in the body of the page.

2. To add the validation, you will first determine what should be validated. You should remember that validation can only do so much, that it really only saves you trouble before you pass on variables to a CGI script. For instance, in this example you'll check that the submission to:

 

3. First you'll create two functions to handle the checking of lengths and then email. To check the length, you'll use this function:

// function to validate the length of an item
function ValidLength(item, len) {
     return (item.length >= len);
}

This takes the name of an item and the length you require and checks to see if the length is greater or equal to the len . Using the return statement will return a value of true or false for the function ValidLength.

// function to validate an email address
function ValidEmail(item) {
     if (!ValidLength(item,5)) return false;
     if (item.indexOf ('@') == -1) return false;
     return true;
}

This function does two things. First, it uses the previous function to check if the submission in the email text box is greater or equal to a length of five. The ! before the function call means "not". So the line literally reads "if the length of the item is not at least five characters, then this ValidLength function is false." Then it uses the indexOf() method (part of the built-in String object) to find the index value of the character @ in the item. If it can't find this character, the value will equal -1 and ValidEmail is again false.

 

4. Now you can create a larger function to handle all the three validations, using the previous two functions:

// global variable to catch errors
var errfound = false;

// main Validate function
function Validate() {
  errfound = false;
  if (!ValidLength(document.order.name1.value,6))
    error(document.order.name1,"Yah, try that name again.");
  if (!ValidEmail(document.order.email.value))
    error(document.order.email, "Try a real email address.");
  if (document.order.totalcost.value == "")
    error(document.order.qty1, "Come on, moneybags - buy something!");
  return !errfound;
  //  true if there are no errors
}

The function includes all three checks for the correct submission. If any of the conditionals are "not" valid, then the error function runs. Here's how it is defined:

function error(elem, text) {
// abort if we already found an error
  if (errfound) return;
  window.alert(text);
  elem.select();
  elem.focus();
  errfound = true;  
}

In error, you'll first check to see if the variable is actually true; if so, the script leaves the function. Otherwise an alert window will pop up with the text specified displayed inside. Next, the script uses the select() method of the built-in document object to select all the text inside the elem variable, and then puts your cursor inside of the text box with the focus()method. This is very powerful, allowing you to control for the user where they are supposed to look for the validation and dropping their cursor right inside for them to edit the text.

 

5. The last thing is to redo the FORM tag to run the Validate function when submitted:

<FORM NAME="order" onSubmit="return Validate();">

The way this is written, the Validate function is called and if it returns a false value (if something is invalid) the data doesn't get submitted to the CGI.

 

6. Here's the entire script, with the added portions in red:

<HTML>
<HEAD><TITLE>Order Form</TITLE>
<SCRIPT>
// function to calculate the total cost field
function Total() {
  var tot = 0
  tot += (40.00 * document.order.qty1.value);
  tot += (69.95 * document.order.qty2.value);
  tot += (99.95 * document.order.qty3.value);
  tot += (4.95 * document.order.qty4.value);
  document.order.totalcost.value = tot;
}

// function to update cost when quantity is changed
function UpdateCost(number, unitcost) {
  costname = "cost" + number;
  qtyname = "qty" + number;
  var q = document.order[qtyname].value;
  document.order[costname].value = q * unitcost;
  Total();
}
// function to validate the length of an item
function ValidLength(item, len) {
     return (item.length >= len);
}
// function to validate an email address
function ValidEmail(item) {
     if (!ValidLength(item,5)) return false;
     if (item.indexOf ('@') == -1) return false;
     return true;
}
// global variable to catch errors
var errfound = false;

// main Validate function
function Validate() {
  errfound = false;
  if (!ValidLength(document.order.name1.value,6))
    error(document.order.name1,"Yah, try that name again.");
  if (!ValidEmail(document.order.email.value))
    error(document.order.email, "Try a real email address.");
  if (document.order.totalcost.value == "")
    error(document.order.qty1, "Come on, moneybags - buy something!");
  return !errfound;
  //  true if there are no errors
}

function error(elem, text) {
// abort if we already found an error
  if (errfound) return;
  window.alert(text);
  elem.select();
  elem.focus();
  errfound = true;  
}

</SCRIPT>
</HEAD>
<BODY>
<H1>Order Form</H1>
<FORM NAME="order" onSubmit="return Validate();">
<B>Name:</B><INPUT TYPE="text" NAME="name1" SIZE=20>
<B>Phone:</B><INPUT TYPE="text" NAME="phone" SIZE=15>
<B>Email:</B><INPUT TYPE="text" NAME="email" SIZE=20><P>
<B>Shipping Address:</B><BR>
<TEXTAREA NAME="billto" COLS=40 ROWS=4></TEXTAREA><P>
<B>Products to Order:</B><BR>
QTY: <INPUT TYPE="text" NAME="qty1" VALUE="0" SIZE=4 
onChange = "UpdateCost(1, 40.00);">
Cost: <INPUT TYPE="text" NAME="cost1" VALUE="0" SIZE=6>
($40.00 ea) Fictional Spreadsheet 7.0<BR>
QTY: <INPUT TYPE="text" NAME="qty2" VALUE="0" SIZE=4 
onChange = "UpdateCost(2, 69.95);">
Cost: <INPUT TYPE="text" NAME="cost2" VALUE="0" SIZE=6>
($69.95 ea) Fictional Word Processor 6.0<BR>
QTY: <INPUT TYPE="text" NAME="qty3" VALUE="0" SIZE=4 
onChange = "UpdateCost(3, 99.95);">
Cost: <INPUT TYPE="text" NAME="cost3" VALUE="0" SIZE=6>
($99.95 ea) Fictional Database 7.0<BR>
QTY: <INPUT TYPE="text" NAME="qty4" VALUE="0" SIZE=4 
onChange = "UpdateCost(4, 4.95);">
Cost: <INPUT TYPE="text" NAME="cost4" VALUE="0" SIZE=6>
($4.95 ea) Instructional Booklet<HR>
<B> Total Cost:</B>
<INPUT TYPE="text" NAME="totalcost" SIZE=8><HR>
<INPUT TYPE="submit" NAME="submit" VALUE="Send Your Order">
<INPUT TYPE="reset" VALUE="Start Over">
</FORM>
</BODY>
</HTML>

7. To test this script, try load the page and without typing anything into a text box, hit the submit button. You should be lead sequentially through the validation process.