CFDJ Issue 2: Vol: 8  p.52
Extending CFFORM with Customized JavaScript Validation
Author: Selene Bainum

Listing 1: ExtendCFFORM.cfm  
<HTML>
<HEAD>
<TITLE>Extending CFFORM</TITLE>
<SCRIPT LANGUAGE = "JavaScript">
// Main validation function.
// Variables needed: form name
// All validation functions will be called from
// this function
// The actual validation functions will be outside
// of this function, either above or below it
// If any of the variables used in these functions
// are ColdFusion variables, the functions must be
// within CFOUTPUT tags
function ExtendJS(FormName) {
  // Call the function to validate a date as being
  // before today's date.
  // Variables to pass: form name, field name,
  // type
  // The type parameter will have a value of
  // either 'date' or 'eurodate'
  if (!DateLessThan(FormName,'DOB','date')) {
    alert("Your DOB cannot be after today.");
    return false;
  }
  // Call the RadioCheckBox function to
  // ensure one of a radio button series is
  // checked
  // Variables to pass: form name, field name,
  // number of items total, min required, max
  // required
  // * For radio fields, min and max will be 1
  // * The number of items total will most likely
  // be the RecordCount of the query used to
  // generate the options.
  if (!RadioCheckBox(FormName,'Sex',2,1,1))
  {
    alert("You must select your sex.");
    return false;
  }
  // Call the RadioCheckBox function to
  // ensure one (or more) of a checkbox series is
  // checked
  // Variables to pass: form name, field name,
  // number of items total, min required, max
  // required
  // * The number of items total will most likely
  // be the RecordCount of the query used to
  // generate the options.
  if
   (!RadioCheckBox(FormName,'Hobbies',4,2,3))
  {
    alert("You must select 2 or 3 hobbies.");
    return false;
  }
  // Call the SingleSelectRequired function to
  // ensure an item in a select box is chosen
  // Variables to pass: form name, field name
  if (!SingleSelectRequired(FormName,'Version')) {
    alert("You must a version of CF.");
    return false;
  }
  // Call the MultiSelectCheck function to ensure
  // one (or more) items in multi-select box are
  // chosen
  // Variables to pass: form name, field name
  if (!MultiSelectCheck(FormName,'FavTags',2,6)) {
    alert("You must at least 2 tags.");
    return false;
  }
  // Call the TextAreaRequired function to ensure
  // a textbox field is filled out
  // Variables to pass: form name, field name
  if (!TextAreaRequired(FormName, 'Comments')) {
    alert("You must enter some comments.");
  return false;
  }
}

// Validation functions

// Function to ensure a text area field is filled
// out.
// Variables needed: form name, field name
function TextAreaRequired(Form,Field) {
  // determine the length of the value of the
  // field.
  // The eval function will evaluate the statement
  // inside the parenthesis.
  var length = eval("document." + Form + "." + Field
    + ".value.length");
  // If the length of the value of the field is 0,
  // return false.
  if (length == 0) {
    return false;
  } else {
    return true;
  }
}

// Function to validate the number of items
// selected in a multi-select box
// Variables needed: form name, field name,
// minimum items selected,
// maximum items selected
function MultiSelectCheck(Form,Field,minReq,maxReq)
{
  // Set the selected var to a default of 0.
  var selected = 0;
  // Determine how many options are in the
  // multi-select box
  var length = eval("document." + Form + "." + Field
    + ".length");
  // Loop through the items in the multi-select
  //box
  for (i=0; i<length; i++) {
    // If an item is selected, increment the
    // selected var by one
    if (eval("document." + Form + "." + Field + "["
      + i + "].selected")) {
      selected++;
    }
  }
  // Determine if the number of items selected is
  // between the max and min values.
  // Return false if not, true if so
  if (selected < minReq || selected > maxReq) {
    return false;
  } else {
    return true;
  }
}

// Function to ensure that a value in a select box
// is selected
// Variables needed: form name, field name
function SingleSelectRequired(Form,Field) {
  // Determine the index of the item currently
  // selected
  var itemSelected = eval("document." + Form + "." +
    Field + ".selectedIndex");
  // If that index is 0, return false
  if (itemSelected == 0) {
    return false;
  } else {
    return true;
  }
}

// Function to validate radio and check boxes
// For radio, ensures that one radio button in a
// series is selected
// For checkbox, ensures that the number selected
// is in the min and under the max
// Variables needed: form name, field name, number
// of items total, minimum items checked, maximum
// items checked
// For radio buttons, the min and max will always
// be 1
function
  RadioCheckBox(Form,Field,length,minReq,maxReq)
{
  // Set the checked var to a default value of 0
  var checked = 0;
  // Loop through the number of items
  for (i=0; i<length; i++) {
    // If an item is checked, increment the
    // checked var
    if (eval("document." + Form + "." + Field + "["
      + i + "].checked")) {
      checked++;
    }
  }
  // If the checked var is between the min and
  // max, return true, otherwise, false
  if (checked < minReq || checked > maxReq) {
    return false;
  } else {
    return true;
  }
}

// Function to validate a date so that the date
// entered must be less than today
// Variables needed: form name, field name
// Don't you wish JavaScript had a DateCompare
// function?
function DateLessThan(Form,Field,type) {
  // Create a var called today with a value of
  // today's date
  var today = new Date();
  // Get the time in milliseconds from the current
  // date
  var todayMS = today.getTime();
  // Get the date value of the form field (this
  // has already been validated as a valid date by
  // CF's form validation'
  var dateValue = eval("document." + Form + "." +
    Field + ".value");
  // Split the date to create an array
  var dateSplit = dateValue.split("/");
  // If the type is 'date', set the month to the
  // first value in the array
  // Subtract 1 from the date because JavaScript
  // uses 0-11 to represent months
  // Set the day of the month to the second value
  // in the array
  if (type == 'date') {
    var month = dateSplit[0] - 1;
    var day = dateSplit[1];
  }
  // If the type is 'eurodate', set the month to
  // the second value in the array
  // Subtract 1 from the date because JavaScript
  // uses 0-11 to represent months
  // Set the day of the month to the first value
  // in the array
  if (type == 'eurodate') {
    var month = dateSplit[1] - 1;
    var day = dateSplit[0];
  }
  // Set the year to the third value in the array
  var year = dateSplit[2];
  // Create a new date object variable to hold the
  // date, passing in the month, day and year
  var dateEntered = new Date(year,month,day,0,0,0);
  // Get the milliseconds from this date
  var dateEnteredMS = dateEntered.getTime();
  // Compare the milliseconds from the current
  // date with those of the date entered.
  // Return false if the date entered is greater
  // than today's date
  if (dateEnteredMS > todayMS) {
    return false;
  } else {
    return true;
  }
}

</SCRIPT>
</HEAD>

<BODY BGCOLOR = "#ffffff">

<B>Fill out the form below:</B><P>

<I>(all fields required)</I><P>

<!---
  Create the form with the CFFORM tag.
  Add an onSubmit attribute and in it call
  the ExtendJS() function. Pass the name of the
  form, in this case Extend, to the function
--->
<CFFORM NAME = "Extend" ACTION = "Action.cfm"
onSubmit = "return ExtendJS('Extend')">

<TABLE BORDER = "0">
  <TR>
    <TD><B>Name:</B></TD>
    <TD><CFINPUT TYPE = "text" NAME = "Name"
    REQUIRED = "yes"
    MESSAGE = "You must enter your name."></TD>
  </TR>

  <TR>
    <TD><B>Age:</B></TD>
    <TD><CFINPUT TYPE="Text" NAME="Age"
    RANGE="21,150" VALIDATE="integer"
    REQUIRED="Yes"
    MESSAGE = "You must be 21."></TD>
  </TR>

  <TR>
    <TD><B>DOB:</B></TD>
    <TD><CFINPUT TYPE="Text" NAME="DOB"
    VALIDATE="date" REQUIRED="Yes"
    MESSAGE = "You must enter a valid date.">
    </TD>
  </TR>

  <TR>
    <TD><B>Sex:</B></TD>
    <TD><NOBR><CFINPUT TYPE="Radio" NAME="Sex"
    VALUE="Male">Male&nbsp;<CFINPUT TYPE="Radio"
    NAME="Sex" VALUE="Female">Female</NOBR></TD>
  </TR>

  <TR>
    <TD VALIGN = "top"><B>Hobbies:</B><BR><I>Check
    2 or 3</I></TD>
    <TD VALIGN = "top">
    <CFINPUT TYPE="checkbox" NAME="Hobbies"
    VALUE="TV">Watching TV<BR>
    <CFINPUT TYPE="checkbox" NAME="Hobbies"
    VALUE="Reading">Reading<BR>
    <CFINPUT TYPE="checkbox" NAME="Hobbies"
    VALUE="WorkingOut">Working Out<BR>
    <CFINPUT TYPE="checkbox" NAME="Hobbies"
    VALUE="Programming">Programming<BR>
    </TD>
  </TR>

  <TR>
    <TD><B>First CF Version:</B></TD>
    <TD><SELECT NAME = "Version">
    <OPTION VALUE = "">Select One
    <OPTION VALUE = "1.x">1.x
    <OPTION VALUE = "2.x">2.x
    <OPTION VALUE = "3.x">3.x
    <OPTION VALUE = "4.x">4.x
    </SELECT></TD>
  </TR>

  <TR>
    <TD VALIGN = "top"><B>Favorite
    Tags:</B><BR><I>Select at least 2</I></TD>
    <TD VALIGN = "top"><SELECT NAME = "FavTags"
    SIZE = "6" MULTIPLE>
    <OPTION VALUE = "CFOUTPUT">CFOUTPUT
    <OPTION VALUE = "CFQUERY">CFQUERY
    <OPTION VALUE = "CFIF">CFIF
    <OPTION VALUE = "CFFORM">CFFORM
    <OPTION VALUE = "CFLOOP">CFLOOP
    <OPTION VALUE = "CFSET">CFSET
    </SELECT></TD>
  </TR>
 
  <TR>
    <TD COLSPAN = "2"><B>Comments:</B></TD>
  </TR>
 
  <TR>
    <TD COLSPAN = "2"><TEXTAREA NAME = "Comments"
    COLS = "30" ROWS = "4" WRAP =
    "virtual"></TEXTAREA></TD>
  </TR>
</TABLE><P>

<INPUT TYPE = "submit" VALUE = "Submit">
</CFFORM>

</BODY>
</HTML>