/**
 * $Source: /usr/local/cvs/integration/web/components/form/form.js,v $
 * $Author: karl $
 * $Revision: 1.10 $
 * $Date: 2004/09/09 04:42:14 $
 *
 * ====================================================================
 *
 * Copyright (C) 2002-04 Frontleaf. All Rights Reserved.
 *
 * Use, modification and distribution of this Software in source or 
 * object form is strictly prohibited without prior agreement 
 * with Frontleaf.  Frontleaf reserves all rights not expressly granted to
 * you in such an agreement.  
 * 
 * Send all inquiries to license (at) frontleaf.com.
 **/

function isButtonGroup(element) {

  return (! element.tagName && element.length);
}

function isSelect(element) {
  return (element.type == "select-one");
}

function checkValue(formName, elementName, message) {

  var element = document.forms[formName].elements[elementName];

  if (! element) {
    alert("Could not find element " + elementName + " in form " + formName);
    return;
  }

  var isGroup = isButtonGroup(element);
  if (isGroup) {
    var value = getCheckedValue(elementName);
  } else {
    if (isSelect(element)) {
      var value = getSelectedValue(formName, elementName);
    } else {
      var value = element.value;
    }
  }
  if (! value || value == "") {
    if (message != "") {
      alert(message);
    }
    if (! isGroup && (! element.type || (element.type != "hidden"))) {
      element.focus();
    }
    event.returnValue = false;
    return false;
  }
  return true;
}

function checkIntRange(formName, elementName, min, max, message) {

  intPattern = /^\d+$/;

  var element = document.forms[formName].elements[elementName];
  if (! element) {
    alert("Could not find element " + elementName + " in form " + formName);
    return;
  }

  var value = element.value;

  if (! intPattern.exec(value)) {
    if (message != "") {
      alert(message);
    }
    element.focus();
    event.returnValue = false;
    return false;
  }

  if (value < min || value > max) {
    if (message != "") {
      alert(message);
    }
    element.focus();
    event.returnValue = false;
    return false;
  }

  return true;
}

function checkEmailValue(s) {

   var emailPattern = /^.+@.+\..{2,3}$/;
   if (! emailPattern.test(s)) { 
     return false;
   }

   var illegalChars= /[\(\)\<\>\,\;\:\\\/\"\[\]]/
   if (s.match(illegalChars)) {
      return false;
   }

   return true;
} 

function checkEmail(formName, elementName, message) {

  return checkFunction(formName, elementName, message, checkEmailValue);
}

function checkDate(formName, elementName, message) {

  var datePattern = /\d{1,2}\/\d{1,2}\/\d\d\d\d/;

  return checkPattern(formName, elementName, message, datePattern);
}

function checkInt(formName, elementName, message) {

  var intPattern = /^\d+$/;

  return checkPattern(formName, elementName, message, intPattern);
}

function checkNum(formName, elementName, message) {

  var numPattern = /^(\d+(\.\d*)?|\.\d+)$/;

  return checkPattern(formName, elementName, message, numPattern);
}

function checkURL(formName, elementName, message) {

  var urlPattern = /^http:\/\/[a-zA-Z0-9_\-\.]+(:\d+)*\/?/;

  return checkPattern(formName, elementName, message, urlPattern);
}

function checkTime(formName, elementName, message) {

  var timePattern = /\d{1,2}:\d\d\ ([aA][mM]|[pP][mM])/;

  return checkPattern(formName, elementName, message, timePattern);
}

function checkPattern(formName, elementName, message, pattern) {

  var element = getElement(formName, elementName);
  if (element == null) { 
    alert("Element " + elementName + " not found.");
    event.returnValue = false;
    return false;  
  }

  var value = element.value;

  if (! pattern.exec(value)) {
    alert(message);
    element.focus();
    event.returnValue = false;
    return false;
  }

  return true;
}

function checkFunction(formName, elementName, message, f) {

  var element = getElement(formName, elementName);
  if (element == null) { 
    alert("Element " + elementName + " not found.");
    event.returnValue = false;
    return false;  
  }

  var value = element.value;

  if (! f(value)) {
    alert(message);
    element.focus();
    event.returnValue = false;
    return false;
  }

  return true;
}

// Function that checks that a pair of form elements is either both
// set or both unset.

function checkValuePair(formName, elementOne, elementTwo, message) {

  var element1 = document.forms[formName].elements[elementOne];
  var element2 = document.forms[formName].elements[elementTwo];

  if (! element1) {
    alert("Could not find element " + elementOne + " in form " + formName);
    return;
  }
  if (! element2) {
    alert("Could not find element " + elementTwo + " in form " + formName);
    return;
  }

  if (isButtonGroup(element1)) {
    var value1 = getCheckedValue(elementOne);
  } else {
    if (isSelect(element1)) {
      var value1 = getSelectedValue(formName, elementOne);
    } else {
      var value1 = element1.value;
    }
  }
  if (isButtonGroup(element2)) {
    var value2 = getCheckedValue(elementTwo);
  } else {
    if (isSelect(element2)) {
      var value2 = getSelectedValue(formName, elementTwo);
    } else {
      var value2 = element2.value;
    }
  }
  if ((value1 == "" && value2 != "") || (value1 != "" && value2 == "")) {
    alert(message);
    if (value1 == "") {
      element1.focus();
    } else {
      element2.focus();
    }
    event.returnValue = false;
    return false;
  }
  return true;
}

function getCheckedValue(elementName, elements) {
  
  if (! elements) {
    elements = document.getElementsByName(elementName);
  }

  for (i = 0; i < elements.length; i++) {
    var element = elements.item(i);
    if (element.checked) {
      return element.value;
    }
  }
  return "";
}

function getCheckedValues(elementName) {

  var elements = document.getElementsByName(elementName);
  var values = new Array();
  var valueCount = 0;
  for (i = 0; i < elements.length; i++) {
    if (elements.item(i).checked) {
      values[valueCount++] = elements.item(i).value;
    }
  }
  return values;
}

function getSelectedValue(formName, elementName) {
  
  var element = document.forms[formName].elements[elementName];
  if (element.selectedIndex != -1) {
    return element.item(element.selectedIndex).value;
  }
  return "";
}

// form data takes the form [ [elementName, whichTest, errorMessage], ... ]
// valid tests are "notnull" and "date"

function checkValues(formName, formData) {

  for (i = 0; i < formData.length; i++) {

    var elementData = formData[i];
    var elementName = elementData[0];
    var whichTest = elementData[1];
    var errorMessage = elementData[2];

    if (whichTest == "notnull") {

      if (! checkValue(formName, elementName, errorMessage)) 
        return false; 
    }
  }

  return true;
}

function getElement(formName, elementName) {

  var form = document.forms[formName];
  if (! form) { 
    alert("No such form " + formName);
    return null;
  }

  var element = form.elements[elementName];
  if (! element) { 
    alert("No such element " + elementName);
    return null;
  }

  return element;
}

function getValue(formName, elementName) {

  var element = getElement(formName, elementName);
  if (element == null) { return; }

  if (element.tagName == "SELECT") {
    return getSelectedValue(formName, elementName);
  }

  if (element.length) {
    return getCheckedValue(elementName, element);
  }

  return element.value;
}

function setValue(formName, elementName, value) {

  var element = getElement(formName, elementName);
  if (element == null) { return; }

  if (element.length && element.tagName != "SELECT") {
    setCheckedValue(element, value);
    return;
  }

  if (element.tagName == "SELECT") {
    setSelectedValue(element, value);
  }

  element.value = value;
}

function setCheckedValue(elements, value) {
  
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    element.checked = (element.value == value);
  }
}

function setSelectedValue(element, value) {
  
  var options = element.options;
  for (var i = 0; i < options.length; i++) {
    var option = options[i];
    option.selected = (option.value == value);
  }
}

function setCheckedValues(formName, elementName, values) {

  var element = getElement(formName, elementName);
  if (element == null) { return; }

  var elements = element;
  if (! element.length) {
    elements = new Array();
    elements[0] = element;
  }

  for (var i = 0; i < values.length; i++) {
    var value = values[i];
    for (var j = 0; j < elements.length; j++) {
      var element = elements[j];
      if (element.value == value) element.checked = true;
    }
  }
}

function focusElement(formName, elementName, selectAll) {

  if (! elementName) { return; }

  var element = getElement(formName, elementName);
  if (element == null) { return; }

  element.focus();
  if (selectAll)
    element.select();
}

function Validator(type, required) {

  this.type = type;
  this.required = required;

  this.validate = validateValue;
  this.checkType = checkType;
  this.checkLength = checkLength;
  this.checkChars = checkChars;
  this.checkRange = checkRange;
  this.toString = toString;
}

function validateValue(value) {

  if (value == "") {
    if (this.required) {
      this.message = "A value is required for the field '" + this.label + "'";
      return false;
    } else {
      return true;
    }
  }

  switch (this.type) {
    case "text":
      if (! this.checkLength(value)) { return false; }
      if (! this.checkChars(value)) { return false; }
      break;
    case "integer":
      if (! this.checkType(value)) { return false; }
      var intValue = parseInt(value);
      if (! this.checkRange(intValue)) { return false; }
      break;
    case "number":
      if (! this.checkType(value)) { return false; }
      var numValue = parseFloat(value);
      if (! this.checkRange(numValue)) { return false; }
      break;
    case "date":
      if (! this.checkType(value)) { return false; }
      break;
    case "email":
      if (! this.checkType(value)) { return false; }
      break;
  }

  return true;
}

function checkType(value) {

  switch (this.type) {

    case "integer":

      var pattern = /^\d+$/;
      if (! pattern.exec(value)) {
        this.message = "'" + value + "' is not a valid integer.";
        return false;
      }
      break;

    case "number":

      var numPattern = /^(\d+(\.\d*)?|\.\d+)$/;

      if (! numPattern.exec(value)) {
        this.message = "'" + value + "' is not a valid number.";
        return false;
      }

      if (this.decimalPlaces) {
        numPattern = new RegExp("^(\\d+(\\.\\d{0," + this.decimalPlaces +
                                "})?|\\.\\d{1," + this.decimalPlaces + "})$");
        if (! numPattern.exec(value)) {
          this.message = "'" + value + "' has more than " +
          this.decimalPlaces + " digits after the decimal point.";
          return false;
        }
      }
      break;

    case "date":

      var datePattern = /\d{1,2}\/\d{1,2}\/\d\d\d\d/;
      if (! datePattern.exec(value)) {
        this.message = "'" + value + "' is not a valid date (MM/dd/YYYY).";
        return false;
      }
      break;

    case "email":

      if (! checkEmailValue(value)) {
        this.message = "'" + value + "' is not a valid e-mail address.";
        return false;
      }
      break;
  }

  return true;
}

function checkRange(value) {

  var nVal = parseFloat(value);

  if (this.minValue) {

    var nMin = parseFloat(this.minValue);

    if (! this.minBound) this.minBound = "ge";

    if (this.minBound == "gt" && nVal <= nMin) {
      this.message = "Value must be greater than " + this.minValue + ".";
      return false;
    }

    if (this.minBound == "ge" && nVal < nMin) {
      this.message = "Value must be greater than or equal to " +
                     this.minValue + ".";
      return false;
    }
  }

  if (this.maxValue) {

    var nMax = parseFloat(this.maxValue);

    if (! this.maxBound) this.maxBound = "le";

    if (this.maxBound == "lt" && nVal >= nMax) {
      this.message = "Value must be less than " + this.maxValue + ".";
      return false;
    }

    if (this.maxBound == "le" && nVal > nMax) {
      this.message = "Value must be less than or equal to " +
                     this.maxValue + ".";
      return false;
    }
  }

  return true;
}

function checkLength(value) {

  var length = value.length;

  if (this.minLength && length < this.minLength) {
    this.message =
      "Value cannot be less than " + this.minLength + " characters long.";
    return false;
  } 

  if (this.maxLength && length > this.maxLength) {
    this.message =
      "Value cannot be more than " + this.maxLength + " characters long.";
    return false;
  } 

  return true;
}

function checkChars(value) {

  if (! this.allowChars) { return true; }

  var chars = this.allowChars.split(",");

  var isDigit = false;
  var isLetter = false;
  var isSpace = false;

  for (var i = 0; i < chars.length; i++) {
    var c = chars[i];
    if (c == 'digit') {
      isDigit = true;
    } else if (c == 'space') {
      isSpace = true;
    } else if (c == 'letter') {
      isLetter = true;
    }
  }

  var digPat = /\d/;
  if (! isDigit && value.search(digPat) != -1) {
    this.message = "Value cannot contain digits.";
    return false;
  }

  var spacePat = /\s/;
  if (! isSpace && value.search(spacePat) != -1) {
    this.message = "Value cannot contain spaces.";
    return false;
  }

  return true;
}

function toString() {

  var s = "";
  var i = 0;

  for (var name in this) {
    var value = this[name];
    if (! value || value instanceof Function) { continue; }
    if (i++ > 0) { s += ";"; }
    s += name + ":" + value;
  }

  return s;  
}

function validateForm(formName) {

  var form = document.forms[formName];
  if (! form) { 
    alert("No form named '" + formName + "' to validate.");
    return; 
  }

  var elements = form.elements;

  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    if (element.tagName == "INPUT" &&
        (element.type == "hidden" || element.type == "submit")) {
      continue;
    }

    if (! element.validation) { continue; }

    var validator = createValidator(element.validation);
    validator.label = element.title ? element.title : element.name;

    if (! validator.validate(element.value)) {
      alert(validator.message);
      element.focus();
      event.returnValue = false;
      return false;
    }
  }

  return true;
}

function highlightForm(formName) {

  var form = document.forms[formName];

  if (! form) { 
    alert("No form named '" + formName + "' to validate.");
    return; 
  }

  var elements = form.elements;

  for (var i = 0; i < elements.length; i++) {

    var element = elements[i];

    if (element.tagName == "TEXTAREA") {
      element.innerText = trimString(element.innerText);
    }

    if (! element.validation) { continue; }

    var validator = createValidator(element.validation);

    if (validator.required) {
      element.style.border = "2 inset red";
    }

    if (validator.standard && window.user && validator.defaultRule == "user") {
      
      if (window.user[validator.standard]) {
        element.value = window.user[validator.standard];
      }
    }
  }
}

function createValidator(parameterString) {

  var validator = new Validator("text", false);

  var params = parameterString.split(";");
  for (var i = 0; i < params.length; i++) {
    var param = params[i].split(":");
    validator[param[0]] = param[1];
  }

  return validator;
}

function objectToString(object) {

  var s = "";
  var i = 0;

  for (var name in object) {
    var value = object[name];
    if (! value || value instanceof Function) { continue; }
    if (i++ > 0) { s += ";"; }
    s += name + ":" + value;
  }

  return s;
}

function trimString(s) {

  s = s.replace(/^\s*(.*)/, "$1");
  s = s.replace(/(.*?)\s*$/, "$1");

  return s;
}

/**
 * Updates the element label in the common situation where
 * a 2-column table is used to layout the form.
 **/
function updateLabel(element, label) {

   var cell = element.parentNode;
   if (cell.tagName == "TD" && cell.previousSibling) {
     cell = cell.previousSibling;
     if (cell.innerHTML && cell.innerHTML == "&nbsp;" ||
         cell.innerHTML == element.title) {
       cell.innerHTML = label;
     }
   }
}

function setFieldName(label, formName) {

  if (! label) { return; }

  var name = getValue(formName, "name");
  if (name != "" && ! name.match(/^field/)) { return; }

  name = labelToName(label);

  setValue(formName, "name", name);
}

function labelToName(label) {

  var name = label.toLowerCase();
  name = name.replace(/\s/g, "_");
  name = name.replace(/\W/g, "");

  return name;
}

function labelToFileName(label) {

  var name = label.toLowerCase();
  name = name.replace(/\s/g, "-");
  name = name.replace(/[^a-zA-Z0-9-]/g, "");

  return name;
}

function tabToElement(formName, tabIndex) {

  var elements = document.forms[formName].elements;

  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    if (element.tabIndex == tabIndex) {
      element.focus();
      break;
    }
  }
}

function showContextHelp(contextPath, path) {

  path = contextPath + "/admin/help/context/" + path + ".html";
  helpWin = window.showHelp(path);
}


