Creative Juices Bo. Co.

Satisfy Your Thirst For Something Refreshing!

CJ FormFieldinator 1.1

Smarter form field filtering, formating and validating with Javascript.

Project Description

FormFieldinator is a collection of JavaScript functions to help you filter, validate and format HTML form input fields. You can perform text input masking, format phone numbers, validate e-mail address and much more. It was created to be fairly easy to incorporate and modify. The functions are broken up into three main categories:

  1. Filtering: Filter what the user can type into a field.
  2. Validating: Validate what the user typed into a field.
  3. Formating: Format the field once a user is done typing into a field.

Filtering

Filtering is used when you want to prevent someone from entering a certain character or characters into a form field. Let's say that you have an e-mail field. It's fairly common knowledge that some characters aren't permitted . So we prevent the user from typing these in. We also want to make sure that they can use the standard editing commands like copy, cut, paste and select all. I've also added filters for alpha, numeric and alpha/numeric characters. You also can pass the function your own characters to bypass the standard set.

Out of all the functions, this one is going to be the most problematic for most people. It's not my fault, honest! The problems stem from what I like to call "browser-interoperability". It's been what, like 100 years since the web browser was invented and these stupid browser manufacturers can't agree on something as simple as how to standardize a key being pressed in the browser window.

Here's the problem. Some browsers like our beloved onKeyPress event. Whilst others prefer onKeyDown. But the fun doesn't stop there, because not only do they handle these events differently, handle any modifier keys differently (Like the SHIFT, ALT, TAB keys), they also produce different results!!! Yea for us web developers. Anyway, this is a pretty good hack and it should fail gracefully. Take a gander to learn more.

The Function

function doFieldFilter(e, type, xtra, strict) {
   var re,
   rex = "";

   // Try to grab the keycode for the event
   var key = (e.which) ? e.which: (e.keyCode) ? e.keyCode: (window.event.keyCode) ? window.event.keyCode: "undefined";

   // Do we have a KeyCode event to play with?
   if (key && key !== "undefined") {

      // Grab the character from the keycode to perform our check (This is not 100% accurate on all browsers)
      var chr = String.fromCharCode(e.charCode ? e.charCode: (key) ? key: 0);

      // List of standard edit keys for IE, Safari, Gecko and Opera browsers
      // Here's the order: NULL, undo, cut, copy, paste, select all, tab, delete, backspace, return/enter, (Safari arrows left, up, right, down)
      var editKeys = "0,90,88,67,86,65,9,46,8,13,63232,63233,63235,63235";
      var rek = new RegExp("^" + key.toString() + "\\,|\\," + key.toString() + "$|\\," + key.toString() + "\\,");
      if (rek.test(editKeys)) {
         return true;
      }

      // Check to see if we were passed an "xtra" string. 
      // Yes, means we need to convert the "xtra" characters into a bonified RegEx variable to use below.
      // No, means we can check to see if we should do a "strict" check.
      if (("alpha,numeric,alphanum").indexOf(type) > -1 && typeof xtra !== "undefined" && xtra !== "") {
         re = /([\w\W\d\D\s\S])/;
         rex = xtra.replace(re, "\\\\$1");
      } else if (typeof strict === "undefined" || strict === "" || strict !== 1 || strict !== true) {
         strict = false;
      }

      // Handle the filtering
      switch (type) {
      case "alpha":
         re = strict ? /^[a-zA-Z]$/: ((rex === "") ? /^[a-zA-Z \.\,\'\-]$/: new RegExp("^[a-zA-Z" + rex + "]$"));
         return re.test(chr);
      case "numeric":
         re = strict ? /^[0-9]$/: ((rex === "") ? /^[0-9\,\.\-]$/: new RegExp("^[0-9" + rex + "]$"));
         return re.test(chr);
      case "alphanum":
         re = strict ? /^[a-zA-Z0-9]$/: ((rex === "") ? /^[a-zA-Z0-9 \.\,\'\-]$/: new RegExp("^[a-zA-Z0-9" + rex + "]$"));
         return re.test(chr);
      case "email":
         re = /^[a-zA-Z0-9\+\-\.\_\@]$/;
         return re.test(chr);
      default:
         return false;
      }
      return false;

   } else {

      // It appears this browser doesn't support key detection events
      // I'm allowing the key to pass, but you may want to stop it. Your call.
      return true;

   }
}

Usage Example

Usage is fairly straight forward. All you need to do is add a onKeyPress event handler to your input field like so:

<input type="text" name="myField" value="" onkeypress="return(doFieldFilter(event,'alpha'));">

Validating

You might be asking yourself why you would need to validate a field after we came up with such a cool filter function. Well, remember one of the things we allowed with those functions, is that the user has the ability to copy, cut, select all and PASTE. This gives them the ability to paste invalid characters into our filtered field, which means that it doesn't get filtered. This function ensures that after the user is done typing and moves to the next field we still have a way to validate what they entered.

The Function

function doFieldValidate(obj, type, xtra, strict) {
   var re,
   rex = "";

   // Only validate if we have something to work with
   if (typeof obj === "undefined" || obj.value === "" || type === "") {
      return;
   }

   // Check to see if we were passed an "xtra" string.
   // Yes, means we need to convert the "xtra" characters into a bonified RegEx variable to use below.
   // No, means we can check to see if we should do a "strict" check.
   if (("alpha,numeric,alphanum").indexOf(type) > -1 && typeof xtra !== "undefined" && xtra !== "") {
      re = /([\w\W\d\D\s\S])/;
      rex = xtra.replace(re, "\\\\$1");
      re = "";
   } else if (typeof strict === "undefined" || strict === "" || strict !== 1 || strict !== true) {
      strict = false;
   }

   // Handle the validation
   switch (type) {
   case "alpha":
      re = strict ? /^[a-zA-Z]*$/: (rex === "") ? /^[a-zA-Z \.\,\'\-]*$/: new RegExp("^[a-zA-Z" + rex + "]*$");
      if (!re.test(obj.value)) {
         obj.select();
         alert('Please enter a valid alpha value.');
         obj.focus();
      }
      break;
   case "numeric":
      re = strict ? /^[0-9]*$/: (rex === "") ? /^[0-9\,\.\-]*$/: new RegExp("^[0-9" + rex + "]*$");
      if (!re.test(obj.value)) {
         obj.select();
         alert('Please enter a valid numeric value');
         obj.focus();
      }
      break;
   case "alphanum":
      re = strict ? /^[a-zA-Z0-9]*$/: (rex === "") ? /^[a-zA-Z0-9 \.\,\'\-]*$/: new RegExp("^[a-zA-Z0-9" + rex + "]*$");
      if (!re.test(obj.value)) {
         obj.select();
         alert('Please enter a valid alpha/numeric value.');
         obj.focus();
      }
      break;
   case "email":
      re = /^[a-zA-Z0-9._\-]+@([a-zA-Z0-9.\-]+\.)+[a-zA-Z0-9.\-]{2,4}$/;
      if (!re.test(obj.value)) {
         obj.select();
         alert('Please enter a valid e-mail address.');
         obj.focus();
      }
      break;
   case "phone":
      // Most standard U.S. Phone Numbers. No Extension
      re = /^\+?1?\-{0,9} ?\(?[0-9]{3}\)?\-? ?[0-9]{3}\-[0-9]{4}$/;
      if (!re.test(obj.value)) {
         obj.select();
         alert('Please enter a valid U.S. phone number.');
         obj.focus();
      }
      break;
   case "dollar":
      // Doesn't take into account thousandths separators
      re = /^\$?[0-9]*\.?[0-9]{2}$|^\$?[0-9]*$/;
      if (!re.test(obj.value)) {
         obj.select();
         alert('Please enter a valid dollar amount.');
         obj.focus();
      }
      break;
   default:
   }
}

Usage Example

Typically you would want to use this function with an onBlur event.

<input type="text" name="myField" value="" onblur="doFieldValidate(this,'email');">

...and in conjunction with a filter function:

<input type="text" name="myField" value="" 
   onkeypress="return(doFieldFilter(event,'email'));" 
   onblur="doFieldValidate(this,'email');">

Formating

And finally, formatting. There are times, that I want things in a certain format. Mainly phone numbers. So this function can be used to perform any of your formatting needs after the user makes their changes in the form field.

The Function

function doFieldFormat(obj, type, loc) {
      
   // Only validate if we have something to work with
   if (typeof obj === "undefined" || obj.value === "" || type === "") {
      return;
   }

   // Handle the formatting
   switch (type) {
   case "phone":
      var phone = obj.value.replace(/[^0-9]+?/g, '');
      if (isNaN(phone)) {
         alert('Please enter a valid phone number.');
         obj.focus();
         obj.select();
         return;
      } else {
         switch (phone.length) {
         case 0:
            alert('Please enter a valid phone number.');
            obj.focus();
            obj.select();
            break;
         case 7:
            // ###-####
            phone = phone.substr(0, 3) + "-" + phone.substr(3, 4);
            break;
         case 10:
            // (###) ###-####
            phone = "(" + phone.substr(0, 3) + ") " + phone.substr(3, 3) + "-" + phone.substr(6, 4);
            break;
         case 11:
            // # (###) ###-####
            phone = phone.substr(0, 1) + " (" + phone.substr(1, 3) + ") " + phone.substr(4, 3) + "-" + phone.substr(7, 4);
            break;
         default:
            alert('Please enter a valid U.S. phone number (with area code, if applicable).');
            obj.focus();
            obj.select();
         }
         obj.value = phone;
      }
      break;
   case "upper":
      obj.value = obj.value.toUpperCase();
      break;
   case "lower":
      obj.value = obj.value.toLowerCase();
      break;
   default:
   }
}

Usage Example

This function works best by using it with an onChange event.

<input type="text" name="myField" value="" onchange="doFieldFormat(this,'phone');">