/**
 * @file Checks a form for all required fields to be filled and for correct mail adresses and prompts feedback messages to the user. Possibility to reset the form and all messages, if the user cancels. Contains no localized strings (language neutral). Works for pages with several forms.
 *       Usage: Call the function checkForm() from the <form>-element's onsubmit-attribute with a preceding return like this <form onsubmit="return checkForm(...);" ...>. Optionally, call the function resetForm() from the <form>-element's onreset-attribute (with or without preceding return).
 * @requires: - labels for every obligatory input or textarea 
 *            - a hidden <p>-element for the warning message inside the <form>-element. It is hidden by a css-class named "hidden-warning", containing the command display:none
 *            - an empty <span>-element inside that warning <p>-element to display the names of the incorrectly filled inputs
 *            - a css class named "warning" to highlight the <p>-element and the labels of incorrectly filled inputs
 *            - an html anchor (<a name="..."></a>) element at the top of the form, just before the <p>-element with the warning message. The anchor name attribute starts with the name of the form, followed by "-top", for example if the <form>-element had "contact" as value for its name attribute, the anchor name must be "contact-top"
 * @author: Michael Kamphausen, http://www.michael-kamphausen.de
 * @version: 2007-07-20
 */

/*
 * Checks a form for all required fields to be filled and for correct mail adresses and prompts feedback messages to the user
 * @param formName name- or id-attribute of the <form>-element
 * @param obligatoryFields an array with the id-attribute values of all input-elements that are required, not the name-attribute! Values containing nothing but whitespaces are invalid, too.
 * @param mailFields an array with the id-attribute values of all input-elements that contain mail-adresses that shall be checked (@ and dot-sign, surrounded by any characters except whitespace)
 * @return true, if all required values are given and correctly formatted
 */
function checkForm(formName, obligatoryFields, mailFields) {
  if (!formName) {return false;}
  failedFields = new Array();
  form = document.forms[formName];
  
  if (obligatoryFields) {
    for (var i = 0, lengthI = obligatoryFields.length; i < lengthI; i++) {
      var element = form.elements[obligatoryFields[i]];
      if (element.length) {
        var checked = false;
        for (var j = 0, lengthJ = element.length; (j < lengthJ) && !checked; j++) {
          checked = element[j].checked;
        }
        if (!checked) {
          failedFields.push(obligatoryFields[i]);
        }
      } else {
        var input = element.value;
        if (!input || !input.length || (input.replace(/\s/g, "").length == 0)) {
          failedFields.push(obligatoryFields[i]);
        }
      }
    }
  }
  
  if (mailFields) {
    for (var i = 0, lengthI = mailFields.length; i < lengthI; i++) {
      var input = form.elements[mailFields[i]].value;
      if (!input || !input.length || (input.search(/\S+@\S+\.\S/) < 0)) {
        failedFields.push(mailFields[i]);
      }
    }
  }
  
  if (failedFields.length > 0) {
    showWarnings(form, failedFields);
    document.location.href = document.location.href.replace(/#.*/, "") + "#" + formName + "-top";
    return false;
  } else {
    return true;
  }
}

/*
 * Reset the warning message and highlighted labels, bring them back to normal
 * @param formName name- or id-attribute of the <form>-element
 */
function resetForm(formName) {
  if (!formName) {return false;}
  form = document.forms[formName];
  document.location.href = document.location.href.replace(/#.*/, "") + "#" + formName + "-top";
  showWarnings(form, new Array());
}

/*
 * Displays or hides the warning message and warning highlighted labels, depending of it's occurance in the parameter failedFields. This function can be, but is not intended to be directly called, only from checkForm() and resetForm().
 */
function showWarnings (form, failedFields) {
  if (!form || !failedFields) {return false;}
  var failedLabels = new Array();

  var labels = form.getElementsByTagName("label");
  for (var i = 0, lengthI = labels.length; i < lengthI; i++) {
    var currentLabel = labels.item(i);
    var found = false;
    if (currentLabel.className) {
      currentLabel.className = 
        currentLabel.className.replace(/ warning/, "");
    }
    for (var j = 0, lengthJ = failedFields.length; (j < lengthJ) && !found; j++) {
      found = currentLabel.htmlFor == failedFields[j].replace(/\[.*\]/g, "");
      if (found) {
        currentLabel.className = currentLabel.className + " warning";
        failedLabels.push(currentLabel.firstChild.data.replace(/:.*$/, ""));
      }
    }
  }
  
  var failedLabelsString = "";
  for (var i = 0, lengthI = failedLabels.length; i < lengthI - 2; i++) {
    failedLabelsString = failedLabelsString + failedLabels[i] + ", ";
  }
  failedLabelsString = failedLabelsString + 
    ((lengthI - 2 >= 0)?(failedLabels[lengthI - 2] + " & "):(""));
  failedLabelsString = failedLabelsString + 
    ((lengthI - 1 >= 0)?(failedLabels[lengthI - 1] + " "):(""));
  
  var paras = form.getElementsByTagName("p");
  var found = false;
  for (var i = 0, lengthI = paras.length; (i < lengthI) && !found; i++) {
    var found = (paras.item(i).className == "hidden-warning") ||
      (paras.item(i).className == "warning");
    if (found) {
      var span = paras.item(i).getElementsByTagName("span").item(0);
      if (failedFields.length > 0) {
        paras.item(i).className = "warning";
        if (!span.firstChild) {
          span.appendChild(document.createTextNode(failedLabelsString));
        } else {
          span.firstChild.data = failedLabelsString;
        }
      } else {
        paras.item(i).className = "hidden-warning";
        if (span.firstChild) {
          span.firstChild.data = "";
        }
      }
    }
  }

}
