/* changelog
Jan 31
- added label functionality originally from CBS
- changed validate- to validation-
- fixed Nan to NaN
*/

if (typeof window.$ !== 'function')
	function $(s) { return document.getElementById(s);}

/*
* @Date: Feb 21, 2005
* @Description: This function strips defined chars from a string
* useful in validation routines
* example: stripChars(str, "()-") returns the string with any
* brackets and dashes removed
**/
function stripChars(str, chars) {
  var i;
  var newstring = "";
  for (i = 0; i < str.length; i++) {
    mychar = str.charAt(i);
    if (chars.indexOf(mychar) == -1)
      newstring += mychar;
  }
  return newstring;
}

/**
* @Date: Feb 21, 2005
* @Description: This function extracts defined chars from a string
* useful in validation routines
* it is 'sort of' the reverse of stripChars
* example: extractChars(str, "0123456789") returns all digits from the string
**/
function extractChars(str, chars) {
  var i;
  var newstring = "";
  for (i = 0; i < str.length; i++) {
    mychar = str.charAt(i);
    if (chars.indexOf(mychar) != -1)
      newstring += mychar;
  }
  return newstring;
}

/**
* @Date: Dec 1, 2004
* @Description: This function tests a credit card using the Luhn validation
* The sum of digits must be divisible by 10
* digits in odd positions are doubled, then sum of left+right digit is taken
**/
function isValidCreditCard(sCreditCardNumber)
{
  var nTotal      = 0;
  var nPosition     = 0;
  var bValid      = true; // innocent until proven guilty
  sCreditCardNumber = extractChars(sCreditCardNumber, "0123456789");
  if (sCreditCardNumber.length < 13)
    bValid = false;
  else
  {
    for ( i = sCreditCardNumber.length; i > 0 ;  i--)
    {
      var nDigit      = 0;
      // advance
      nPosition++;
      // get digit
      nDigit= parseInt(sCreditCardNumber.charAt(i-1));
      // odd position: add to total
      if ((nPosition % 2) !== 0)
         nTotal += parseInt(nDigit);
      else
      // even position: add sum of digits to total
      {
        // calc sum of left and right digit (use parseInt to cut off fractional parts
        var nDoubled = nDigit * 2;
        var nLeftDigit  = parseInt(nDoubled / 10);
        var nRightDigit = nDoubled % 10;
        // get sum of left and right
        nTotal += nLeftDigit + nRightDigit;
      }
    }
    // if divisible by 10 it is valid
    bValid = (nTotal % 10) === 0;
  }
  return (bValid);
}

/* check if d is a date value
 * formatted means it is in fact a string, formatted as mm/dd/yyyy
*/
function isDate(d, formatted)
{
  var ret = false;

  var date = new Date(d);

  // it's at least a number
  if (!isNaN(date))
  {
    if (formatted)
    {
      day = date.getDate();
      month = date.getMonth()+1;
      year = date.getFullYear();
      dateString = '' + month + '/' + day + '/' + year;
      pattern = new RegExp('' + month + '.' + day + '.' + year);
      ret = pattern.test(dateString);
    }
    else
      ret = true;
  }
  return ret;
}

/* generic validation routine */
function validateForm(frm, target)
{
  var i;
  var ret = true;
  var field;
  var out='';
  var errorFields = [];

  if (!target)
    target = "errors";

  if (!$(target))
  {
    console.log('setup element ' + target + ' to make errors visible');
    return false;
  }

  // loop through all fields
  // check if they have validation class name
  // and do appropriate validation
  // @return true, if all validation passes
  for (i=0; i<frm.elements.length; i++)
  {
		field = frm.elements[i];
		// skip disabled fields and fields without a name
		if (field.disabled || field.name==undefined)
			continue;

		if ($('label-'+field.name))
			field.label = $('label-'+field.name).innerHTML;
		else
			field.label = field.name;

		// validate required fields
		filter = /validation-required/;

    // validate required fields
    filter = /validation-required/;
    if (filter.test(field.className))
    {
      if (field.type=='checkbox')
			{
				if (!field.checked)
	      {
	        out += 'Please check the ' + field.label + ' box<br />';
	        errorFields.push(field);
	        ret = false;
	      }
			}
      else
        if (field.value==='')
        {
          out += 'Please enter a value for ' + field.label + '<br />';
          errorFields.push(field);
          ret = false;
        }
    }
    // validate numeric fields
    filter = /validation-number/;
    if (filter.test(field.className))
    {
      if (field.value!=='' && isNaN(field.value))
      {
        out += 'Please enter a number for ' + field.label + '<br />';
        errorFields.push(field);
        ret = false;
      }
    }
    // validate digit only fields
    filter = /validation-digits/;
    if (filter.test(field.className))
    {
      var filter  = /^[0-9]+$/;
      if (field.value!=='' && !filter.test(field.value))
      {
        out += 'Please enter a number for ' + field.label + '<br />';
        errorFields.push(field);
        ret = false;
      }
    }
    // validate date fields
    filter = /validation-date/;
    if (filter.test(field.className))
    {
      if (field.value!=='' && !isDate(field.value, true))
      {
        out += 'Please enter a valid date for ' + field.label + '<br />';
        errorFields.push(field);
        ret = false;
      }
    }
    // validate this date later than other field's date
    filter = /validation-date-after/;
    if (filter.test(field.className))
    {
      var otherFieldName = field.className.replace(/.*validation-date-after-/,'').replace(/ .*/,'');
      if (field.value!=='' && $(otherFieldName))
      {
				var otherField = $(otherFieldName);
				if (isDate(field.value) && isDate(otherField.value))
				{
					var date1	= new Date(field.value);
					var date2 = new Date(otherField.value);
				}
				if (+date1 <= +date2) // + converts to number
				{
	        out += 'Please enter a date for  ' + field.label + ' after ' + otherField.name  + '<br />';
	        errorFields.push(field);
	        ret = false;
				}
      }
    }
    // validate email addresses
    filter = /format-email/;
    if (filter.test(field.className))
    {
      filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
      if (field.value!=='' && !filter.test(field.value))
      {
        out += 'Please enter a valid email address in ' + field.label + '<br />';
        errorFields.push(field);
        ret = false;
      }
    }
    // validate credit cards
    // this uses Luhn validation
    // which is a numeric algorithm
    filter = /format-creditcard/;
    if (filter.test(field.className))
    {
      filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
      if (field.value!=='' && !isValidCreditCard(field.value))
      {
        out += 'Please enter a valid credit card number'  + '<br />';
        errorFields.push(field);
        ret = false;
      }
    }
    // validate urls
    filter = /format-url/;
    if (filter.test(field.className))
    {
      filter  = /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/i;
      if (field.value!=='' && !filter.test(field.value))
      {
        out += 'Please enter a valid url in ' + field.label + '<br />';
        errorFields.push(field);
        ret = false;
      }
    }
    // validate verification fields
    filter = /validation-match/;
    if (filter.test(field.className))
    {
      var otherField = field.className.replace(/.*validation-match-/,'').replace(/ .*/,'');
      if (field.value!=='' && field.value!=$(otherField).value)
      {
        out += 'The value in ' + field.label + ' does not match ' + otherField  + '<br />';
        errorFields.push(field);
        ret = false;
      }
    }
    field.className = field.className.replace(" error","");
  }
  $(target).innerHTML = out;
  // indicate errors
  for (i = 0; i < errorFields.length; i++)
    errorFields[i].className += " error";
  window.scroll(0,0);
  return ret;
}