Using Client-Side Validation


The biggest drawback in using server-side validation is that the validation occurs after form submission. This means that if any validation rules fail, the user must go back to the form, make the corrections, and resubmit it to the server. To make matters worse, some browsers lose the data in the form fields when the Back button is clicked, forcing the user to reenter all the data.

Obviously, this hardly creates a user-friendly interface. Too many good Web sites have lost visitors because their forms were aggravating to work with.

Fortunately, an alternative is available: client-side validation.

Understanding Client-Side Validation

To perform client-side validation, you add a series of browser instructions to your Web page. The browser interprets these instructions and executes them right on the user's computer (i.e., on the client side) before the form ever gets submitted to the server.

These instructions are written in scripting languages, such as JavaScript (supported by almost all browsers) or VBScript (based on Visual Basic and supported by Microsoft Internet Explorer only). These are interpreted languages that enable you to control browser behavior.

NOTE

Don't confuse JavaScript with Java. Java is a true compiled object-oriented application development language, one that can be used to write entire programs. JavaScript (including JScript, which is a variant of JavaScript) is an interpreted language designed to control Web browsers. Unlike Java, JavaScript can't access anything on your computer other than your Web browser.


To validate a form, you write a script that will trap the form submission and allow it to proceed only if a series of validation checks have passed. If any checks fail, you would display an error message and prevent the form from being submitted.

Of course, to do this, you'd have to learn JavaScript (or VBScript).

Client-Side Validation Via <cfform>

You've already seen how ColdFusion can dramatically simplify server-side validation by automatically generating code for you. Well, it can do the same for client-side validation, generating the JavaScript needed to validate form fields. And the best part is that you already know the tags you need to make this work, they are <cfform> and <cfinput>.

Listing 13.5 contains login3.cfm, a slightly modified version of login2.cfm. Make that very slightly modified. Can you even see the change?

Listing 13.5. login3.cfmClient-Side Validation Rules
 <!--- Name:        login3.cfm Author:      Ben Forta (ben@forta.com) Description: Form field validation demo Created:     12/21/04 ---> <html> <head>   <title>Orange Whip Studios - Intranet</title> </head> <body> <!--- Page header ---> <cfinclude template="header.cfm"> <!--- Login form ---> <cfform action="process2.cfm"> <table align="center" bgcolor="orange">   <tr>     <td align="right">       ID:     </td>     <td>       <cfinput type="text"                name="LoginID"                maxlength="5"                required="yes"                message="A valid numeric ID is required!"                validate="integer"                validateAt="onSubmit">     </td>   </tr>   <tr>     <td align="right">       Password:     </td>     <td>       <cfinput type="password"                name="LoginPassword"                maxlength="20"                required="yes"                message="Password is required!"                validateAt="onSubmit">     </td>   </tr>   <tr>     <td colspan="2" align="center">       <cfinput type="submit"                name="submit"                value="Login">     </td>  </tr> </table> </cfform> </body> </html> 

Listings 13.4 and 13.5 are almost identical. The only change is the validateAt attribute in the two <cfinput> tags which has been changed from:

 validateAt="onServer" 

to

 validateAt="onSubmit" 

onServer tells ColdFusion to generate validation code that will be processed on the server (as seen previously). onSubmit tells ColdFusion to generate code that will be processed by the browser when the form is about to be submitted. validateAt="onSubmit" generates JavaScript code which it embeds into your form (in the much the same was as it embedded hidden form fields for server-side validation).

Run login3.cfm, the form should look exactly as it did before. But now if you generate an error you'll see a pop-up window right in your browser, as seen in Figure 13.5.

Figure 13.5. Client-side validation error messages are displayed in a browser pop-up box.


Using client-side validation, the form was never submitted, because it failed the validation test. onSubmit validation essentially traps the form submission, and only allows it to continue if it passes all validation tests. This is obviously a far friendlier user experience, if users see a pop-up message like the one in Figure 13.5 they will be able to make corrections and resubmit the form.

NOTE

The pop-up error box is a standard browser dialog box that varies from browser to browser, and there is no way to change what it looks like. The only thing you can change are the actual error messages themselves.


It is worth noting that a lot is going on under the hood to make all this work, and ColdFusion has successfully shielded you from it. But do a View Source and you'll see that the generated code has gotten quite lengthy and complex:

 <html> <head>   <title>Orange Whip Studios - Intranet</title> <script type="text/javascript" src="/books/2/448/1/html/2//CFIDE/scripts/cfform.js"> </script> <script type="text/javascript" src="/books/2/448/1/html/2//CFIDE/scripts/masks.js"> </script> <script type="text/javascript"> <!--     function  _CF_checkCFForm_1(_CF_this)     {         //reset on submit         _CF_error_exists = false;         _CF_error_messages = new Array();         _CF_error_fields = new Object();         _CF_FirstErrorField = null;         //form element LoginID required check         if( _CF_hasValue(_CF_this['LoginID'], "TEXT", false ) )         {             //form element LoginID 'INTEGER' validation checks             if (!_CF_checkinteger(_CF_this['LoginID'].value, true))             {                 _CF_onError(_CF_this, "LoginID",                  _CF_this['LoginID'].value,                  "A valid numeric ID is required!");                 _CF_error_exists = true;             }         }else {             _CF_onError(_CF_this, "LoginID",              _CF_this['LoginID'].value,              "A valid numeric ID is required!");             _CF_error_exists = true;         }         //form element LoginPassword required check         if( !_CF_hasValue(_CF_this['LoginPassword'],             "PASSWORD", false ) )         {             _CF_onError(_CF_this, "LoginPassword",             _CF_this['LoginPassword'].value,             "Password is required!");             _CF_error_exists = true;         }         //display error messages and return success         if( _CF_error_exists )         {             if( _CF_error_messages.length > 0 )             {                 // show alert() message                 _CF_onErrorAlert(_CF_error_messages);                 // set focus to first form error,                 // if the field supports js focus().                 if( _CF_this[_CF_FirstErrorField].type == "text" )                 { _CF_this[_CF_FirstErrorField].focus(); }             }             return false;         }else {             return true;         }     } //--> </script> </head> <body> <table align="center">  <tr> <td> <img src="/books/2/448/1/html/2/../images/logo_c.gif" alt="Orange Whip Studios"> </td> <td align="center"> <font size="+2">Orange Whip Studios<br>Movies</font> </td>  </tr> </table> <form name="CFForm_1" action="process2.cfm"       method="post" onsubmit="return _CF_checkCFForm_1(this)"> <table align="center" bgcolor="orange">   <tr>     <td align="right">       ID:     </td>     <td>       <input name="LoginID"               type="text" maxlength="5"  />     </td>   </tr>   <tr>     <td align="right">       Password:     </td>     <td>       <input name="LoginPassword"               type="password" maxlength="20"  />     </td>   </tr>   <tr>     <td colspan="2" align="center">       <input name="submit"               type="submit" value="Login" />     </td>  </tr> </table> </form> </body> </html> 

That's a lot of code, and most of it is the JavaScript needed to validate form fields.

So what can client-side validation check for? The exact same checks that server-side validation does. Use required="yes" to make a form field required, and use validate= specifying any of the types listed in Table 13.2 previously. The exact same validation options are supported by both server-side and client-side validation, all you have to do is decide which you want and specify validateAt="onServer" or validateAt="onSubmit".

NOTE

There is actually a third option supported by validateAt. To force client-side validation as soon as the user leaves the form field (either by clicking on another field or by tabbing between fields) specify validateAt="onBlur". But use this option sparingly, as this type of validation can annoy your users.


TIP

If validateAt is not specified, the default of validateAt="onSubmit" will be used.


One of the validation types warrants special mention. validate="range" checks that a number is within a specified range, which means that you must provide the range of allowed values. This is done using the range attribute, as follows:

 <cfinput type="text"          name="age"          validate="range"          range="1,100"> 

This code snippet will allow numbers from 1 to 100. You may also specify just a minimum (and no maximum) by only providing one number in the range, as follows:

 <cfinput type="text"          name="age"          validate="range"          range="18"> 

This code will only allow 18 or higher. To specify a maximum but no minimum, just provide the second number, like this:

 <cfinput type="text"          name="age"          validate="range"          range=",17"> 

This code will only allow 17 or lower.

NOTE

The actual JavaScript validation code is in a file named cfform.js in the cfide/scripts directory beneath the Web root. This file is included dynamically using a <script> tag whenever any validation is used.


Extending <cfinput> Validation Options

You can't add your own validation types to <cfinput>, but you can extend the validation by providing regular expressions. A regular expression is a search pattern used to match strings. Full coverage of regular expressions is beyond the scope of this book, but here is an example to help explain the concept.

NOTE

Interested in learning more about Regular Expressions? You may want to get a copy of Sams Teach Yourself Regular Expressions in 10 Minutes (Sams, ISBN 0672325667).


Colors used in Web pages are often specified as RGB values (colors specified in amounts of red, green and blue). RGB values are six characters longthree sets of two hexadecimal values (00 to FF). To obtain a set of RGB values in a form you could use three <cfinput> tags like this:

 Red: <cfinput type="text"          name="color_r"          validate="regex"          pattern="[A-Fa-f0-9]{2,}"          message="RGB value must be 00-FF"          size="2"          maxlength="2"> <br> Green: <cfinput type="text"          name="color_g"          validate="regex"          pattern="[A-Fa-f0-9]{2,}"          message="RGB value must be 00-FF"          size="2"          maxlength="2"> <br> Blue: <cfinput type="text"          name="color_b"          validate="regex"          pattern="[A-Fa-f0-9]{2,}"          message="RGB value must be 00-FF"          size="2"          maxlength="2"> <br> 

validate="regex" specifies that regular expressions are to be used for validation. The regular expression itself is passed to the pattern attribute. [A-Fa-f0-9] matches a single character of A tHRough F (upper or lower case) or 0 through 9. The {2,} instructs the browser to only accept a minimum of 2 instances of the previous expression. That coupled with maxlength="2" provides the exact validation rule needed to accept RGB values.

As you can see, with minimal work you can write Regular Expressions to validate all sorts of things.

Specifying An Input Mask

We're not quite done yet. Client-side validation provides users with a far better experience that does server-side validation. But let's take this one step further.

All the validation thus far checks for errors after a user inputs data into a form field. Which begs the question, why let users type incorrect data into form fields in the first place? If a form field requires specific data, like LoginID in the forms above which required a numeric ID, let's prevent the user from typing anything else.

As simple as that suggestion sounds, controlling user input at that level is rather complex, and requires some very sophisticated scripting. Fortunately, you don't have to write that validation code either. The <cfinput> tag supports an additional attribute named mask that accepts an input filter mask. A filter is a string made up of characters that identify what is allowed for each character entered. For example, 9 is used to allow only digits (0 through 9). So the following mask would only allow two digits and nothing else:

 mask="99" 

Table 13.3 lists the mask characters supported by <cfinput mask=>.

Table 13.3. Supported Mask Characters

CHARACTER

ALLOWS

A

A through Z (upper- or lowercase)

9

Any digit

X

A through Z (upper- or lowercase) and any digit

?

Any character

 

Any other character inserts that actual character into the input text


So, for a U.S. ZIP code you could use the following mask:

 mask="99999-9999" 

And this mask could work for Canadian postal codes:

 mask="A9A 9A9" 

And to mask a U.S. Social Security number you could use:

 mask="999-99-9999" 

Of course, masking and validation may be combined, as seen in Listing 13.6, an update to our login page.

Listing 13.6. login4.cfmLogin Screen With Client-Side Validation Rules And Masking
 <!--- Name:        login4.cfm Author:      Ben Forta (ben@forta.com) Description: Form field validation demo Created:     12/21/04 ---> <html> <head>   <title>Orange Whip Studios - Intranet</title> </head> <body> <!--- Page header ---> <cfinclude template="header.cfm"> <!--- Login form ---> <cfform action="process2.cfm"> <table align="center" bgcolor="orange">   <tr>     <td align="right">       ID:     </td>     <td>       <cfinput type="text"                name="LoginID"                maxlength="5"                required="yes"                mask="99999"                message="A valid numeric ID is required!"                validate="integer"                validateAt="onSubmit">     </td>   </tr>   <tr>     <td align="right">       Password:     </td>     <td>       <cfinput type="password"                name="LoginPassword"                maxlength="20"                required="yes"                message="Password is required!"                validateAt="onSubmit">     </td>   </tr>   <tr>     <td colspan="2" align="center">       <cfinput type="submit"                name="submit"                value="Login">     </td>  </tr> </table> </cfform> </body> </html> 

Run this new login form. It will look just like the previous login screens, but see what happens when you try to type an alphabetical character into the LoginID field. And all it took was one more <cfinput> attribute.

Validating On The Server And Client

You've seen <cfinput> used to validate on the server and on the client. So far we used one or the other, but it need not be an either/or proposition. In fact, <cfinput> supports the use of multiple validation types at once. All you need to do is specify the types delimited by commas.

So, to validate the UserID field using masks, client-side validation, and server-side validation, you could do the following:

 <cfinput type="text"          name="LoginID"          maxlength="5"          required="yes"          mask="99999"          message="A valid numeric ID is required!"          validate="integer"          validateAt="onSubmit,onServer"> 

Preventing Multiple Form Submissions

I want to share one last <cfinput> goodie with you. All Web application developers face the problem of dealing with multiple form submissions. For example, a user fills in a form, clicks the submit button, and then gets impatient and submits it again and again and again.

If your form was a front end to database searches, this would result in multiple searches being performed. And while this won't negatively impact your data, it will definitely slow the application. This becomes an even bigger issue when forms are used to insert data into database tables (as will be seen in the next chapter). Multiple form submissions then are a real problem, as users could inadvertently insert multiple rows to your table.

Once again, <cfinput> comes to the rescue with a special validate option that only applies to form buttons. validate="SubmitOnce" generates JavaScript code that prevents multiple form submissions.

For example, to not allow our login form to be submitted multiple times, the button could be changed to:

 <cfinput type="submit"          name="submit"          value="Login"          validate="SubmitOnce"> 

Clean and simple, thanks to <cfinput>.



Macromedia Coldfusion MX 7 Web Application Construction Kit
Macromedia Coldfusion MX 7 Web Application Construction Kit
ISBN: 321223675
EAN: N/A
Year: 2006
Pages: 282

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net