For those of you (like me) who are using WebGUI to help manage forms
which _don't_ get processed by WebGUI - (like FormMail/BFormMail) - you
may run into an IE problem with the new WebGUI. Formmail/BFormmail
doesn't check the required fields until you submit your results - and
that works fine - except that if you use the back button to go back to
your form in IE - it will CLEAR all of the contents of that form.
One way to fix this is to improve the form validation for non-webgui forms. I
didn't know how to do this - so I taught myself enough javascript to
get by, and I wrote a nice templated approach to this which I'm proud
of, so thought I'd share it with you all. :)
This javascript will flag any fields which are empty, unselected, unchecked, etc - and will highlight the fields and put a little image next to it of your choice - indicating that the field needs changing.
Example given below:
What you need:
You'll need either a few javascript functions added to any javascript
file you're including, or you'll want to add them to your page style.
function IsRadio(ss)
{
switch(ss.type)
{
case "select-one":
case "text":
case "textarea":
return false;
break;
case "radio":
default:
if (ss[0].type == "radio")
return true;
}
return false;
}
function FieldRequired(ss)
{
switch(ss.type)
{
case "radio": { return CheckRequired(ss); break; }
case "select-one": { return SelectionRequired(ss); break; }
case "text":
case "textarea": { return ContentRequired(ss); break; }
default:
{
if (ss[0].type == "radio")
return CheckRequired(ss);
break;
}
}
return true;
}
function ContentRequired(ss) {
if(ss.value.length > 0) { return false; }
return true;
}
function CheckRequired(ss) {
for(var i = 0; i < ss.length; i++) {
if(ss[i].checked) { return false; }
}
return true;
}
function SelectionRequired(ss) {
for(var i = 0; i < ss.length; i++) {
if(ss[i].selected) {
if(ss[i].value.length) { return false; }
}
}
return true;
}
function insertAfter(parent, node, referenceNode) {
parent.insertBefore(node, referenceNode.nextSibling);
}
function FlagField(ss)
{
var errorID="";
if(IsRadio(ss))
errorID = 'error'+ss[0].name;
else
errorID = 'error'+ss.name;
if(!document.getElementById(errorID))
{
var errorClass='fieldError';
var errorIndicator=document.createElement('img');
errorIndicator.id=errorID;
errorIndicator.src='/extras/error.gif';
errorIndicator.alt='Error';
errorIndicator.title='Error!';
ss.className=errorClass;
if (IsRadio(ss))
insertAfter(ss[ss.length-1].parentNode,errorIndicator,ss[ss.length-1].nextSibling);
else
insertAfter(ss.parentNode,errorIndicator,ss);
}
}
function ClearFlag(ss)
{
var errorID = "";
if(IsRadio(ss))
errorID = 'error'+ss[0].name;
else
errorID = 'error'+ss.name;
var oldFlag = document.getElementById(errorID);
if (oldFlag)
{
ss.className="";
oldFlag.parentNode.removeChild(oldFlag);
}
}
The above routines all do the checking - FieldRequired() takes any form
object and then determines whether it's a radio button, text object,
select list, etc and checks it accordingly. There is reference to one image in FlagField which you will need to define. This is the image that is inserted after the field that has failed validation - I use a little exclamation mark icon, but it's up to you what you want to use.
You will also need a small bit of CSS to define what an error field looks like:
.fieldError {
background: #fcc;
}
Now.. the cool bit - in your form template you need to add the following:
<SCRIPT language="JavaScript1.2">
function CheckRequiredFields() {
var errormessage = new String();
// Put field checks below this point.
<tmpl_loop field_loop>
<tmpl_if field.isRequired>if(FieldRequired(document.bformmail.<tmpl_var field.name>)){ errormessage += "\n * <tmpl_var field.label> is a required field."; }</tmpl_if>
</tmpl_loop>
// Put field checks above this point.
if(errormessage.length > 2) {
alert('You still have required fields remaining:\n' + errormessage);
return false;
}
return true;
} // end of function CheckRequiredFields()
</SCRIPT>
The above code uses templates to iterate through each field and if it's
a required field then add javascript code to check it. If the field
isn't filled in/checked/selected/etc then it adds it to a growing error
message which lists all the fields not entered. If you're using the tab
form object then you need to change the loop slightly:
<SCRIPT language="JavaScript1.2">
function CheckRequiredFields() {
var errormessage = new String();
// Put field checks below this point.
<tmpl_loop tab_loop>
<tmpl_loop tab.field_loop>
<tmpl_if tab.field.isRequired>if(FieldRequired(document.bformmail.<tmpl_var tab.field.name>)){ errormessage += "\n * <tmpl_var tab.field.label> is a required field."; }</tmpl_if>
</tmpl_loop>
</tmpl_loop>
// Put field checks above this point.
if(errormessage.length > 2) {
alert('You still have required fields remaining:\n' + errormessage);
return false;
}
return true;
} // end of function CheckRequiredFields()
</SCRIPT>
Now.. the final bit - and the most cruicial. In your <form
action=xxx statement you need to add two things - one - a name (in my
code above I assume the name is bformmail - but you can change this to
whatever you want as long as it is unique), and secondly you need to
add the removed code to call the above javascript code.
<form name="bformmail" removed="return CheckRequiredFields();" method="post" action="/cgi-bin/BFormMail.cgi">
Your method and action can differ, but if you use the above code as is,
then the other two need to be the same. The removed code is what sets
it all off - it calls the template generated code which in turns calls
those javascript routines to check the fields. The great thing about
this is that it leverages the power of webgui and uses templates to do
the work for you :)
This could also be applied to regular
webgui forms too if you really wanted, but there's not much point as
they work pretty well as is.
Keywords: MESSAGE