/*
 *  File:  checkForm.js
 *
 *  Automatic form checking (for ver 4.0 browsers and above)
 *
 *  Usage:
 *
 *    <script type="text/javascript"
 *            src="http://www.bgsu.edu/scripts/checkForm.js">
 *    </script>
 *    ...
 *    <form ... onsubmit="return checkForm( this )">
 *
 *  Insert the <script> tags in the <head> or <body> of your document.
 *  Insert the <form> tag in the <body> of your document.
 *
 *  Example:  checkFormTest.html
 *
 *  The following input elements are recognized by checkForm:
 *
 *                     Checked?
 *    Element          Yes   No   Result
 *    ------------------------------------------------------------------
 *    button                 X    NA
 *    checkbox          X         Warning if none in a group are checked
 *    file              X         Error if input field is empty
 *    hidden                 X    NA
 *    password          X         Error if input field is empty
 *    radio             X         Error if none in a group are checked
 *    reset                  X    NA
 *    select-one        X         Warning if no option is selected
 *    select-multiple   X         Warning if no options are selected
 *    submit                 X    NA
 *    text              X         Error if input field is empty
 *    textarea          X         Error if input field is empty
 *
 *  Note:  A select-multiple element is a select element with the
 *         MULTIPLE attribute, whereas a select-one element has no 
 *         MULTIPLE attribute.
 *
 *  For custom form checking, simply override the checkForm() function.
 *  For example, to check a subset of the input elements, try this:
 *
 *    <script type="text/javascript"
 *            src="http://www.bgsu.edu/scripts/checkForm.js">
 *    </script>
 *    <script type="text/javascript">
 *      // Overrides checkForm() (skips over some input elements):
 *      function checkForm( form ) {
 *        return checkText( form.mailTo ) &&
 *               checkText( form.mailFrom ) &&
 *               checkText( form.mailSubject ) &&
 *               checkSelectOne( form.group ) &&
 *               checkTextarea( form.message );
 *      }
 *    </script>
 *    ...
 *    <form ... onsubmit="return checkForm( this )">
 * 
 *  where mailTo, mailFrom, mailSubject, group, and message are the 
 *  names of specific input elements that require checking (all other
 *  input elements are ignored).
 *
 *  Here is a complete list of the functions called by checkForm():
 *
 *    Element           Function
 *    ------------------------------------------------------------------
 *    text              checkText
 *    textarea          checkTextarea
 *    radio             checkRadio
 *    checkbox          checkCheckbox
 *    select-one        checkSelectOne
 *    select-multiple   checkSelectMultiple
 *    file              checkFile
 *    password          checkPassword
 *
 *  These boolean functions may be used separately (as above) or may be
 *  overridden for further customization.  For example, here's how to 
 *  use a more restrictive form of the checkSelectMultiple() function:
 *
 *    <script type="text/javascript"
 *            src="http://www.bgsu.edu/scripts/checkForm.js">
 *    </script>
 *    <script type="text/javascript">
 *      // checkSelectStrict returns true if an option is selected:
 *      var checkSelectMultiple = checkSelectStrict;
 *    </script>
 *    ...
 *    <form ... onsubmit="return checkForm( this )">
 *    
 *  Finally, here is an example that handles select elements with 
 *  attribute SIZE="1" (which is the default size in HTML):
 *
 *    <script type="text/javascript"
 *            src="http://www.bgsu.edu/scripts/checkForm.js">
 *    </script>
 *    <script type="text/javascript">
 *      // checkSelectSpecial returns true if the user makes a 
 *      // selection other than options[0]:
 *      var checkSelectOne = checkSelectSpecial;
 *    </script>
 *    ...
 *    <form ... onsubmit="return checkForm( this )">
 *    
 *  The checkSelectSpecial() function returns true if the user 
 *  makes a selection other than options[0].
 *
 */

// Returns true if all form elements pass their respective test:
function checkForm( formObj ) {

  // Local variables:
  var element, type, name, oldName;
  
  // Check all input elements:
  var n = formObj.elements.length;
  for ( var i = 0; i < n; i++ ) {
    element = formObj.elements[i];
    type = element.type;
    // Ignore buttons and hidden fields:
    if ( type == "text" ) {
      if ( !checkText( element ) ) return false;
    } else if ( type == "textarea" ) {
      if ( !checkTextarea( element ) ) return false;
    } else if ( type == "radio" || type == "checkbox" ) {
      name = element.name;
      if ( name != oldName ) {
        // Obtain the corresponding group element:
        element = eval( "formObj." + name );
        if ( type == "radio" && !checkRadio( element ) ) return false;
        if ( type == "checkbox" && !checkCheckbox( element ) ) return false;
        oldName = name;
      }
    } else if ( type == "select-one" ) {
      if ( !checkSelectOne( element ) ) return false;
    } else if ( type == "select-multiple" ) {
      if ( !checkSelectMultiple( element ) ) return false;
    } else if ( type == "file" ) {
      if ( !checkFile( element ) ) return false;
    } else if ( type == "password" ) {
      if ( !checkPassword( element ) ) return false;
    }
  }
  
  // All tests were successful:
  return true;
  
}

// Default function assignments:
var checkText = checkTextGeneric;
var checkTextarea = checkTextGeneric;
var checkFile = checkTextGeneric;
var checkPassword = checkTextGeneric;
var checkSelectOne = checkSelectGeneric;
var checkSelectMultiple = checkSelectGeneric;

// Returns true if a generic text element is not empty:
function checkTextGeneric( textObj ) {
  if ( isEmpty( textObj ) ) {
    window.alert( "Enter " + textObj.name + "!" );
    textObj.value = "";
    textObj.focus();
    return false;
  }
  return true;
}

// Returns true if an option of a generic select element is selected 
// or if the user does not wish to select any options:
function checkSelectGeneric( selectObj ) {
  if ( selectObj.selectedIndex == -1 ) {
    var name = selectObj.name;
    if ( window.confirm( "Do you want to select " + name + "?" ) ) {
      selectObj.focus();
      return false;
    }
  }
  return true;
}

// Returns true if a radio button is checked:
function checkRadio( radioObj ) {
  var n = radioObj.length;
  for ( var i = 0; i < n; i++ ) {
    if ( radioObj[i].checked ) return true;
  }
  window.alert( "Please check " + radioObj[0].name + "!" );
  radioObj[0].focus();
  return false;
}

// Returns true if at least one of a group of checkboxes is checked
// or if the user does not wish to check any checkboxes:
function checkCheckbox( checkboxObj ) {
  var n = checkboxObj.length;
  for ( var i = 0; i < n; i++ ) {
    if ( checkboxObj[i].checked ) return true;
  }
  var name = checkboxObj[0].name;
  if ( window.confirm( "Do you want to check " + name + "?" ) ) {
    checkboxObj[0].focus();
    return false;
  }
  return true;
}

// Returns true if an option is selected:
function checkSelectStrict( selectObj ) {
  if ( selectObj.selectedIndex == -1 ) {
    window.alert( "Please select " + selectObj.name + "!" );
    selectObj.focus();
    return false;
  }
  return true;
}

// A function to check select elements with attribute SIZE="1".
// Returns true if the user makes a selection other than options[0]:
function checkSelectSpecial( selectObj ) {
  if ( selectObj.selectedIndex == 0 ) {
    window.alert( "Please select " + selectObj.name + "!" );
    selectObj.focus();
    return false;
  }
  return true;
}

// Returns true if the value of the text element is null or whitespace:
function isEmpty( textObj ) {
  var regexp = /^\s*$/;
  return regexp.test( textObj.value );
}

// For backwards compatibility with a previous version of this script:
// (Do not use!  Will be removed in a future version!)
var checkSelect = checkSelectSpecial;
