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:
- Filtering: Filter what the user can type into a field.
- Validating: Validate what the user typed into a field.
- 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');">
Comments are closed.