var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz' "
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ' "

var whitespace = " \t\n\r";

var decimalPointDelimiter = ".";
var signNumberDelimiter = "+-";

var phoneNumberDelimiters = "()- ";
var ZIPCodeDelimiters = "-";
var CAZIPCodeDelimiters = " ";


var validUSPhoneChars = digits + phoneNumberDelimiters;
var validWorldPhoneChars = digits + phoneNumberDelimiters + "+";
var validZIPCodeChars = digits + ZIPCodeDelimiters;

var digitsInUSPhoneNumber = 10;
var digitsInZIPCode1 = 5;
var digitsInZIPCode2 = 9;
var digitsInCAZIPCode = 6;

// Variables for stuff that's missing
var mPrefix = " Please enter your ";
var mPrefixA = " Please select: ";
var mSuffix = ".\n";
var mSuffixA = "\n";

// Strings
var sUSLastName = "Last Name";
var sUSFirstName = "First Name";
var sWorldLastName = "Family Name";
var sWorldFirstName = "Given Name";
var sTitle = "Title";
var sCompanyName = "Company Name";
var sUSAddress = "Street Address";
var sWorldAddress = "Address";
var sCity = "City";
var sStateCode = "State Code";
var sWorldState = "State, Province, or Prefecture";
var sCountry = "Country";
var sZIPCode = "ZIP Code";
var sWorldPostalCode = "Postal Code";
var sPhone = "Phone Number";
var sFax = "Fax Number";
var sEmail = "Email";
var sOtherInfo = "Other Information";

// Prompts calling out invalid information
var iThe = "The ";
var iReenter = "Please re-enter.\n";
var iStateCode = " field must be a valid two character U.S. state abbreviation (like CA for California).  " + iReenter;
var iZIPCode = " field must be a 5 or 9 digit U.S. ZIP Code (like 94043).  " + iReenter;
var iCAZIPCode = " field must be a 7 character Canadian ZIP Code (like G0L 4A0).  " + iReenter;
var iPostalCode = " field must be alphanumeric.  " + iReenter;
var iUSPhone = " field must be a 10 digit U.S. phone number (like 415 555 1212).  " + iReenter;
var iEmail = " field must be a valid email address (like user@domain.com).  " + iReenter;

// Prompts for information
var pEntryPrompt = "Please enter a ";
var pStateCode = "2 character code (like CA).";
var pZIPCode = "5 or 9 digit U.S. ZIP Code (like 94043).";
var pCAZIPCode = "7 character Canadian ZIP Code (like G0L 4A0).";
var pUSPhone = "10 digit U.S. phone number (like 415 555 1212).";
var pEmail = "valid email address (like user@domain.com).";

var USStateCodeDelimiter = "|";
var USStateCodes = "AL|AK|AS|AZ|AR|CA|CO|CT|DE|DC|FM|FL|GA|GU|HI|ID|IL|IN|IA|KS|KY|LA|ME|MH|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|MP|OH|OK|OR|PW|PA|PR|RI|SC|SD|TN|TX|UT|VT|VI|VA|WA|WV|WI|WY|AE|AA|AE|AE|AP";

var defaultEmptyOK = false;  //set to False to make information required
/*  ================================================================ */
function makeArray(n) {
//   this.length = n;
   for (var i = 1; i <= n; i++) {
      this[i] = 0;
   } 
   return this;
}
/*  ================================================================ */
function checkSign(s) {
  var c = s.charAt(0);
  if (signNumberDelimiter.indexOf(c) != -1)
    return 1;
  else
    return 0;    
}
/*  ================================================================ */
function isEmpty (s)         { return ((s == null) || (s.length == 0)); }
function isLetter (c)        { return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) || (c == ' ') ); }
function isDigit (c)         { return ((c >= "0") && (c <= "9")); }
function isLetterOrDigit (c) { return (isLetter(c) || isDigit(c)); }
/*  ================================================================ */
function isWhitespace (s) {
  if (isEmpty(s)) return true;
  for (var i = 0; i < s.length; i++) {
    var c = s.charAt(i);
    if (whitespace.indexOf(c) == -1) return false;
  }
  return true;
}
/*  ================================================================ */
function isInteger (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  
  for (var i = 0; i < s.length; i++) {
    var c = s.charAt(i);
    if (!isDigit(c)) return false;
  }
  return true;
}
/*  ================================================================ */
function isSignedInteger (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  return (isInteger(s.substring(checkSign(s), s.length), r) );
}
/*  ================================================================ */
function isPositiveInteger (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r
  return (isSignedInteger(s, r) && (parseInt (s) > 0) );
}
/*  ================================================================ */
function isFloat (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r
  if (s == decimalPointDelimiter) return false;

  var seenDecimalPoint = false;
  for (var i = 0; i < s.length; i++) {   
    var c = s.charAt(i);

    if ((c == decimalPointDelimiter) && !seenDecimalPoint) 
      seenDecimalPoint = true;
    else if (!isDigit(c)) 
      return false;
  }
  return true;
}
/*  ================================================================ */
function isSignedFloat (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  return (isFloat(s.substring(checkSign(s), s.length), r))
}
/*  ================================================================ */
function isAlphabetic (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;

  for (var i = 0; i < s.length; i++) {   
    var c = s.charAt(i);
    if (!isLetter(c))
      return false;
  }
  return true;
}
/*  ================================================================ */
function isAlphanumeric (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;

  for (var i = 0; i < s.length; i++) {   
    var c = s.charAt(i);
    if (! isLetterOrDigit(c) )
      return false;
  }
  return true;
}
/*  ================================================================ */
function isSSN (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  return (isInteger(s) && s.length == digitsInSocialSecurityNumber)
}
/*  ================================================================ */
function isUSPhoneNumber (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  return (isInteger(s) && s.length == digitsInUSPhoneNumber)
}
/*  ================================================================ */
function isInternationalPhoneNumber (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  return (isPositiveInteger(s))
}
/*  ================================================================ */
function isZIPCode (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  return (isInteger(s) && ((s.length == digitsInZIPCode1) || (s.length == digitsInZIPCode2)))
}
/*  ================================================================ */
function isCAZIPCode (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;

  var b = true;
  for (var i = 0; i < s.length; i++) {   
    var c = s.charAt(i);
    if (b) {
      if (! isLetter(c))
        return false;
    } else {
      if (! isDigit(c))
        return false;
    }
    b = !b;
  }

  return (s.length == digitsInCAZIPCode)
}
/*  ================================================================ */
function isStateCode(s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  return ( (USStateCodes.indexOf(s) != -1) && (s.indexOf(USStateCodeDelimiter) == -1) )
}
/*  ================================================================ */
function isEmail (s, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  if (isWhitespace(s)) return false;
    
  // there must be >= 1 character before @, so we start looking at character position 1
  var i = 1;
  var sLength = s.length;

  // look for @
  while ((i < sLength) && (s.charAt(i) != "@")) { i++ }

  if ((i >= sLength) || (s.charAt(i) != "@")) 
    return false;
  else 
    i += 2;

  // look for .
  while ((i < sLength) && (s.charAt(i) != ".")) { i++ }

  // there must be at least one character after the .
  if ((i >= sLength - 1) || (s.charAt(i) != ".")) 
    return false;
  else 
    return true;
}
/*  ================================================================ */
function isIntegerInRange (s, a, b, r) {
  if (r == null) { r = defaultEmptyOK; }
  if (isEmpty(s)) return r;
  if (!isInteger(s, false)) return false;

  var num = parseInt (s);
  return ((num >= a) && (num <= b));
}
/*  ================================================================  */
function stripCharsInBag (s, bag) {
  var returnString = "";
  for (var i = 0; i < s.length; i++) {
    var c = s.charAt(i);
    if (bag.indexOf(c) == -1) returnString += c;
  }
  return returnString;
}
/*  ================================================================ */
function stripCharsNotInBag (s, bag) {
  var returnString = "";
  for (var i = 0; i < s.length; i++) {
    var c = s.charAt(i);
    if (bag.indexOf(c) != -1) returnString += c;
  }
  return returnString;
}
/*  ================================================================ */
function stripWhitespace (s)        { return stripCharsInBag (s, whitespace); }
/*  ================================================================ */
function charInString (c, s) { 
  for (i = 0; i < s.length; i++) { if (s.charAt(i) == c) return true; }
  return false;
}
/*  ================================================================ */
function stripInitialWhitespace (s) {
  for (var i = 0; i < s.length; i++) { if (whitespace.indexOf(s.charAt(i)) != -1) break; }
  return s.substring (i, s.length);
}
/*  ================================================================ */
function reformat (s) {   
  var arg;
  var sPos = 0;
  var resultString = "";

  for (var i = 1; i < reformat.arguments.length; i++) {
    arg = reformat.arguments[i];
    if (i % 2 == 1) 
      resultString += arg;
    else {
      if (sPos <= s.length) {
        var l = sPos + arg
        if (l > s.length) {
          resultString += s.substring(sPos, s.length);
          for (var j = 1; j <= arg - (s.length - sPos); j++) {
            resultString += ' ';
          }
        } else {
          resultString += s.substring(sPos, sPos + arg);
        } 
        sPos = l; //+= arg;
      } else {
        for (var j = 1; j <= arg; j++) {
          resultString += ' ';
        }
      }
    }
  }
  return resultString;
}
/*  ================================================================ */
function reformatZIPCode (s) {
  if (s.length == 5) 
    return s;
  else 
    return (reformat (s, "", 5, "-", 4));
}
/*  ================================================================ */
function reformatCAZIPCode (s) { return (reformat (s, "", 3, " ", 3)) }
function reformatUSPhone (s) { return (reformat (s, "", 3, "-", 3, "-", 4)) }
function reformatSSN (s)     { return (reformat (s, "", 3, "-", 2, "-", 4)) }
/*  ================================================================  */
function prompt (s)          { window.status = s; }
function promptEntry (s)     { window.status = pEntryPrompt + s; }
function warnError (f, s, m) {   
  f.focus();
  alert(m); //mPrefix + s + mSuffix);
  return false;
}
/*  ================================================================ */
function checkAndWarn (f, n, func, r) {
  if (r == null) { r = defaultEmptyOK; }
  var res = func(f, n);
  if (res != '') { 
    warnError (f, n, res);
    return false;
  }
  return true;
}
/*  ================================================================ */
function checkNumeric (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  if (!isInteger(f.value)) return mPrefix + n + mSuffix;
  return '';
}
/*  ================================================================ */
function checkAlphabetic (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  if (!isAlphabetic(f.value)) return mPrefix + n + mSuffix;
  return '';
}
/*  ================================================================ */
function checkString (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  if (isWhitespace(f.value)) return mPrefix + n + mSuffix;
  return '';
}
/*  ================================================================ */
function checkStateCode (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  s = s.toUpperCase();
  if (!isStateCode(s)) return iThe + n + iStateCode;
  return '';
}
/*  ================================================================ */
function checkZIPCode (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  s = stripCharsInBag(s, ZIPCodeDelimiters)
  if (!isZIPCode(s)) return iThe + n + iZIPCode;
  f.value = reformatZIPCode(s)
  return '';
}
/*  ================================================================ */
function checkCAZIPCode (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  s = stripCharsInBag(s, CAZIPCodeDelimiters)
  if (!isCAZIPCode(s)) return iThe + n + iCAZIPCode;
  f.value = reformatCAZIPCode(s)
  return '';
}
/*  ================================================================ */
function checkPostalCode (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  if (!isAlphanumeric(s)) return iThe + n + iPostalCode;
  return '';
}
/*  ================================================================ */
function checkUSPhone (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  var s = stripCharsInBag(s, phoneNumberDelimiters)
  if (!isUSPhoneNumber(s)) return iThe + n + iUSPhone;
  f.value = reformatUSPhone(s)
  return '';
}
/*  ================================================================ */
function checkInternationalPhone (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  var s = stripCharsInBag(s, phoneNumberDelimiters)
  if (!isInternationalPhoneNumber(s)) return iThe + n + iWorldPhone;
  return '';
}
/*  ================================================================ */
function checkEmail (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
  var s = f.value;
  if (isEmpty(s)) {
    if (r)
      return '';
    else
      return mPrefix + n + mSuffix;
  }
  if (!isEmail(s)) return iThe + n + iEmail;
  return '';
}
/*  ================================================================ */
function checkSelectedIndex (f, n, r) {
  if (r == null) { r = defaultEmptyOK; }
//  var i = f.options[f.selectedIndex].value;
  var i = f.selectedIndex;
  if (i == 0) {
    if (r)
      return '';
    else
      return mPrefixA + n + mSuffixA;
  }
  return '';
}
/*  ================================================================ */
function checkQuestions (q, m, r) {
  var s = '';
  var count = 0;
  var n ;

  for (var i = 3; i < checkQuestions.arguments.length; i++) {
    var item = checkQuestions.arguments[i];

    n = (item.name + '*').substring(0, 1);

    if (n == 'c') { if (item.checked) count += 1; }
    if (n == 'r') { if (item.checked) count += 1; }
    if ((n == 'u') || (n == '*')) {
      for (var j = 0; j < item.length; j++) {
        if (item[j].checked) { 
          count += 1;
          break; 
        }
      }
    }
    if ((n == 'x') || (n == 't')) { if (!isWhitespace(item.value)) count += 1; }
    
  }
  if (r && (count == 0))
    s += ' Please answer: ' + q + '\n';
  if (count > m)
    s += 'You may only have ' + m + ' answer(s) for ' + q + '\n';
  return s
}
/*  ================================================================ */
function checkQuestionAnswered () {
  var n ;

  for (var i = 0; i < checkQuestionAnswered.arguments.length; i++) {
    var item = checkQuestionAnswered.arguments[i];

    n = (item.name + '*').substring(0, 1);

    if (n == 'c') { if (item.checked) return true; }
    if (n == 'r') { if (item.checked) return true; }
    if ((n == 'u') || (n == '*')) {
      for (var j = 0; j < item.length; j++) {
        if (item[j].checked) { return true; }
      }
    }
    if ((n == 'x') || (n == 't')) { if (!isWhitespace(item.value)) return true; }
  }
  return false;
}
/*  ================================================================ */
function getRadioButtonValue (r) {
  for (var i = 0; i < r.length; i++) { 
    if (r[i].checked) { break; }
  }
  return r[i].value;
}

