When you use CFINPUT and CFSELECT tags, ColdFusion automatically generates javascript to validate your inputs on the client's browser based on specifications you provide; and it converts the CFFORM they reside in to a plain HTML form supported by javascript. This javascript never becomes part of the ColdFusion script itself on the server. You'll only see it on the client. (A few less-common ColdFusion tags use java applets with javascript; they are outside the scope of this article.)
Here's a look "under the hood" at this automatically generated javascript and how ColdFusion forms use it to validate client inputs. During this visit, you'll look at the javascript framework that makes this possible, demonstrate how to require a numeric entry to fall within a stated range, create a page you can use to see every form of ColdFusion client-side validation, and review summaries of the javascript routines with which ColdFusion performs client-side data validation.
First, though, a caveat is in order. Traditional versions of ColdFusion (that is, prior to CFMX) work as shown in this demonstration. CFMX, however, includes /CFIDE/scripts/cfform.js and /CFIDE/scripts/masks.js whenever the CFFORM tag is used. This has three implications:
<cfif isDefined("form.doer") and len(form.doer)>
You have submitted the form.
</cfif>
<cfform name="demo" action="submit.cfm" method="post">
<input type="submit" name="doer" value="Click Me">
</cfform>
Now, put this form on a Web server running ColdFusion, point your browser to it, and view source. You'll see something like this. (To save room, I've removed extra white space from these examples.)
<script LANGUAGE=JAVASCRIPT TYPE="text/javascript" >
<!--
function _CF_checkdemo(_CF_this)
{
return true;
}
//-->
</script>
The check form function (_CF_check...) is executed whenever you submit a specific CFFORM. (You'll see how in a moment.) The entire group of javascript functions generated by ColdFusion is wrapped in an HTML script tag that tells the browser what language this is and how to interpret it. The function within the script tag is wrapped in an HTML comment to hide it from browsers that don't understand the script tag. The closing HTML comment tag is itself hidden from the script interpreter with a script comment "//". The function name and its parameter have outlandish names so that they won't accidentally conflict with other javascript you might write for yourself. The function name ends with the name of your form, "demo" in this case. The parameters in parentheses - this function has only one parameter - show how many values to pass this function. Parameter names in function definitions like this are probably NOT used when the function is called; so, hunt for the function name, not the parameters, when you try to see how routines are associated with each other. This function (check your form name) would usually call validation routines, but since you haven't asked to validate anything, it simply ends with "return true" and doesn't do anything.
Before you press the button, there's nothing useful between the javascript function and the HTML form. After you press the button, the cfif statement displays the "You have" statement. Notice that the "You have" statement is indented. That's because it's indented within the cfif statement. The browser skips this white space when it renders the page.
You have submitted the form.
The next thing you see is the form itself. It's a plain HTML form. The javascript onSubmit statement in the opening form tag calls the check form function named and defined above. The function call in the form tag uses a parameter of "this", telling javascript to pass THIS object (the form encompassed by this tag) to the called function as its parameter.
<FORM NAME="demo" ACTION="submit.cfm" METHOD=POST onSubmit="return _CF_checkdemo(this)"> <input type="submit" name="doer" value="Click Me"> </FORM>
<cfif isDefined("form.doer") and len(form.doer)>
Your number is <cfoutput>#form.myfield#</cfoutput>
</cfif>
<cfform name="demo" action="required.cfm" method="post">
Number from 5 to 8:<cfinput type="text" name="myfield"
required="yes" range="5,8">
<input type="submit" name="doer" value="Click Me">
</cfform>
The ColdFusion code isn't much bigger than last time, but now ColdFusion server adds javascript to display an error, require a value, and require that the value fall within a specific range. For ease of understanding, let's ignore everything (for the moment) except the javascript function that checks the form and the javascript function that displays an error message.
The last javascript function on the page, the check form function (_CF_check...), used to be almost empty. Now it calls the hasValue function (_CF_hasValue) to determine whether myfield has something in it and calls the onError function (_CF_onError) to display a message in an alert box if myfield is empty. ColdFusion has even written an error message corresponding to myfield. If we had specified the message to be displayed in the event that this problem cropped up with this field, the specified message would have been used instead of this canned message. The check form function then calls the checkrange function (_CF_checkrange) to confirm that the value entered is in the desired range and calls the error function if it is not. If this page had 50 fields to test in a single form, it would use only one copy of this function. (A page having two forms would get a copy for each form.)
function _CF_checkdemo(_CF_this)
{
if (!_CF_hasValue(_CF_this.myfield, "TEXT" ))
{
if (!_CF_onError(_CF_this, _CF_this.myfield,
_CF_this.myfield.value, "Error in myfield text."))
{
return false;
}
}
if (!_CF_checkrange(_CF_this.myfield.value, 5, 8))
{
if (!_CF_onError(_CF_this, _CF_this.myfield,
_CF_this.myfield.value, "Error in myfield text."))
{
return false;
}
}
return true;
}
If there's an error, the first javascript function on the page, the onError function (_CF_onError), displays an error message appropriate to the form, field name, field contents, and message in an alert box. The parameter names in the function definition aren't clear at first. Looking back at the data passed by the check form function makes it easier to see what the onError function receives: the equivalent of the form name, field name, field contents, and the message to be displayed.
function _CF_onError(form_object, input_object, object_value,
error_message)
{
alert(error_message);
return false;
}
To see all of the javascript functions created by ColdFusion, a more flexible set of code is desirable.
To forestall later questions, the code reminds you how to invoke this page. It tests for the format variable in your URL and specifies one if none is found. It puts the URL variable in the action URL so that the variable isn't lost when you submit the form. It displays your last entry, if any. Because for flexibility, it uses ColdFusion variables where text is expected, it wraps the form in cfoutput tags. You would normally hard code the input label and "validate" value as plain text.
Invoke as "validate.cfm?format={ColdFusion validation type}".<br>
<cfif (not isDefined("url.format"))
or (len(url.format) lt 1)>
<cfset url.format="float">
</cfif>
<cfset actpage="validate.cfm?format=#url.format#">
<cfif isDefined("form.doer") and len(form.doer)>
<cfoutput>#form.myfield#</cfoutput>
</cfif>
<cfoutput>
<cfform name="demo" action="#actpage#" method="post">
#url.format#: <cfinput type="text" name="myfield"
validate="#url.format#">
<input type="submit" name="doer" value="Click Me">
</cfform>
</cfoutput>
ColdFusion creates many javascript functions to perform client-side entry validation. Omiting the _CF_ prefix, here is the name, size, uses, and summary of each one. If you want to determine the size of a function you've written or found elsewhere to compare it with this list, you can use Microsoft Word's "word count" function and add the line count to the "character count (with spaces)" that it displays. Remember, you'll probably never see a single page that contains all of these functions.
checkcreditcard: 1124; used to validate creditcard. If the entry is present, it removes hyphens and spaces and performs a mod10 test on the input value.
checkdate: 1142; used to validate date. It confirms that the entry, if present, is in the format month number / date of month number / year number. It accepts dates with strange looking years like 10/23/9 or 9/23/124; this is probably OK for entry into databases but not for direct output to a report.
checkday: 383; used to validate date and eurodate. It checks individual pieces of a date to confirm that the month, day, and year are reasonable. If the year is NOT evenly divisible by four or is a century NOT evenly divisible by 400, it does NOT permit February 29th to be used. (Yes, this is confusing, but so is the definition of leap year.)
checkeurodate: 1213; used to validate eurodate. It confirms that the entry, if present, is in the format date of month number / month number / year number. It accepts dates with strange looking years like 23/9/4 or 23/9/123; this is probably OK for entry into databases but not for direct output to a report.
checkinteger: 602; used to validate creditcard, date, eurodate, integer, social_security_number, telephone, time, and zipcode. It confirms that the entry, if present, contains an integer with an optional sign (+/-).
checknumber: 1303; used to validate creditcard, date, eurodate, float, integer, range, social_security_number, telephone, time, and zipcode. It confirms that the entry, if present, is a number. The number may begin with a sign (+/-) and may contain one decimal point. However, a number in scientific notation will be rejected.
checkphone: 1116; used to validate telephone. It confirms that the entry, if present, follows a typical format for a United States telephone number (including area code): nnn nnn-nnnn. The separators may be hyphens or spaces.
checkrange: 382; used to validate date, eurodate, range, telephone, and time. This is a front end for numberrange. If an entry is present and is a number, it invokes numberrange and returns true if numberrange is satisfied.
checkssc: 848; used to validate social_security_number. It confirms that the entry, if present, follows the usual format for a United States Social Security Number: nnn-nn-nnnn. The separators may be spaces, hyphens, plus signs, or periods.
checktime: 1148; used to validate time. It confirms that the entry, if present, is in the format hh:mm:ss (or hh:mm) where hh may be from 00 to 23, mm from 00 to 59, and ss from 00 to 59. The routine has a minor flaw: it accepts times like "10:", "10::", and "10:09:". It also contains a misleading comment which implies it cares about dates. (It doesn't; it only accepts times.)
checkzip: 784; used to validate zipcode. It confirms that the entry, if present, is in one of two formats for United States postal "zip" codes: nnnnn or nnnnn-nnnn. The separator (for the long format) may be a hyphen or a space.
hasValue: 654; used to require that a field is filled in or a selection is made in a checkbox or select list. This is multi-purpose routine that covers all three types of input controls.
numberrange: 324: used to validate date, eurodate, range, telephone, and time. If an entry is present, it confirms that the entry is neither smaller nor larger than the specified range.
Second, don't bother writing new routines for the validation functions already handled by ColdFusion (except perhaps the time function). The best code is code you don't have to write.
Third, if you do have a validation need that these routines won't fill, use them as a starting point and tell others what you've learned.
ColdFusion generates a framework and many of the javascript routines you need in order to handle client-side data validation. Because the javascript is not part of the ColdFusion code, you don't have to add, modify, or review it as you add, modify, and review the rest of your code. You usually won't even see it. Automatically generated javascript is just another feature that makes ColdFusion the choice of champions. =Marty=
[Experience with CFMX, a version not available when this demonstration was originally published, led to the caveat in the introduction.]