/*======================================================================================
' Copyright : Streamline Technologies, LLC - Nashville, TN
' Author	: Alex Short
' Created	: 2/9/2007
' Purpose	: Javascript functions used in Streamline Technologies web sites
======================================================================================*/

// Global variables
var isIE;

// Set isIE to true if browser is IE
if (navigator.userAgent.indexOf('MSIE') != -1) isIE = true;
else isIE = false;

// Submits form f
function submitForm(f) {
  for (var i=0; i<document.forms.length; i++) {
    if (document.forms[i].name == f) document.forms[i].submit();   
} }

// Returns the value of a radio button          
function getRadioButtonValue(radio) {
  if (isNaN(radio.length)) { 
    if (radio.checked) return radio.value;     //Only 1 radio option exists  
  }
  else {
    for (var i=0; i<radio.length; i++) 
      if (radio[i].checked) break;
    return radio[i].value;
  }
}

// Returns true if string s is empty
function isEmpty(s) {   
  return ((s == null) || (s.length == 0));
}

// Trims leading/trailing whitespace off string s
function trim(s) {
  return s.replace(/^\s+|\s+$/g,'');
}

//Removes all characters which appear in string bag from string s
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;
}

//Reformats string s
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 {
      resultString += s.substring(sPos, sPos + arg);
      sPos += arg;
  } }
  return resultString;
}

// Returns true if string s has a length in the range of integer arguments a and b
function isStringInRange(s, a, b) {   
  var len = s.length;
  return ((len >= a) && (len <= b));
}

//Returns true if character c is a digit (0 .. 9)
function isDigit(c) {   
  return ((c >= '0') && (c <= '9'));
}

//Returns true if all characters in string s are digits
function isInteger(s) {   
  for (var i=0; i<s.length; i++) {
    var c = s.charAt(i);
    if (!isDigit(c)) return false;
  }
  return true;  
}

//Returns true if all characters are numbers; first character can be + or -
function isSignedInteger(s) {   
  var startPos = 0;
  if ((s.charAt(0) == '-') || (s.charAt(0) == '+'))
    startPos = 1;    
  return (isInteger(s.substring(startPos, s.length)))
}

//Returns true if string s is an integer >= 0
function isNonnegativeInteger(s) {   
  return (isSignedInteger(s) && parseInt(s) >= 0);
}

//Returns true if string s is an integer > 0
function isPositiveInteger(s) {   
  return (isSignedInteger(s) && parseInt(s) > 0);
}

//Returns true if string s is an integer within the range of integer arguments a and b
function isIntegerInRange(s, a, b) {   
  if (!isInteger(s)) return false;
  var num = parseInt(s);
  return ((num >= a) && (num <= b));
}

//Returns true if string s is an integer between 1 and 12
function isMonth(s) {   
  return isIntegerInRange(s, 1, 12);
}

//Returns true if string s is an integer between 1 and 31
function isDay(s) {
  return isIntegerInRange (s, 1, 31);
}

//Returns true if string s is a valid year number (2 or 4 digits) 
function isYear(s) {   
  if (!isNonnegativeInteger(s)) return false;
  return ((s.length == 2) || (s.length == 4));
}

//Returns number of days in February of year
function daysInFebruary(year) {
  return (((year % 4 == 0) && ((!(year % 100 == 0)) || (year % 400 == 0) )) ? 29 : 28);
}

//Returns true if string s is a valid state code 
function isStateCode(s) {
  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';
  return ((USStateCodes.indexOf(s) != -1) && (s.indexOf('|') == -1));
}

//Returns true if string s is a valid date (mm/dd/yyyy or mm/dd/yy)
function isDate(s) {
  var daysInMonth = new Array();
  daysInMonth[1] = 31;
  daysInMonth[2] = 29;
  daysInMonth[3] = 31;
  daysInMonth[4] = 30;
  daysInMonth[5] = 31;
  daysInMonth[6] = 30;
  daysInMonth[7] = 31;
  daysInMonth[8] = 31;
  daysInMonth[9] = 30;
  daysInMonth[10] = 31;
  daysInMonth[11] = 30;
  daysInMonth[12] = 31;
  var elems = s.split('/');
  if (!(elems.length == 3)) return false;
  var month = parseInt(elems[0],10);
  var day = parseInt(elems[1],10);
  var year = parseInt(elems[2],10); 
  if (!(isYear(elems[2]) && isMonth(month) && isDay(day))) return false;
  if (day > daysInMonth[month]) return false; 
  if ((month == 2) && (day > daysInFebruary(year))) return false;
  return true;
}

//Returns true if string s is an integer between 1 and 12
function isHour(s) {   
  return isIntegerInRange(s, 1, 12);
}

//Returns true if string s is an integer between 1 and 59
function isMinuteOrSecond(s) {   
  if (!isIntegerInRange(s, 0, 59)) return false;
  return (s.length == 2);
}

//Returns true if string s is a valid time (hh:mm:ss or hh:mm pm)
function isTime(s) {
  var elems = s.split(':');
  if (!((elems.length == 2) || (elems.length == 3))) return false; 
  if (elems.length == 2) {
    if (s.charAt(s.length - 2) != 'A' && s.charAt(s.length - 2) != 'a' && s.charAt(s.length - 2) != 'p' && s.charAt(s.length - 2) != 'P') return false;
    elems[1] = trim(elems[1].substring(0, elems[1].length - 2));
  }    
  if (!(isHour(elems[0]) && isMinuteOrSecond(elems[1]))) return false;
  if (elems.length == 3) { 
    if (!(isMinuteOrSecond(elems[2]))) return false;    
  }
  return true;
}

//Returns true if string s is a valid US phone number
function isUSPhoneNumber(s) {   
  return (isInteger(s) && s.length == 10)
}

//Returns true if string s is a valid zip code
function isZIPCode(s) {  
  return (isInteger(s) && ((s.length == 5) || (s.length == 9)));
}

//Returns true if string s is in valid email format
function isEmail(s) {   
  var i = 1;
  var sLength = s.length;
  while ((i < sLength) && (s.charAt(i) != '@')) i++; 
  if ((i >= sLength) || (s.charAt(i) != '@')) return false; 
  else i += 2;
  while ((i < sLength) && (s.charAt(i) != '.')) i++;   
  if ((i >= sLength - 1) || (s.charAt(i) != '.')) return false;
  else return true;
}

//Returns true if all characters in s are digits; allows 1 decimal point
function isFloat(s) {   
  var seenDecimalPoint = false;
  if (s == '.') return false;
  for (var i=0; i<s.length; i++) {   
    var c = s.charAt(i);
    if ((c == '.') && !seenDecimalPoint) seenDecimalPoint = true;
    else if (!isDigit(c)) return false;
  }
  return true;
}

//Uses the "Luhn Mod 10" test to see if string s is a valid credit card number
function isCreditCard(s) {
  var sum = 0; 
  var mul = 1; 
  var l = s.length;
  if (l > 19) return false;  // Encoding only works on cards with less than 19 digits
  for (var i=0; i<l; i++) {
    var digit = s.substring(l-i-1,l-i);
    var tproduct = parseInt(digit,10) * mul;
    if (tproduct >= 10) sum += (tproduct % 10) + 1;
    else sum += tproduct;
    if (mul == 1) mul++;
    else mul--;
  }  
  if ((sum % 10) == 0) return true;
  else return false;
}
 
//Returns true if cc is a valid Visa number
function isVisa(cc) {
  if ((cc.length == 16 || cc.length == 13) && cc.substring(0,1) == 4)
    return isCreditCard(cc);
  return false;
}

//Returns true if cc is a valid MasterCard number
function isMasterCard(cc) {
  firstdig = cc.substring(0,1);
  seconddig = cc.substring(1,2);
  if (cc.length == 16 && firstdig == 5 && (seconddig >= 1 && seconddig <= 5))
    return isCreditCard(cc);
  return false;
}

//Returns true if cc is a valid American Express number
function isAmEx(cc) {
  firstdig = cc.substring(0,1);
  seconddig = cc.substring(1,2);
  if (cc.length == 15 && firstdig == 3 && (seconddig == 4 || seconddig == 7))
    return isCreditCard(cc);
  return false;
}

//Returns true if cc is a valid Discover number
function isDiscover(cc) {
  first4digs = cc.substring(0,4);
  if (cc.length == 16 && first4digs == '6011') 
    return isCreditCard(cc);
  return false;
}
 
function checkRadioSelected(field, req) {  
  var isChecked = false;
  if (!req) {
    isChecked = true;
  }
  else {  
    if (isNaN(field.length)) {			//Only 1 radio option exists
      if (field.checked) isChecked = true;    
    }
    else {
      for (var i=0; i<field.length; i++) 
        if (field[i].checked) { isChecked = true; break; }
  } }
  if (!isChecked) {
    if (isNaN(field.length)) errMessage(field, true, 'Please select option(s).');
    else errMessage(field[0], true, 'Please select option(s).');
    return false;
  }   
  if (isNaN(field.length)) errMessage(field, false);
  else errMessage(field[0], false);
  return true; 
}

function checkStringInRange(field, min, max, req) {  
  var s = trim(field.value);  
  field.value = s;
  if (isEmpty(s)) {
    if (!req) { 
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isStringInRange(s, min, max)) {
    errMessage(field, true, 'This is a required field (' + min + ' - ' + max + ' characters.)');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function checkStringMatch(field1, field2) {  
  var s1 = trim(field1.value);  
  var s2 = trim(field2.value); 
  if (isEmpty(s1) || isEmpty(s2) || (s1 != s2)) {
    errMessage(field1, true, field1.name + 'and' + field2.name + 'must match.');
    errMessage(field2, true, field1.name + 'and' + field2.name + 'must match.');
    return false;
  }
  errMessage(field1, false);
  errMessage(field2, false);
  return true; 
}

function checkPositiveInteger(field, reqd) {  
  var s = trim(field.value);
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isPositiveInteger(s)) {
    errMessage(field, true, 'Please enter a positive integer.');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function checkNonnegativeInteger(field, reqd) {  
  var s = trim(field.value);
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isNonnegativeInteger(s)) {
    errMessage(field, true, 'Please enter a non-negative integer.');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function checkIntegerInRange(field, min, max, reqd) {  
  var s = trim(field.value);
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isIntegerInRange(s, min, max)) {
    errMessage(field, true, 'Please enter an integer between ' + min + ' and ' + max + '.');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function checkStateCode(field, reqd) {  
  var s = trim(field.value);
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  s = s.toUpperCase();
  if (!isStateCode(s)) {
    errMessage(field, true, 'Please enter a 2-character US state code.');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function checkDate(field, reqd) {
  var s = trim(field.value);  
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isDate(s)) {
    errMessage(field, true, 'Please enter a date (mm/dd/yyyy or mm/dd/yy)');
    return false;
  }
  errMessage(field, false);
  return true;   
}
  
function checkTime(field, reqd) {
  var s = trim(field.value);  
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isTime(s)) {
    errMessage(field, true, 'Please enter a time (hh:mm:ss or hh:mm am/pm).');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function reformatUSPhone(USPhone) {   
  return (reformat(USPhone, '(', 3, ') ', 3, '-', 4))
}

function checkUSPhone(field, reqd) {
  var s = trim(field.value);  
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  var normalizedPhone = stripCharsInBag(s, '()- ');
  if (!isUSPhoneNumber(normalizedPhone)) {
    errMessage(field, true, 'Please enter a valid phone number, including area code.');
    return false;
  }
  errMessage(field, false);
  field.value = reformatUSPhone(normalizedPhone);
  return true;   
}

function reformatZIPCode(ZIPString) {   
  if (ZIPString.length == 5) return ZIPString;
  else return (reformat(ZIPString, '', 5, '-', 4));
}

function checkZIPCode(field, reqd) {
  var s = trim(field.value);  
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  var normalizedZIP = stripCharsInBag(s, '-');
  if (!isZIPCode(normalizedZIP)) {
    errMessage(field, true, 'Please enter a valid zip code.');
    return false;
  }
  errMessage(field, false);
  field.value = reformatZIPCode(normalizedZIP);
  return true;   
}

function checkEmail(field, reqd) {
  var s = trim(field.value);  
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isEmail(s)) {
    errMessage(field, true, 'Please enter a valid email address.');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function checkFloat(field, reqd) {  
  var s = trim(field.value);
  field.value = s;
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');      
    return false;
  }
  if (!isFloat(s)) {
    errMessage(field, true, 'Please enter a decimal value.');
    return false;
  }
  errMessage(field, false);
  return true;   
}

function checkCreditCard(field, mc, visa, disc, amex, reqd) {
  var s = trim(field.value);
  if (isEmpty(s)) {
    if (!reqd) {
      errMessage(field, false);
      return true;
    }
    errMessage(field, true, 'This is a required field.');
    return false;
  }
  var normalizedCCN = stripCharsInBag(s, '- ');
  if (mc && isMasterCard(normalizedCCN)) {
    field.value = normalizedCCN;
    errMessage(field, false);
    return true; 
  }
  if (visa && isVisa(normalizedCCN)) {
    field.value = normalizedCCN;
    errMessage(field, false);
    return true; 
  }
  if (disc && isDiscover(normalizedCCN)) {
    field.value = normalizedCCN;
    errMessage(field, false);
    return true; 
  }
  if (amex && isAmEx(normalizedCCN)) {
    field.value = normalizedCCN;
    errMessage(field, false);
    return true; 
  }
  errMessage(field, true, 'Please enter a valid credit card.');
  return false;
}
