function obtainTargetArray(language, typeArray, msgArray) {
  var messageArray =
  [["english","Please correct the following problems:\n","-- more --",
    ["text", "Cannot be blank"],
    ["word", "Check your entry"],
    ["words", "Check your entry"],
    ["checkbox", "Please select at least one"],
    ["radio", "Please check one"],
    ["select", "Please make at least one selection"],
    ["phone", "Invalid phone number"],
    ["intphone", "Invalid phone number"],
    ["email", "Invalid e-mail address"],
    ["zip", "Invalid zip code"],
    ["card", "Invalid credit card number"],
    ["pin", "Must be at least 4 digits"],
    ["alphanumeric", "Invalid entry"],
    ["numeric", "Invalid entry"],
    ["date", "Check your entry"],
    ["username", "Must be less than 20 characters and contain no spaces, special characters or quotation marks"],
    ["pwd", "Must be 1 - 16 characters long and begin with a letter"],
    ["cvv2", "Please enter your card validation code"]],
   ["dutch","Corrigeer de volgende problemen:\n","-- more --",
    ["text", "Ongeldige invoer"],
    ["word", "Controleer uw invoer"],
    ["words", "Controleer uw invoer"],
    ["checkbox", "Selecteer minstens 1 waarde"],
    ["radio", "Kruis 1 waarde aan"],
    ["select", "Maak minstens 1 keuze"],
    ["phone", "Ongeldig telefoonnummer"],
    ["intphone", "Ongeldig telefoonnummer"],
    ["email", "Ongeldig e-mailadres"],
    ["zip", "Ongeldige postcode"],
    ["card", "Ongeldig creditcardnummer"],
    ["pin", "Ongeldige PIN"],
    ["alphanumeric", "Controleer uw invoer"],
    ["numeric", "Ongeldige invoer"],
    ["date", "Controleer uw invoer"],
    ["username", "Uw wachtwoord moet 1 tot 20 tekens bevatten."],
    ["pwd", "Uw wachtwoord moet 1 tot 16 tekens bevatten."],
    ["cvv2", "Gelieve de valideringscode van uw kaart in te voeren"]],
   ["french","Veuillez corriger suivants les problèmes:\n","-- plus --",
    ["text", "Saisie incorrecte"],
    ["word", "Vérifiez votre saisie"],
    ["words", "Vérifiez votre saisie"],
    ["checkbox", "Veuillez faire une sélection"],
    ["radio", "Veuillez cocher une option"],
    ["select", "Veuillez faire une sélection"],
    ["phone", "Numéro de téléphone incorrect"],
    ["intphone", "Numéro de téléphone incorrect"],
    ["email", "Adresse électronique incorrecte"],
    ["zip", "Code postal incorrect"],
    ["card", "INuméro de carte de crédit incorrect"],
    ["pin", "Code incorrect"],
    ["alphanumeric", "Vérifiez votre saisie"],
    ["numeric", "Saisie incorrecte"],
    ["date", "Vérifiez votre saisie"],
    ["username", "Cela doit être un seul mot composant entre 1 et 20 caractères."],
    ["pwd", "Cela doit être un seul mot composant entre 1 et 16 caractères."],
    ["cvv2", "Veuillez saisir votre code de validation de carte"]],
   ["german","Beheben Sie bitte die folgenden Probleme:\n","-- mehr --",
    ["text", "Ungültige Eingabe"],
    ["word", "Prüfen Sie ihre Eingabe"],
    ["words", "Prüfen Sie ihre Eingabe"],
    ["checkbox", "Mindestens eine Auswahl erforderlich"],
    ["radio", "Bitte wählen Sie eine Option"],
    ["select", "Mindestens eine Auswahl erforderlich"],
    ["phone", "Ungültige Telefonnummer"],
    ["intphone", "Ungültige Telefonnummer"],
    ["email", "Ungültige eMail-Adresse"],
    ["zip", "Ungültige Postleitzahl"],
    ["card", "ngültige Kreditkartennummer"],
    ["pin", "Ungültige PIN"],
    ["alphanumeric", "Prüfen Sie ihre Eingabe"],
    ["numeric", "Ungültige Eingabe"],
    ["date", "Prüfen Sie ihre Eingabe"],
    ["username", "Es muss ein Wort mit 1 - 20 Zeichen sein."],
    ["pwd", "Es muss ein Wort mit 1 - 16 Zeichen sein."],
    ["cvv2", "Bitte geben Sie Ihren Kartenbestätigungscode ein"]],
   ["italian","Correggere prego i seguenti problemi:\n","-- più --",
    ["text", "Dati immessi non validi"],
    ["word", "Verifica i dati immessi"],
    ["words", "Verifica i dati immessi"],
    ["checkbox", "Scegli almeno una voce"],
    ["radio", "Spunta una voce"],
    ["select", "Effettua almeno una scelta"],
    ["phone", "Numero di telefono non valido"],
    ["intphone", "Numero di telefono non valido"],
    ["email", "Indirizzo e-mail non valido"],
    ["zip", "Codice di avviamento postale non valido"],
    ["card", "Numero di carta di credito non valido"],
    ["pin", "PIN non valido"],
    ["alphanumeric", "Verifica i dati immessi"],
    ["numeric", "Dati immessi non validi"],
    ["date", "Verifica i dati immessi"],
    ["username", "La lunghezza della password deve essere compresa tra 1 e 20 caratteri."],
    ["pwd", "La lunghezza della password deve essere compresa tra 1 e 16 caratteri."],
    ["cvv2", "Immettere il codice di verifica della carta di credito"]],
   ["portuguese","Corrija por favor os seguintes problemas:\n","-- mais --",
    ["text", "Entrada inválida"],
    ["word", "Verifique seus dados de entrada"],
    ["words", "Verifique seus dados de entrada"],
    ["checkbox", "Marque uma opção"],
    ["radio", "Faça ao menos uma escolha"],
    ["select", "Selecione ao menos uma opção"],
    ["phone", "Número de telefone inválido"],
    ["intphone", "Número de telefone inválido"],
    ["email", "Endereço eletrônico inválido"],
    ["zip", "CEP incorreto"],
    ["card", "Número de cartão de crédito incorreto"],
    ["pin", "Senha incorreta"],
    ["alphanumeric", "Verifique seus dados de entrada"],
    ["numeric", "Entrada inválida"],
    ["date", "Verifique seus dados de entrada"],
    ["username", "Deve ser uma palavra entre 1 e 20 caracteres."],
    ["pwd", "Deve ser uma palavra entre 1 e 16 caracteres."],
    ["cvv2", "Digite o código de validação do seu cartão"]],
   ["spanish","Corrija por favor siguientes los problemas:\n","-- más --",
    ["text", "Valor no válido"],
    ["word", "Verifique el valor ingresado"],
    ["words", "Verifique el valor ingresado"],
    ["checkbox", "Seleccione al menos uno"],
    ["radio", "Marque uno"],
    ["select", "Efectúe al menos una selección"],
    ["phone", "Número de teléfono no válido"],
    ["intphone", "Número de teléfono no válido"],
    ["email", "Dirección de correo electrónico no válida"],
    ["zip", "Código postal no válido"],
    ["card", "Número de tarjeta de crédito no válido"],
    ["pin", "Contraseña no válida"],
    ["alphanumeric", "Verifique el valor ingresado"],
    ["numeric", "Valor no válido"],
    ["date", "Verifique el valor ingresado"],
    ["username", "Debe ser una sola palabra de entre 1 y 20 caracteres."],
    ["pwd", "Debe ser una sola palabra de entre 1 y 16 caracteres."],
    ["cvv2", "Introduzca el código de validación de su tarjeta"]],
   ["swedish","Please correct the following problems:\n","-- more --",
    ["text", "Ogiltigt värde"],
    ["word", "Kontrollera det du skrev in"],
    ["words", "Kontrollera det du skrev in"],
    ["checkbox", "Markera minst en"],
    ["radio", "Markera en"],
    ["select", "Välj minst en"],
    ["phone", "Ogiltigt telefonnummer"],
    ["intphone", "Ogiltigt telefonnummer"],
    ["email", "Ogiltig e-postadress"],
    ["zip", "Ogiltigt postnummer"],
    ["card", "Ogiltigt kreditkortsnummer"],
    ["pin", "Ogiltig PIN-kod"],
    ["alphanumeric", "Kontrollera det du skrev in"],
    ["numeric", "Ogiltigt värde"],
    ["date", "Kontrollera det du skrev in"],
    ["username", "Must be one word between 1 and 20 Characters"],
    ["pwd", "Must be one word between 1 and 16 Characters"],
    ["cvv2", "Ange kortets valideringskod"]]];

  // pick the array to be used
  languageUsed = language.toLowerCase();
  for (var i = 1; i < messageArray.length; i++)
    if (messageArray[i][0] == languageUsed) return messageArray[i];
  return messageArray[0]; // default language is "English"
}

function finalizeMsgArray(toBeArray, typeArray, lookUpArray) { // as of 04/19/00 hku
  var type;
  for (var k=0; k<toBeArray.length; k++)
    if (toBeArray[k] == null || toBeArray[k] == "") {
      type = typeArray[k];
      for (var j=3; j<lookUpArray.length; j++)
        if (type == lookUpArray[j][0]) { toBeArray[k] = lookUpArray[j][1]; break; }
    }
  return toBeArray;
} // finalizeMsgArray()

function validateField() {
  // as of 10/3/00 hku *** Display alert message(if any), then return a boolean ***
  var message = fieldValidate(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6]);
  if (message == "") return true;
  alert(message); return false;
} // validateField()

function fieldValidate(formNum, fields, types, language, friendlyNames, messageArray, maxMsgs) {
  /* rewritten by AF 7/3/01
  as of 10/3/00 hku *** Return a string for display and/or additional retouch *** */
  if (formNum == null || formNum == "") formNum = 0;
  var form = document.forms[formNum];
  if (language == null || language == "") language = "English";

  if (typeof messageArray == "undefined" || messageArray == "")
    messageArray = new Array();
  messageArray.length = types.length;

  var infoArray = new Array();
  infoArray = obtainTargetArray(language, types, messageArray);
  messageArray = finalizeMsgArray(messageArray, types, infoArray);
  var alertPromptHeader = infoArray[1];
  var alertPromptMore = infoArray[2];
  if (typeof maxMsgs == "undefined" || maxMsgs == "" || isNaN(maxMsgs) || maxMsgs > fields.length)
    maxMsgs = fields.length;

  var msgs = new Array();
  var focusObj = "";
  var error = false;

  for (var i=0; i<fields.length; i++) {
    error = false; // re-initialize each time
    var trimTypes = "text, word, words, phone, intphone, email, zip, card, alphanumeric, numeric, " +
      "date, username, pwd, cvv2";
    if (trimTypes.indexOf(types[i]) > -1) trim(eval("form." + fields[i]));
    switch (types[i]) {
      case "text": // non-whitespace character
        var str = remove(eval("form." + fields[i] + ".value"), " ");
        if (str.length < 1 || badWord(str)) error = true;
        break;
      case "word":
      case "words":
        var str = eval("form." + fields[i] + ".value");
        var chkStr = "-.'"; if (types[i] == "words") chkStr += " "; // allow space if words
        if (!validWord(str, 1, chkStr)) error = true;
        break;
      case "checkbox":
        if (!checkboxChecked(formNum, fields[i])) error = true;
        else showNormImage(fields[i]);
        break;
      case "radio":
        var checked = false;
        for ( var j=0; j< eval("form."+fields[i]+".length"); j++)
          if (eval("form." + fields[i] + "["+j+"].checked")) checked = true;
        if (!checked) error = true;
        break;
      case "select":
        var temp = eval("form." + fields[i] + ".selectedIndex");
        if (temp == -1) { 
          error = true; break;
        }
        var tempValue = eval("form."+fields[i]+".options["+temp+"].value");
        if ( tempValue == "") error = true;
        break;
      case "phone":
        var usphonefield = eval("form." + fields[i]);
        usphonefield.value = remove(usphonefield.value, ".");
        if (!USphoneVerified(usphonefield.value)) error = true;
        break;
      case "intphone": // validation for international phones
        var intphonefield = eval("form." + fields[i]);
        intphonefield.value = remove(intphonefield.value, ".");
        var str = remove(intphonefield.value, "()- ");
        if (str.length < 3 || str.length > 20 || !find(str, "0123456789")) error = true;
        break;
      case "email":
        var str = eval("form." + fields[i] + ".value");
        // var regExp = /^([a-z0-9])+([-_.]*[a-z0-9]*)*@([a-z0-9])+([-_]*[a-z0-9])*\.([a-z]{2,3})$/i;
        if (!validEmail(str)) error = true;
        break;
      case "zip":
        var str = remove(eval("form." + fields[i] + ".value"), " -");
        if (!find(str, "0123456789") || (str.length != 5 && str.length != 9)) error = true;
        break;
      case "card":
        var CCNo = remove(eval("form." + fields[i] + ".value"), " -"); // remove spaces and dashes
        // check entry, verify Mod 10 and make sure CCNo matches CC type
        if (!find(CCNo, "0123456789") || !(CCNo.length >= 13 && CCNo.length <= 16) ||
            !Mod10Verified(CCNo) || !ccNameVerified(CCNo, form.CCName.options[form.CCName.selectedIndex].value))
          error = true;
        break;
      case "pin":
        var str = eval("form." + fields[i] + ".value");
        if (str.length != 4 && str.length != 5 || !find(str, "0123456789")) error = true;
        break;
      case "alphanumeric":
        var str = eval("form." + fields[i] + ".value");
        if (!validWord(str, 1, "0123456789 -")) error = true;
        break;
      case "numeric":
        var str = eval("form." + fields[i] + ".value");
        if (!find(str, "0123456789")) error = true;
        break;
      case "date":
        var str = eval("form." + fields[i] + ".value");
        if (!dateVerified(str)) error = true;
        break;
      case "username":
        var str = eval("form." + fields[i] + ".value.toLowerCase()");
        if (!(str.length >= 1 && str.length <= 20)) error = true;
        var chr = str.charCodeAt(0);
        if (!(chr >= 97 && chr <= 122)) error = true;
        for (var j = 0; j < str.length; j++) {
          chr = str.charCodeAt(j);
          if (!((chr >= 97 && chr <= 122) || // a-z
                (chr == 95) || (chr >= 48 && chr <= 57))) // _, 0 - 9
            error = true;
        }
        break;
      case "pwd":
        var str = eval("form." + fields[i] + ".value.toLowerCase()");
        if (!(str.length >= 1 && str.length <= 16)) error = true;
        var chr = str.charCodeAt(0);
        if (!(chr >= 97 && chr <= 122)) error = true;
        for (var j = 0; j < str.length; j++) {
          chr = str.charCodeAt(j);
	  if (!((chr >= 97 && chr <= 122)||  // a-z
                (chr >= 48 && chr <= 57) ||  // _, 0 - 9
                (chr >= 33 && chr <= 47) ||  // special characters
                (chr >= 58 && chr <= 64) ||  // special characters
                (chr >= 91 && chr <= 96) ||  // special characters
                (chr >= 123 && chr <= 126))) // special characters
          error = true;
        }
        break;
      case "cvv2":
        var CCName = form.CCName.options[form.CCName.selectedIndex].value.toLowerCase();
        var str = eval("form." + fields[i] + ".value");
        var validLength = 3;
        if (CCName == "american express") validLength = 4;
        if (find(str, "0123456789") && str.length == validLength) break;
        error = true;
        form.cvv2code.value = "";
        if (CCName == "visa") form.cvv2code.value = "1";
        break;
      default: break;
    } // switch(types[i])
    if (error) {
      msgs[msgs.length] = friendlyNames[i] + " .. " + messageArray[i];
      if (focusObj == "" && types[i] != "checkbox" && types[i] != "radio") focusObj = fields[i];
      showErrImage(fields[i]);
    } else showNormImage(fields[i]);

  } // end for
  if (msgs.length > maxMsgs) { 
    msgs[maxMsgs] = alertPromptMore; msgs.length = maxMsgs + 1;
  }

  var message = "";
  for (var k=0; k<msgs.length; k++) if (msgs[k] != "") message += "\n" + msgs[k];
  if (message != "") message = alertPromptHeader + message;
  if (focusObj != "") {
    var type = eval("form." + focusObj + ".type");
    if (type != "hidden" && type != "radio") eval("form." + focusObj + ".focus()");
  }
  return message;
} // fieldValidate()

function USphoneVerified(cbNum) {
  cbNum = remove(cbNum, "()- ");
  if (!find(cbNum, "0123456789")) return false;
  if (cbNum.substring(0,1) == "1")
    return(cbNum.length == 11 && cbNum.substring(2,4) != "11")
  return(cbNum.length >= 8 && cbNum.length <= 20)
}

function checkboxChecked(theForm, groupName) {
  // HKu 01/20/2000 - verifying if a chekbox group been checked
  var elements = document.forms[theForm].elements;
  for (var i=0; i<elements.length; i++)
    if (elements[i].type == "checkbox" && elements[i].name == groupName && elements[i].checked)
      return true;
  return false;
}

function Mod10Verified(newStr) {
  //YK - 05/25/1999 HKu Modified 05/11/2000 CC checks
  var jNum = newStr.length;
  var jName = new Array();
  var jSub = new Array();
  for (i = 0; i < jNum; i++) jName[i] = newStr.charAt(i); // create array of CC numbers
  var j = ((jNum == 16) || (jNum == 14)) ? 0 : 1;
  for (i = j; i < jNum; i += 2) {
    jSub[i] = jName[i] * 2;
    if (jSub[i] >= 10) {
      jz = jSub[i].toString();
      jx = parseFloat(jz.charAt(0)) + parseFloat(jz.charAt(1));
    } else jx = jSub[i];
    jName[i] = jx;
  }
  var value = 0;
  for (i = 0; i < jNum; i++) value += parseFloat(jName[i]);
  value=value.toString();
  return(value.charAt(1) != 0) ? false : true;
}

function ccNameVerified(lNum, lName) {
  // AF 6/18/01
  var num = parseFloat(lNum).toString();
  var chrNum = num.substr(0, 1);
  var name = lName.toLowerCase();
  if (chrNum == "3") {
    if (name == "american express" && num.length == 15) return true;
    if (name == "diners club" && num.length == 14 &&
        (num.substr(1, 1) == "6" || num.substr(1, 1) == "8")) return true;
  }
  if (chrNum == "4" && (num.length == 13 || num.length == 16) && name == "visa") return true;
  if (chrNum == "5" && num.length == 16 && name == "master card") return true;
  if (chrNum == "6" && num.length == 16 && name == "discover") return true;
  return false;
} // ccNameVerified()

function dateVerified(dateStr) {
  if (!dateStr.match(/^(1[0-2]|0?[1-9])\/(0?[1-9]|[12][0-9]|3[01])\/\d{1,4}$/)) return false;
  var monthEntered = dateStr.substring(0,dateStr.indexOf("/"));
  var thatDate = new Date(dateStr);
  var theMonth = thatDate.getMonth()+1;
  return(theMonth == monthEntered) ? true : false;
} // dateVerified(dateStr)

function badWord(str) {
  return false;
}

/* Accepts one argument which is a string to check and 2 optional arguments:
     minLen is making sure the min length is kept, if ommitted, it will take a length of zero
     valiChars is a string of valid characters to accept
   as many as necessary. These arguments will pass to the function which chrs are acceptable besides
   the ones predefined in this function (from ASCII table) those are a-z, A-Z, foreign and no other chrs
   Uses validChar()
   Examples:
      validWord("balobitar") --> true;
      validWord("balobitar1") --> false;
      validWord("balobitar 1", "1 ") --> true;
      validWord("balobitarÁ", "Á") --> true;
   This function also runs badWord()
   AF */
function validWord(str, minLen, validChars) {
  if (typeof minLen == "undefined") var minLen = 0;
  if (str.length < minLen || str.length > 30) return false; // 30 is max
  if (typeof validChars == "undefined") var validChars = "";
  for (var i = 0; i < str.length; i++)
    if (!validChar(str.charCodeAt(i), validChars)) return false;
  return !badWord(str);
} // validWord()

/* Checks chr against valid character defined in ASCII table.
   By default it allows A-Z, a-z and foreign chars.
   Also searches for match in validChars as a string.
   Examples:
      validChar("a") --> true
      validChar("a$", "$") --> true
   Accepts ASCII value of a single character.
   AF*/
function validChar(chr, validChars) {
  if (typeof validChars == "undefined") var validChars = "";
  // See if not found in ASCII table, then search for allowed chrs passed through validChars (if any)
  if ((chr >= 65 && chr <= 90) || (chr >= 97 && chr <= 122) || // A-Z or a-z
      (chr >= 192 && chr <= 214) || (chr >= 217 && chr <= 221) ||
      (chr >= 224 && chr <= 246) || (chr >= 249 && chr <= 255)) return true;
  for (var i = 0; i < validChars.length; i++)
    if (chr == validChars.charCodeAt(i)) return true;
  return false;
} // validChar()


/* Validates for email.
   Uses validChar() to check through each character for valid email.
   Also uses badWord() to check for invalid words.
   AF*/
function validEmail(str) {
  if (str.length < 6) return false; // min email is a@b.it
  if (str.indexOf("@") == -1) return false; // make sure the email contains @ sign
  if (str.indexOf("@", str.indexOf("@") + 1) > -1) return false; // make sure @ is not more than once
  if (!validChar(str.charCodeAt(0), "0123456789")) return false; // must start with a-z, 0-9 or foreign char defined in ASCII table

  for (var i = 1; i < str.indexOf("@"); i++) // 1st char is already validated. go until @ sign
    if (!validChar(str.charCodeAt(i), ".-_0123456789")) return false; // make sure all chars before @ are valid

    // make sure all chars between @ and last . are valid
  var lastDot = str.lastIndexOf(".");
  if (!validChar(str.charCodeAt(str.indexOf("@") + 1), "0123456789")) return false;
  for (var j = str.indexOf("@") + 2; j < lastDot - 1; j++)
    if (!validChar(str.charCodeAt(j), "-0123456789.")) return false;
  if (!validChar(str.charCodeAt(lastDot - 1), "0123456789")) return false;

  // top level domain is either 2 or 3 chars length
  if (str.length - lastDot - 1 < 2 || str.length - lastDot - 1 > 4) return false;

  // make sure top level domain is a-z
  for (var k = lastDot + 1; k < str.length; k++) {
    var chr = str.toLowerCase().charCodeAt(k);
    if (!(chr >= 97 && chr <= 122)) return false; // a-z
  }

  return !badWord(str);
} // validEmail()

/* Scans through str for chars.
   Returns boolean. If str is empty, returns false
   AF*/
function find(str, chars) {
  if (str.length == 0) return false;
  for (var i = 0; i < str.length; i++)
    if (chars.indexOf(str.charAt(i)) == -1) return false;
  return true;
} // find()

/* Removes chars from str.
   Returns cleaned str.
   AF*/
function remove(str, chars) {
  var newStr = "";
  for (var i = 0; i < str.length; i++)
    if (chars.indexOf(str.charAt(i)) == -1) newStr += str.charAt(i);
  return newStr;
} // remove()

/* Removes spaces before the str and after and updates the field.
   Returns nothing.
   AF*/
function trim(obj) {
  // remove all spaces in front
  var str = new String(obj.value);
  while (str.charAt(0) == " ")
    str = str.substring(1, str.length);
  // remove all spaces at the end
  while (str.charAt(str.length - 1) == " ")
    str = str.substring(0, str.length - 1);
  obj.value = str;
} // trim()

// AF
function existImage(imgName) { return document.images[imgName]; }

function showErrImage(imgName) {
  var errImage = new Image(15, 15);
  errImage.src = "/images/validate/error.gif";
  imgName = "img" + imgName;
  if (existImage(imgName)) document.images[imgName].src = errImage.src;
} // showErrImage()

// imgLocation is optional
function showNormImage(imgName, imgLocation) {
  var normImage = new Image(15, 15);
  normImage.src = "/images/validate/spacer.gif";
  if (imgLocation) normImage.src = imgLocation;
  imgName = "img" + imgName;
  if (existImage(imgName)) document.images[imgName].src = normImage.src;
} // showNormImage()
