  /****************************************************************************
  constants
  ****************************************************************************/
  var REG_INTEGER = /^\d+$/;
  var REG_FLOAT = /^\d*(\.\d+)?$/;
  var REG_ALPHA = /^[A-Za-z]+$/;
  var REG_ALPHA_NUM = /^[A-Za-z0-9]+$/;
  var REG_WHITE_SPACE = /^\s*$/;
  var REG_EMAIL = /^\S+@\S+\.\S+$/;
  var REG_DIGIT_GLOBAL = /\d/g;
  var CURR_SEPARATOR = '.';
  var CURR_UNIT = '$';
  var AMEX_PREFIX = new Array('34', '37');
  var AMEX_LENGTH = new Array('16');
  var VISA_PREFIX = new Array('4');
  var VISA_LENGTH = new Array('13', '16');
  var MCRD_PREFIX = new Array('51', '52', '53', '54', '55');
  var MCRD_LENGTH = new Array('16');
  var DISC_PREFIX = new Array('6011');
  var DISC_LENGTH = new Array('16');
  var DATE_SEPARATOR = '/';
  var PHONE_LENGTH_LONG = 10;
  var PHONE_LENGTH_SHORT = 7;
  var PHONE_AREA_BEGIN = '(';
  var PHONE_AREA_END = ') ';
  var PHONE_SEPARATOR = '-';
  var ZIP_LENGTH_LONG = 5;
  var ZIP_LENGTH_SHORT = 9;
  var ZIP_SEPARATOR = '-';
  var SSN_LENGTH = 9;
  var SSN_SEPARATOR = '-';

  /****************************************************************************
  function: isInteger
  purpose:  determine if a value is an integer
  inputs:   value - value to test
  outputs:  true if value is an integer, otherwise false
  ****************************************************************************/
  function isInteger(value){
    var regExp = REG_INTEGER;
    return (regExp.test(value));
  }
  
  /****************************************************************************
  function: isFloat
  purpose:  determine if a value is a float
  inputs:   value - value to test
  outputs:  true if value is a float, otherwise false
  ****************************************************************************/
  function isFloat(value){
    var regExp = REG_FLOAT;
    return (regExp.test(value));
  }
  
  /****************************************************************************
  function: isAlpha
  purpose:  determine if a value is alphabetic
  inputs:   value - value to test
  outputs:  true if value is alphabetic, otherwise false
  ****************************************************************************/
  function isAlpha(value){
    var regExp = REG_ALPHA;
    return (regExp.test(value));
  }
  
  /****************************************************************************
  function: isAlphaNum
  purpose:  determine if a value is alphanumeric
  inputs:   value - value to test
  outputs:  true if value is alphanumeric, otherwise false
  ****************************************************************************/
  function isAlphaNum(value){
    var regExp = REG_ALPHA_NUM;
    return (regExp.test(value));
  }
  
  /****************************************************************************
  function: isWhiteSpace
  purpose:  determine if a value is white space
  inputs:   value - value to test
  outputs:  true if value is white space, otherwise false
  ****************************************************************************/
  function isWhiteSpace(value){
    var regExp = REG_WHITE_SPACE;
    return (regExp.test(value));
  }
  
  /****************************************************************************
  function: isDate
  purpose:  determine if a value is a date
  inputs:   value - value to test
  outputs:  true if value is a date, otherwise false
  ****************************************************************************/
  function isDate(value){
    var dateCompare = new Date(value);
    if (! isNaN(dateCompare)){
      var splitDate = value.split(DATE_SEPARATOR);
      if (splitDate[2].length == 2)
        splitDate[2] = '19' + splitDate[2];
      return (dateCompare.getMonth() + 1 == splitDate[0] &&
              dateCompare.getDate() == splitDate[1] &&
              dateCompare.getFullYear() == splitDate[2]);
    }
    else
      return (false);
  }
  
  /****************************************************************************
  function: isEmail
  purpose:  determine if a value is an email address
  inputs:   value - value to test
  outputs:  true if value is an email address, otherwise false
  ****************************************************************************/
  function isEmail(value){
    var regExp = REG_EMAIL;
    return (regExp.test(value));
  }
  
  /**********************************************************************
  function: isPhone
  purpose:  determine if a value is a phone number
  inputs:   value - value to test
  outputs:  true if value (with all non-digit characters stripped) is a 
            phone number, otherwise false
  **********************************************************************/
  function isPhone(value){
    var phone = getCharacters(REG_DIGIT_GLOBAL, value);
    return (phone.length == PHONE_LENGTH_SHORT || phone.length == PHONE_LENGTH_LONG)
  }
  
  /**********************************************************************
  function: formatPhone
  purpose:  formats a string to a phone number
  inputs:   value - value to format
  outputs:  string formatted to a phone number
  **********************************************************************/
  function formatPhone(value){
    var phone = '';
    if (value.length == PHONE_LENGTH_LONG){
      phone += PHONE_AREA_BEGIN + value.substr(0, 3) + PHONE_AREA_END;
      phone += value.substr(3, 3) + PHONE_SEPARATOR + value.substr(6, 4);
    } else {
      phone += value.substr(0, 3) + PHONE_SEPARATOR + value.substr(3, 4);
    }
    return (phone);
  }
  
  /**********************************************************************
  function: isZip
  purpose:  determine if a value is a zip code
  inputs:   value - value to test
  outputs:  true if value (with all non-digit characters stripped) is a 
            float, otherwise false
  **********************************************************************/
  function isZip(value){
    var zip = getCharacters(REG_DIGIT_GLOBAL, value);
    return (zip.length == ZIP_LENGTH_SHORT || zip.length == ZIP_LENGTH_LONG);
  }
  
  /**********************************************************************
  function: formatZip
  purpose:  formats a string to a zip code
  inputs:   value - value to format
  outputs:  string formatted to a zip code
  **********************************************************************/
  function formatZip(value){
    var zip = value.substr(0, ZIP_LENGTH_SHORT);
    if (value.length == ZIP_LENGTH_LONG)
      zip += ZIP_SEPARATOR + value.substr(ZIP_LENGTH_SHORT, ZIP_LENGTH_LONG - ZIP_LENGTH_SHORT);
    return (zip);
  }
  
  /**********************************************************************
  function: isSSN
  purpose:  determine if a value is a Social Security Number
  inputs:   value - value to test
  outputs:  true if value (with all non-digit characters stripped) is a 
            float, otherwise false
  **********************************************************************/
  function isSSN(value){
    var ssn = getCharacters(REG_DIGIT_GLOBAL, value);
    return (ssn.length == SSN_LENGTH);
  }
  
  /**********************************************************************
  function: formatSSN
  purpose:  formats a string to a Social Security Number
  inputs:   value - value to format
  outputs:  string formatted to a Social Security Number
  **********************************************************************/
  function formatSSN(value){
    var ssn = '';
    ssn = value.substr(0, 3) + SSN_SEPARATOR + value.substr(3, 2) + SSN_SEPARATOR + value.substr(5, 4);
    return (ssn);
  }
  
  /**********************************************************************
  function: formatCurrency
  purpose:  formats a string to currency
  inputs:   value - value to format
  outputs:  string formatted to currency
  **********************************************************************/
  function formatCurrency(value, fracLen){
    var multiplier = Math.pow(10, fracLen);
    var decPos = 0;
    var lenToRight = 0;
    var lenToLeft = 0;
    var curr = 0;
    curr = (value * multiplier) + 0.5;
    curr = parseInt(curr, 10) / multiplier;
    curr = curr.toString(10);
    decPos = curr.indexOf(CURR_SEPARATOR);
    if (decPos > 0){
      lenToLeft = curr.substring(0, decPos).length;
      lenToRight = curr.substring(decPos + 1, curr.length).length;
    } else {
      lenToRight = 0;
      lenToLeft = curr.length;
    }
    if ((lenToRight == 0) && (decPos < 0) && (fracLen > 0))
      curr = curr + CURR_SEPARATOR;
    if (lenToLeft == 0)
      if (decPos >= 0)
        curr = '0' + curr;
      else if (fracLen > 0)
        curr = '0' + CURR_SEPARATOR + curr;
    if (fracLen > lenToRight)
      curr = curr + pad(fracLen - lenToRight, '0');
    return (CURR_UNIT + curr);
  }
  
  /**********************************************************************
  function: pad
  purpose:  pad a string with a quantity of a specified char
  inputs:   value - value to pad
  outputs:  value padded to the right with a quantity of a specfied char
  **********************************************************************/
  function pad(len, character){
    var padding = '';
    for(var i = 0; i < len; i++)
      padding += ('' + character);
    return (padding);
  }
  
  /**********************************************************************
  function: padLeft
  purpose:  pad a string with a quantity of a specified char
  inputs:   value - value to pad
  outputs:  value padded to the left with a quantity of a specfied char
  **********************************************************************/
  function padLeft(value, len, character){
    var padding = '';
    for (var i = 0; i < len; i++)
      padding += ('' + character);
    return (padding + '' + value);
  }
  
  /**********************************************************************
  function: reverse
  purpose:  reverses a string
  inputs:   value - value to reverse
  outputs:  reversed string
  **********************************************************************/
  function reverse(value){
    var str = '';
    var strLen = value.length;
    for (var i = strLen - 1; i >= 0; i--)
      str += ('' + value.charAt(i));
    return (str);
  }
  
  /**********************************************************************
  function: getCharacters
  purpose:  return the characters in a string that match a regular exp.
  inputs:   value - value to remove characters from
  outputs:  string containing only those characters matching regular exp.
  **********************************************************************/
  function getCharacters(regExp, target){
    var arr = null;
    var chars = '';
    arr = target.match(regExp);
    if (arr != null)
      for (var i = 0; i < arr.length; i++)
        chars += arr[i];
    return (chars);
  }
  
  /**********************************************************************
  function: isValidLUHN
  purpose:  return whether a number passes the LUHN test.
  inputs:   value - value to check
  outputs:  true if the value passes the test, otherwise false.
  **********************************************************************/
  function isValidLUHN(value){
    var len = value.length;
    var sum = 0;
    var num = 0;
    var i = 0;
    for (i = (len - 2); i >= 0; i -= 2){
      num = 2 * parseInt(value.charAt(i));
      if (num >= 10)
        sum += Math.floor(num / 10) + (num % 10);
      else
        sum += num;
    }

    for (i = (len - 1); i >= 0; i -= 2){
      sum += parseInt(value.charAt(i));
    }
    return ((sum % 10) == 0);
  }


  /**********************************************************************
  function: isValidPrefix
  purpose:  return whether a credit card number has a valid prefix.
  inputs:   value - value to check
  outputs:  true if the value passes the test, otherwise false.
  **********************************************************************/
  function isValidPrefix(prefixArr, ccNum){
    var len = prefixArr.length;
    var retVal = false;
    
    for (var i = 0; i < len; i++){
      if (parseInt(ccNum.substr(0, prefixArr[i].length)) == parseInt(prefixArr[i]))
        retVal = true;
    }
    return (retVal);
  }

  /**********************************************************************
  function: isValidLength
  purpose:  return whether a credit card number has a valid length.
  inputs:   value - value to check
  outputs:  true if the value passes the test, otherwise false.
  **********************************************************************/
  function isValidLength(lengthArr, ccNum){
    var len = lengthArr.length;
    var retVal = false;
    for (var i = 0; i < len; i++)
      if (ccNum.length == parseInt(lengthArr[i]))
        retVal = true;

    return (retVal);
  }


  /**********************************************************************
  function: isCreditCardNum
  purpose:  return whether a credit card number is potentially valid.
  inputs:   ccType - credit card type
            ccNum  - credit card number
  outputs:  true if the value is potentially a credit card number, 
            otherwise false.
  **********************************************************************/
  function isCreditCardNum(ccType, ccNum){
    var ccNumClean = getCharacters(REG_DIGIT_GLOBAL, ccNum);
    var retVal = false;
    var len = null;
    switch (ccType){
      case 'AMEX':
        len = AMEX_LENGTH;
        prefix = AMEX_PREFIX;
        break;
      case 'VISA':
        len = VISA_LENGTH;
        prefix = VISA_PREFIX;
        break;
      case 'MCRD':
        len = MCRD_LENGTH;
        prefix = MCRD_PREFIX;
        break;
      case 'DISC':
        len = DISC_LENGTH;
        prefix = MCRD_PREFIX;
        break;
    }
    
    if (isValidLength(len, ccNumClean) && isValidPrefix(prefix, ccNumClean) && isValidLUHN(ccNumClean))
      retVal = true;
    
    return (retVal);
  }

