Automate Your Form Validation

Automate Your Form Validation

orm validation is a checking process that occurs between the time the user clicks the submit button and the actual submission of the form. In this article, you’ll see how to intercept the submission and pass the form data through one or more validation tests. If the data passes the tests (i.e. the validator returns true), the code formats the data and then submits the form. If the form data fails any validation test, users see a prompt asking them to complete the form correctly. Form validation involves string manipulation primarily, so a single script serves all three major browser types: Internet Explorer 4+, Netscape Navigator 4x, and Netscape 6.

The examples in this remainder of this article implement rules for common validation tasks. They break down naturally into five sections: the HTML form, the support functions, the validation rules, the formatting functions, and the validation routine.

Validating forms on the client lightens the load on the server and allows you to format data before it is sent for processing. Unfortunately, writing client-side validation scripts is a tedious and error-prone process. You can improve your development time and reduce errors by creating generic reusable validation scripts. The problem is: How can you write generic validation functions that work with different form content on the client?

The key to client-side validation is to intercept form submission and validate your data before submitting it for further processing. Because data validation is often a repetitive process, you can write generic validation and formatting rules as long as you send values to the validation functions rather than trying to reference named controls.Setting Up the Form
Open your editor of choice and construct the following form (see Figure 1):

Listing 1 contains the form code. Except for the JavaScript function to submit the form, it’s very straightforward HTML. Try it live here.

Non – Empty
US Phone
Zip Code
Credit Card Type
E Mail

Setting Up the Support Functions
When writing validation code, I find it helpful to include generic support functions that provide much of the grunt work. Since the purpose of the generic functions is to make them re-usable, include them in a separate file and reference them in your HTML page like this:

Then, add the following functions to the script file:

   // Support Functions   function strip(filter,str){      var i,curChar;      var retStr = ”;      var len = str.length;      for(i=0; i
Validating forms is much easier if you can eliminate extraneous characters and deal only with the significant input data. For example, when dealing with a phone number, you should be concerned with the numbers, not with the dashes and parentheses. The strip() function strips out garbage characters from strings based on the filter argument. It compares each character in the string argument with those in the filter. If the character in the string matches any of the characters in the filter, the character is discarded. If no match is made, the character is kept. The reformat() function lets you apply formatting rules to strings as needed. In essence, the function takes a string as the first argument and then a series of arguments in groups of three. In each group of three arguments, you must include a set of preceding characters, the number of characters to skip, and a set of following characters. The code wraps the formatting characters around the significant parts of the data.

For example, to wrap parentheses around the characters in a three-character string, you would write:

   stringValue = reformat(stringValue,”(“,3,”)”);
The key lies in knowing how many characters should be in the string you’re formatting.Write the Validation Rules
A validation script is only as good as the rules it contains. The remainder of this article lists validation functions for many common tasks. I present these functions as a starting point for you to build upon?they’re not intended to be finished products. Many of them are relatively complete but some?noticeably the credit card rule?are not as robust as you might need for a production application. Also, the functions contain no built-in security; you’ll need to implement security yourself.

The first three functions are relatively self-explanatory. The notEmpty() function accepts any value other than white space. The validateInteger() and validateFloat() functions ensure that the controls only accept numeric values by first parsing the string and then checking whether the result is numeric with the isNaN() method.

   //Validation Rules   function notEmpty(str){      if(strip(” 

“,str).length ==0) return false; else return true; } function validateInteger(str){ str = strip(‘

‘,str); //remove leading zeros, if any while(str.length > 1 && str.substring(0,1) == ‘0’){ str = str.substring(1,str.length); } var val = parseInt(str); if(isNaN(val)) return false; else return true; } function validateFloat(str){ str = strip(‘

‘,str); //remove leading zeros, if any while(str.length > 1 && str.substring(0,1) == ‘0’){ str = str.substring(1,str.length); } var val = parseFloat(str); if(isNaN(val)) return false; else return true; }

The validateUSPhone(), validateSSN(), and validateZip() functions are similar in that they strip off all of the characters that people commonly enter for phone numbers. The functions then check the length of the resulting numeric character string. In addition, because Social Security numbers and Zip Codes are numeric, the validateSSN() and validateZip() functions also ensure that the entered data is a valid integer. Note that the validateUSPhone() function doesn’t force phone numbers to be integers so that phone numbers represented by characters are passed through.

   function validateUSPhone(str){      str = strip(“*() -./_

\”,str); if(str.length == 10 || str.length == 7) return true; else return false; } function validateSSN(str){ str = strip(” -.

“,str); if(validateInteger(str) && str.length == 9) return true; else return false; } function validateZip(str){ str = strip(“-

“,str); if(validateInteger(str) && (str.length==9 || str.length==5)) return true; else return false; }

The credit card validation rule deserves a bit more attention. After stripping out garbage characters, I took advantage of the fact that all Visa card account numbers begin with a 4, all MasterCard accounts begin with a 5, all Discover card accounts begin with a 6, and all American Express cards begin with a 3. I got the card type from the drop-down list next to the credit card entry text field. If the first character isn’t correct based on the type, the validateCC() function immediately returns false and the data fails the test. In addition, credit cards have a fixed number of digits: Amex accounts all contain 15 digits, and Visa, MasterCard, and Discover card accounts all contain 16 digits. Therefore, the function improves the validation by checking that the data begins with the correct number and is the correct length.

   function validateCC(str,type){      str = strip(“-./_

\”,str); if(type==”1″) if(str.charAt(0)!=”4″) return false; if(type==”2″) if(str.charAt(0)!=”5″) return false; if(type==”3″) if(str.charAt(0)!=”6″) return false; if(type==”4″) if(str.charAt(0)!=”3″) return false; if(validateInteger(str) && ((str.length==15&&type==”4″) || str.length==16)) return true; else return false; }

The validateDate() function first creates a Date object from the string. It then checks whether the valueOf() method of the Date object is numeric or non-zero. If the valueOf() method is non-numeric or zero, the string passed to the function does not represent a valid instance in time and, therefore, fails the test.

      function validateDate(str){      var dateVar = new Date(str);      if(isNaN(dateVar.valueOf()) ||          (dateVar.valueOf() ==0))         return false;      else         return true;   }   
The validateEMail() function strips out unwanted characters and then checks for the presence of both the “@” and “.” characters. While it is possible to fool the rule, you’d be surprised at how many people will first attempt to avoid entering a valid e-mail address and then, after prompting, simply supply their e-mail address.

   function validateEMail(str){      str = strip(” 

“,str); if(str.indexOf(“@”) > -1 && str.indexOf(“.”) > -1) return true; else return false; } //End Validation Rules

Write the Formatting Functions
When writing validation scripts, you must keep in mind that you are gathering information from your users. At some point, you will want to save the data to persistent storage so that you can make use of it later. Often, that persistent storage is a database. You can lighten the load on your database by formatting the data before sending it. In this example, I’m simply redisplaying the formatted data in the appropriate fields. After formatting the data and storing it in the form field, it is the formatted data that is passed to the data store, not the user-entered data visible on screen. Include the following code for formatting data:

   //Formatting functions   function formatPhone(str){      str = strip(“*() -./_

\”,str); if(str.length==10) return reformat(str,”(“,3,”) “,3,”-“,4); if(str.length==7) return reformat(str,””,3,”-“,4); } function formatSSN(str){ str = strip(” -.

“,str); return reformat(str,””,3,”-“,2,”-“,4); } function formatZip(str){ str = strip(“-

“,str); if(str.length==5) return str; if(str.length==9) return reformat(str,””,5,”-“,4); } function formatCC(str,type){ str = strip(“-./_

\”,str); switch(type){ case “1”: return reformat(str,””,4,”-“,4,”-“,4,”-“,4); break; case “2”: return reformat(str,””,4,”-“,4,”-“,4,”-“,4); break; case “3”: return reformat(str,””,4,”-“,4,”-“,4,”-“,4); break; case “4”: return reformat(str,””,4,”-“,6,”-“,5); } } function formatDate(str,style){ var dateVar = new Date(str); var year = dateVar.getYear(); if(year

The formatting functions all follow the same pattern: strip out the unnecessary characters and replace the data with data that has been properly formatted through the reformat() function. The only code to take note of is in the formatDate() function where I had to make allowances for dates that are entered as two digits. The workaround first checks for a number less than 10 and, if encountered, adds 2000 to it. It then adds 1900 to any number less than 100. It works now but will not work after 2010?a kludge but it works, for now.Write the Validation Routine
Up to this point, all the code you’ve seen has been generic, but the validator() validation routine below is dependent on the controls in the form. You’ll need to write a custom version of this function for each form you want to validate. Call the validator() function from the form’s onSubmit event. If the data passes the test, reformat it if necessary, and then submit the form. In the example, I’ve set the action attribute to “javascript:void(0)” which means “do nothing,” In other words, the example form never submits. Instead, I’ll replace the on-screen fields with the formatted values. You should change that the action attribute so the form submits the validated and formatted data to your server.

Add the following code to your page:

   //Form Validator   function validator(form){      if(notEmpty(form.txtNonEmpty.value)==false){         alert(“Field is required.”);         form.txtNonEmpty.focus();         return false;      }      if(validateInteger(form.txtInteger.value)==false){         alert(“Enter an integer.”);         form.txtInteger.focus();         return false;      }      if(validateFloat(form.txtFloat.value)==false){         alert(“Enter a decimal.”);         form.txtFloat.focus();         return false;      }      if(validateUSPhone(form.txtPhone.value)==false){         alert(“Enter a valid phone number.”);         form.txtPhone.focus();         return false;      }      form.txtPhone.value =         formatPhone(form.txtPhone.value);      if(validateSSN(form.txtSSN.value)==false){         alert(“Enter a valid social security number.”);         form.txtSSN.focus();         return false;      }      form.txtSSN.value = formatSSN(form.txtSSN.value);      if(validateZip(form.txtZip.value)==false){         alert(“Enter a valid zip code.”);         form.txtZip.focus();         return false;      }      form.txtZip.value = formatZip(form.txtZip.value);      if(validateCC       (form.txtCC.value,form.txtCCType.options        [form.txtCCType.selectedIndex].value)==false){         alert(“Enter a valid credit card.”);         form.txtCC.focus();         return false;      }      form.txtCC.value = formatCC        (form.txtCC.value,form.txtCCType.options        [form.txtCCType.selectedIndex].value);      if(validateDate(form.txtDate.value)==false){         alert(“Enter a valid date.”);         form.txtDate.focus();         return false;      }      form.txtDate.value =         formatDate(form.txtDate.value,”MM/DD/YY”);      if(validateEMail(form.txtEMail.value)==false){         alert(“Enter a valid E Mail address.”);         form.txtEMail.focus();         return false;      }      form.txtEMail.value =         strip(” 

“,form.txtEMail.value); }

That’s it! Each conditional block validates the text entered into one of the form’s fields. If the entry passes the test, the validator routine reformats the data and replaces the user-entered text in the control with the formatted data. If any test fails, the routine halts the submission process, and displays an appropriate error message. Finally, for user convenience, the routine sets the focus to the offending control.

I hope this example sets you off in the right direction when validating data. It includes validation rules for many common tasks. If you take away one thing from this example, make sure that you understand that your validation scripts are only as good as the rules you create.


Share the Post: