SAMPLE CODE FOR FORM VALIDATION
WITH JAVASCRIPT 1.2 REGULAR EXPRESSIONS

Form validation is one of the most common uses for JavaScript. JavaScript is a quick, easy way to check a user's input for mistakes, typos, and the omission of required fields. Because validation takes place on the client machine, there's no delay for contacting a remote server. The user gets quicker responses, and network bandwidth and server processing power are both conserved. Developers will find it easier and more intuitive to do form validation with JavaScript than with CGI scripts.

Until the release of JavaScript 1.2 in Netscape Communicator, developers writing client-side form validation in JavaScript had to write functions which iterated down the characters of a string, checking each character one at a time. Such code is simpler to write than the equivalent CGI scripts and has the advantage of running on any browser which supports JavaScript 1.0 or later. Developers who need to write JavaScript form validation code for use on any JavaScript-capable browser should see Netscape's sample code for form validation using JavaScript 1.0 or later.

To make it easier for developers to write scripts which sort, compare, split, or check strings, JavaScript 1.2 has added support for regular expressions. Developers who are writing JavaScript 1.2 form validation code for use on Netscape Navigator 4.x can write the code even more quickly by taking advantage of this new feature. (Since JavaScript 1.2 is supported on the server side as well in Enterprise Server 3.x, server-side developers can also use regular expressions.)

Regular expressions are a notation for describing sequences of characters. For example, the sequence of characters for a real number can be described in English as "zero or more digits, followed by a period, followed by one or more digits." The same sequence of characters can be described in regular expression notation as /\d*\.\d+/. The regular expression starts and ends with a forward slash; \d means "digit between zero and nine"; \. means "period"; * means "zero or more"; and + means "one or more."

The most popular and well-known notation for describing regular expressions in software is defined by the Perl scripting language. Perl has become popular because its support for regular expressions makes it easy to write scripts which process text files and change or sort their contents. Developers don't need to painstakingly write functions which examine strings one character at a time in loops; instead, they can write a regular expression which describes a sequence of characters and let the Perl interpreter compare the regular expression to the target string to see if they match.

To make it easy for developers to take advantage of this new functionality, JavaScript 1.2 supports the popular Perl syntax. Experienced Perl developers will find it easy to start using regular expressions in JavaScript, and developers new to regular expressions will be able to take advantage of the many tutorials already in existence on Perl and regular expressions. For a basic introduction to regular expressions and their use in JavaScript 1.2, read this View Source article on String Matching and Replacing in JavaScript 1.2.

This sample code assumes a basic knowledge of regular expressions and JavaScript 1.2 and demonstrates the use of JavaScript regular expressions to validate two forms. It includes all of the functions of the sample code for form validation using JavaScript 1.0 or later. Where appropriate, these functions have been rewritten to take advantage of JavaScript 1.2's support for regular expressions. As a result, the source code has been simplified and shortened.

There are six files in this sample:
 
File  Purpose 
USform.html  U.S.-specific address entry form which demonstrates rigid form validation. 
Intlform.html  International address entry form which demonstrates looser form validation. 
sampleccnums.html  List of sample credit card numbers to enter into forms. 
FormChek.js  Library of JavaScript functions for form validation written using JavaScript 1.2 regular expressions.. 
test.html  Test suite for confirming that functions in FormChek.js are working. 
overview.html  (this document) Summarizes purpose and contents of code sample. 

To use this sample code, first try using the USform.html and Intlform.html samples. See how the forms make sure that the user enters data into the required fields (marked with asterisks) and check the data the user enters into some fields (like phone numbers and credit cards).

Next, View Source on the forms to see the commented HTML source for the forms and methods like onChange which call functions to check the data.

Next, read the commented source code for FormChek.js to see the library of JavaScript functions which are used to validate the data. You can put this JavaScript file into your own applications and reuse the functions it contains.

If you decide to change the source code of FormChek.js, use the test suite test.html to make sure that its functions still work as expected after your changes.

The header of FormChek.js, included below, lists and briefly explains all of the functions provided by the library. For detailed information, see the comments for each function in the source.

HOW THE USE OF REGULAR EXPRESSIONS SHORTENS AND SIMPLIFIES CODE

To see how the use of regular expressions can shorten and simplify source code, compare the function isEmail implemented in JavaScript 1.0 without using regular expressions:

// function isEmail implemented without using regular expressions:
// total lines of code to examine string = 11

function isEmail (s)
{   if (isEmpty(s)) 
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);
   
    // is s whitespace?
    if (isWhitespace(s)) return false;
    
    // there must be >= 1 character before @, so we
    // start looking at character position 1 
    // (i.e. second character)
    var i = 1;
    var sLength = s.length;

    // look for @
    while ((i < sLength) && (s.charAt(i) != "@"))
    { i++
    }

    if ((i >= sLength) || (s.charAt(i) != "@")) return false;
    else i += 2;

    // look for .
    while ((i < sLength) && (s.charAt(i) != "."))
    { i++
    }

    // there must be at least one character after the .
    if ((i >= sLength - 1) || (s.charAt(i) != ".")) return false;
    else return true;
}
... to the same function isEmail implemented in JavaScript 1.2 using regular expressions:
var reEmail = /^.+\@.+\..+$/

// function isEmail implemented using regular expressions:
// total lines of code to examine string = 1, plus 1 above to define expression

function isEmail (s)

{   if (isEmpty(s)) 
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);
    
    else {
       return reEmail.test(s)
    }
}
The first three lines of both versions handle the case when the string is empty. After that, it requires 11 lines of code to examine the string in JavaScript 1.0 (the first example, which doesn't use regular expressions) but only 2 lines of code to examine the string in JavaScript 1.2 (the second example, which does use regular expressions).

For other examples of how using regular expressions simplified functions in this library, download the JavaScript 1.0 and JavaScript 1.2 versions of the library and compare functions isWhitespace, isLetter, isDigit, isLetterOrDigit, isInteger, isSignedInteger, isFloat, isSignedFloat, isAlphabetic, and isAlphanumeric. In each case, examining a string in JavaScript 1.2 requires only one line to define the regular expression and one line to call the regular expression method test. In JavaScript 1.0, much more code is required to examine a string character by character.

REGULAR EXPRESSIONS USED IN THIS EXAMPLE

This table lists the regular expressions which were used in this sample code, the data type each is intended to recognize, and some examples of strings that each regular expression accepts (matches) and rejects (does not match).
 
data type regular expression accepts rejects
whitespace /^\s+$/ spaces, tabs, etc. 0 a
single letter /^[a-zA-Z]$/ a A 0 . -
alphabetic string /^[a-zA-Z]+$/ aAbB a1 23
single digit /^\d/ 0 00 1a
single letter or digit /^([a-zA-Z]|\d)$/ 0 a 00 1a
alphanumeric string /^[a-zA-Z0-9]+$/ a1b2 2.5 1.a
integer /^\d+$/ 0 23 23.5
signed integer /^(+|-)?\d+$/ -1 +12 -1.1
floating point number /^((\d+(\.\d*)?)|((\d*\.)?\d+))$/ 1.1    .9     8. -1.1  .
signed float /^(((+|-)?\d+(\.\d*)?)|((+|-)?(\d*\.)?\d+))$/ -1.1   1.1  .9   8. 1a
email address /^.+\@.+\..+$/ a@b.c a@b
 

NAVIGATOR VERSIONS COMPATIBILITY NOTE

Because this sample code uses JavaScript 1.2's support for regular expressions, Netscape Navigator 4.x or later is required to use it.

HEADER OF SOURCE CODE FILE FormChek.js

// FormChek.js
//
// SUMMARY
//
// This is a set of JavaScript functions for validating input on 
// an HTML form.  Functions are provided to validate:
//
//      - U.S. and international phone/fax numbers
//      - U.S. ZIP codes (5 or 9 digit postal codes)
//      - U.S. Postal Codes (2 letter abbreviations for names of states)
//      - U.S. Social Security Numbers (abbreviated as SSNs)
//      - email addresses
//      - dates (entry of year, month, and day and validity of combined date)
//      - credit card numbers
//
// Supporting utility functions validate that:
//
//      - characters are Letter, Digit, or LetterOrDigit
//      - strings are a Signed, Positive, Negative, Nonpositive, or
//        Nonnegative integer
//      - strings are a Float or a SignedFloat
//      - strings are Alphabetic, Alphanumeric, or Whitespace
//      - strings contain an integer within a specified range
//
// Functions are also provided to interactively check the
// above kinds of data and prompt the user if they have
// been entered incorrectly.
//
// Other utility functions are provided to:
//
//      - remove from a string characters which are/are not 
//        in a "bag" of selected characters     
//      - reformat a string, adding delimiter characters
//      - strip whitespace/leading whitespace from a string
//      - reformat U.S. phone numbers, ZIP codes, and Social
//        Security numbers
//
//
// Many of the below functions take an optional parameter eok (for "emptyOK")
// which determines whether the empty string will return true or false.
// Default behavior is controlled by global variable defaultEmptyOK.
//
// BASIC DATA VALIDATION FUNCTIONS:
//
// isWhitespace (s)                    Check whether string s is empty or whitespace.
// isLetter (c)                        Check whether character c is an English letter 
// isDigit (c)                         Check whether character c is a digit 
// isLetterOrDigit (c)                 Check whether character c is a letter or digit.
// isInteger (s [,eok])                True if all characters in string s are numbers.
// isSignedInteger (s [,eok])          True if all characters in string s are numbers; leading + or - allowed.
// isPositiveInteger (s [,eok])        True if string s is an integer > 0.
// isNonnegativeInteger (s [,eok])     True if string s is an integer >= 0.
// isNegativeInteger (s [,eok])        True if s is an integer < 0.
// isNonpositiveInteger (s [,eok])     True if s is an integer <= 0.
// isFloat (s [,eok])                  True if string s is an unsigned floating point (real) number. (Integers also OK.)
// isSignedFloat (s [,eok])            True if string s is a floating point number; leading + or - allowed. (Integers also OK.)
// isAlphabetic (s [,eok])             True if string s is English letters 
// isAlphanumeric (s [,eok])           True if string s is English letters and numbers only.
// 
// isSSN (s [,eok])                    True if string s is a valid U.S. Social Security Number.
// isUSPhoneNumber (s [,eok])          True if string s is a valid U.S. Phone Number. 
// isInternationalPhoneNumber (s [,eok]) True if string s is a valid international phone number.
// isZIPCode (s [,eok])                True if string s is a valid U.S. ZIP code.
// isStateCode (s [,eok])              True if string s is a valid U.S. Postal Code
// isEmail (s [,eok])                  True if string s is a valid email address.
// isYear (s [,eok])                   True if string s is a valid Year number.
// isIntegerInRange (s, a, b [,eok])   True if string s is an integer between a and b, inclusive.
// isMonth (s [,eok])                  True if string s is a valid month between 1 and 12.
// isDay (s [,eok])                    True if string s is a valid day between 1 and 31.
// daysInFebruary (year)               Returns number of days in February of that year.
// isDate (year, month, day)           True if string arguments form a valid date.


// FUNCTIONS TO REFORMAT DATA:
//
// stripCharsInBag (s, bag)            Removes all characters in string bag from string s.
// stripCharsNotInBag (s, bag)         Removes all characters NOT in string bag from string s.
// stripWhitespace (s)                 Removes all whitespace characters from s.
// stripInitialWhitespace (s)          Removes initial (leading) whitespace characters from s.
// reformat (TARGETSTRING, STRING,     Function for inserting formatting characters or
//   INTEGER, STRING, INTEGER ... )       delimiters into TARGETSTRING.                                       
// reformatZIPCode (ZIPString)         If 9 digits, inserts separator hyphen.
// reformatSSN (SSN)                   Reformats as 123-45-6789.
// reformatUSPhone (USPhone)           Reformats as (123) 456-789.


// FUNCTIONS TO PROMPT USER:
//
// prompt (s)                          Display prompt string s in status bar.
// promptEntry (s)                     Display data entry prompt string s in status bar.
// warnEmpty (theField, s)             Notify user that required field theField is empty.
// warnInvalid (theField, s)           Notify user that contents of field theField are invalid.


// FUNCTIONS TO INTERACTIVELY CHECK FIELD CONTENTS:
//
// checkString (theField, s [,eok])    Check that theField.value is not empty or all whitespace.
// checkStateCode (theField)           Check that theField.value is a valid U.S. state code.
// checkZIPCode (theField [,eok])      Check that theField.value is a valid ZIP code.
// checkUSPhone (theField [,eok])      Check that theField.value is a valid US Phone.
// checkInternationalPhone (theField [,eok])  Check that theField.value is a valid International Phone.
// checkEmail (theField [,eok])        Check that theField.value is a valid Email.
// checkSSN (theField [,eok])          Check that theField.value is a valid SSN.
// checkYear (theField [,eok])         Check that theField.value is a valid Year.
// checkMonth (theField [,eok])        Check that theField.value is a valid Month.
// checkDay (theField [,eok])          Check that theField.value is a valid Day.
// checkDate (yearField, monthField, dayField, labelString, OKtoOmitDay)
//                                     Check that field values form a valid date.
// getRadioButtonValue (radio)         Get checked value from radio button.
// checkCreditCard (radio, theField)   Validate credit card info.


// CREDIT CARD DATA VALIDATION FUNCTIONS
// 
// isCreditCard (st)              True if credit card number passes the Luhn Mod-10 test.
// isVisa (cc)                    True if string cc is a valid VISA number.
// isMasterCard (cc)              True if string cc is a valid MasterCard number.
// isAmericanExpress (cc)         True if string cc is a valid American Express number.
// isDinersClub (cc)              True if string cc is a valid Diner's Club number.
// isCarteBlanche (cc)            True if string cc is a valid Carte Blanche number.
// isDiscover (cc)                True if string cc is a valid Discover card number.
// isEnRoute (cc)                 True if string cc is a valid enRoute card number.
// isJCB (cc)                     True if string cc is a valid JCB card number.
// isAnyCard (cc)                 True if string cc is a valid card number for any of the accepted types.
// isCardMatch (Type, Number)     True if Number is valid for credic card of type Type.
//
// Other stub functions are retained for backward compatibility with LivePayment code.
// See comments below for details.
//
// 18 Feb 97 created Eric Krock
// Original JavaScript 1.0-only version (works on Nav2.x and higher)
// available at http://developer.netscape.com/library/examples/javascript/formval/overview.html
// 
// 4 Nov 97 rewritten to demonstrate use of JavaScript 1.2 regular expressions.
// (code is simpler and shorter but works on Nav4.x and higher only)









Copyright © 1997 Netscape Communications Corporation