CFFORM and field focus problem
The standard use of <CFFORM format="html">, which is the default format, automatically generates the validation script for required fields. Unlike the XML format which uses the xsl\\_cfformvalidation.xsl to generate the validation function, the default format has the function generation hard coded.
On complex html forms, such as a tabbed interface, a problem occurs with the <CFFORM> validation scripts when it tries to focus on a required field that may not be visible. Another annoyance is that the focus will only occur on required fields if they are standard text fields. It will not focus on textarea or other types.
The solution is to override the focus function on the form elements by creating a two-step focus, where the first step initiates any actions required to make the field visible, such as tab navigation and then focus the field.
The example below (Internet Explorer 6) illustrates how to re-assign the focus event. The "Test Focus" button will demonstrate the issue where only text fields will gain focus on a standard form submission and the "Manual Submit" button shows how to gain focus on a textarea.
Also included in the example is the use of the onFocus (which occurs after the focus) and onBlur events to provide a halo effect when the field gains focus.
<cfform name="focusExample">
foo:<cfinput type="text" name="foo" required="yes"
message="Foo is required."><br />
bar:<cfinput type="text" name="bar" required="yes"
message="Bar is required."><br />
comments:<br />
<cftextarea name="comments" rows="5" cols="20" required="yes"
message="Comments are required."></cftextarea><br />
<cfinput type="Submit" name="testFocus" value="Test Focus"><br />
<cfinput type="button" name="manFocus" value="Manual Submit"
onClick="manualSubmission(this)"><bR />
</cfform>
<script>
function haloInput(obj) {
if(typeof(obj) != 'undefined'){
obj.style.borderColor = '#0F0';
obj.style.borderColorDark = '#0F0';
obj.style.borderColorLight = '#0F0';
}else{
this.style.borderColor = '#0F0';
this.style.borderColorDark = '#0F0';
this.style.borderColorLight = '#0F0';
}
}
function plainInput(obj) {
if(typeof(obj) != 'undefined'){
obj.style.borderColor = '';
obj.style.borderColorDark = '';
obj.style.borderColorLight = '';
}else{
this.style.borderColor = '';
this.style.borderColorDark = '';
this.style.borderColorLight = '';
}
}
function checkForOther(){
var fObj = document.getElementById(_CF_FirstErrorField);
var myType = new String(fObj.type);
if(myType.substr(0,6) == 'select' || myType == 'textarea'){
fObj.focus();
}
}
function setFocus(formName){
var currentForm = document[formName];
for (var i = 0; i < currentForm.elements.length;i++){
var fobj = currentForm.elements[i];
if (typeof(fobj) != 'undefined'){
if(fobj.type == 'text'
|| fobj.type == 'textarea'
|| fobj.type == 'select'){
fobj.stepFocus = fobj.focus;
fobj.focus = function(){
// just an alert to show how the
//focus was intercepted. Place
//your own code here such as navigation
//to another tab to make the element
//visible
alert(this.name + ' got focus');
this.stepFocus();
}
// these events occur after the focus
// so lets pretty up the fields
fobj.onfocus = haloInput;
fobj.onblur = plainInput;
}
}
}
}
function manualSubmission(fObj){
var currentForm = fObj.form;
// CFORM automatically generates the function for validation
// so the function name must match _CF_check + the form name
var cfValidate = _CF_checkfocusExample(currentForm);
if(!cfValidate){
checkForOther();
}
}
setFocus('focusExample');
</script>

