/***********************************************************************************
 * File: form_validation.js
 * Description:
 *   Validation functions for forms
 *   Example of usage:
 *
 *   function validate(form) {
 *     // Field name, Caption
 *     checkString(form.firstName, "First Name");
 *     // Field name, Caption, Required (true | false)
 *     checkEmail(form.email, "Email", true);
 *     // Field name, Caption, Required (true | false)
 *     checkDate(form.address3, "Date Of Birth", true);
 *
 *     // Displays error and returns false if an error occurred
 *     return checkError();
 *   }
 *
 *   ...
 *
 *   <form .... onsubmit="return validate(this);">
 *
 ***********************************************************************************/

/***********************************************************************************
 * Get browser version
 ***********************************************************************************/
 
  var br_dom = (document.getElementById) ? true : false;
  var br_ns4 = (document.layers) ? true : false;
  var br_ie = (document.all) ? true : false;
  var br_ie4 = br_ie && !br_dom;
  var br_mac = (navigator.appVersion.indexOf("Mac") != -1);
  var br_ie4Mac = br_ie4 && br_mac;
  var br_opera = (navigator.userAgent.indexOf("Opera")!=-1);
  var br_konqueror = (navigator.userAgent.indexOf("Konqueror")!=-1);

/***********************************************************************************
 * Helper functions
 ***********************************************************************************/

// Check if item is valid
function checkItem(item, field) {
  if(item == null) {
    addError("Script error: " + field + " item is invalid", null);
    return false;
  }
  return true;
}

// Check if item contains only valid characters
function checkCharSet(string, charSet) {
  var i = 0;
  while(i < string.length && charSet.indexOf(string.charAt(i)) >= 0)
    i++;
  
  return (i == string.length);
}

// Get item value (check if dropdown or text field)
function getItemValue(item) {
  if(!checkItem(item))
    return null;

  if(item.type == "select")
    return item.options[item.selectedIndex].value;
  else
    return item.value;
}

// Return difference in years between two dates
function dateYearDiff(date1, date2, range) {
  //alert(date1.getFullYear)
  if(date1 == null || date2 == null)
    return null;

  // Get differences
  var diffYears = parseInt(date2.getFullYear() - date1.getFullYear());
  var diffMonths = parseInt(date2.getMonth() - date1.getMonth());
  var diffDays = parseInt(date2.getDate() - date1.getDate());
  
  // Return difference
  return (diffMonths < 0 || (diffMonths == 0 && diffDays < 0)) ? diffYears - 1 : diffYears;
}

//Returns true or false depending on whether the end date is before the startdate
function validDateRange(startDate, endDate, field) {
var one_day=1000*60*60*24;
field = field.replace(":", "");
field = field.replace("?", "");
  if ((endDate - startDate)/(one_day) < 0) {
    return addError(field + " should be after the Start date");
  } 
  return true;
}


// Return difference in years between two dates
function dateDaysDiff(date1, date2, range) {
  if(date1 == null || date2 == null)
    return null;

  //var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  
  // Get differences
  var diffMili = parseInt(date2.valueOf() - date1.valueOf());
  
  // Return difference
  return parseInt(diffMili / (1000 * 60 * 60 * 24));
}

// Return difference between two dates (l=mili, s=sec, n=min, h=hours, d=days (default), m=months, y=years)
function dateDiff(date1, date2, range) {
  if(date1 == null || date2 == null)
    return null;

  //var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  
  // Get differences
  var diffYears = parseInt(date2.getFullYear() - date1.getFullYear());
  var diffMonths = parseInt(date2.getMonth() - date1.getMonth());
  var diffDays = parseInt(date2.getDate() - date1.getDate());
  var diffMili = parseInt(date2.valueOf() - date1.valueOf());
  
  if(range == null)
    range = "d";
    
  // Return difference
  var div = 1;
  switch(range) {
  case "s":
    div = 1000;
  case "n":
    div *= 60;
  case "h":
    div *= 60;
  case "d":
    div *= 24;
  case "l":
    return parseInt(diffMili / div);
  case "m":
    // Not implemented yet
    return 0;
  case "y":
    return (diffMonths < 0 || (diffMonths == 0 && diffDays < 0)) ? diffYears - 1 : diffYears;
  }
  return null;
}

// Checks for a valid date
function isDate(date) {
  var valid = true;
  
  var i = date.indexOf('/');
  var i2 = date.indexOf('/', i + 1);
  
  day = date.substring(0, i);        // day
  month = date.substring(i + 1, i2);    // month
  year = date.substring(i2 + 1);      // year
  
  if(  isNaN(day) || isNaN(month) || isNaN(year) ||
      day < 1 || day > 31 || day.length > 2 || day.length < 1 ||
      month < 1 || month > 12 || month.length > 2 || month.length < 1 ||
      year < 0 || year.length > 4 || year.length < 2)
    return false;

  var mon = parseInt(month, 10);
  
  // April, June, September, November only 30 days
  if(mon == 4 || mon == 6 || mon == 9 || mon == 11) {
    if(parseInt(day, 10) > 30)
      valid = false;
  }
  else if(mon == 2) {
    if(parseInt(day, 10) > (28 + (parseInt(year, 10) % 4 == 0 && parseInt(year, 10) % 400 != 0 ? 1 : 0)) )
      valid = false;
  }
  else if(parseInt(day, 10) > 31)
    valid = false;
  
  return valid;
}

// Returns true if year is a leap year
function isLeapYear(year) {
  return (year % 4 == 0 && year % 400 != 0);
}

// Converts an item group to a date object
function itemGroupToDate(form, itemPrefix) {
  var day = getItemValue(form.elements[itemPrefix + "_day"]);
  var month = getItemValue(form.elements[itemPrefix + "_month"]);
  var year = getItemValue(form.elements[itemPrefix + "_year"]);

  if(day == null || month == null || year == null || !isDate(day + "/" + month + "/" + year))
    return null;

  return new Date(year, month - 1, day);
}

// Trim a string
function trim(str)
{
  var i = 0, j = str.length - 1;
  while(i < j && str.charAt(i) == ' ')
    i++;
  while(j > i && str.charAt(j) == ' ')
    j--;
  
  return str.substring(i, j + 1);
}

/***********************************************************************************
 * Error functions
 ***********************************************************************************/

// Global validation variable
var validationErrorArray = null;

// Create an error array
function createErrorArray() {
  return new Array();
}

// Add an error
function addError(errorMsg, item, errorArray, skip) {
  if(skip)
    return false;
  
  if(errorArray == null) {
    if(validationErrorArray == null)
      validationErrorArray = createErrorArray();
    
    errorArray = validationErrorArray;
  }

  var i = errorArray.length;
  errorArray.length += 2;
  errorArray[i] = errorMsg;
  errorArray[i + 1] = item;
  
  return false;
}

// Clear any errors
function clearErrors(errorArray) {
  if(errorArray == null)
    validationErrorArray = null;
  else {
    if(validationErrorArray == errorArray)
      validationErrorArray = null;
    errorArray = null;
  }
}

// Returns number of errors
function getErrorCount(errorArray) {
  if(errorArray == null)
    errorArray = validationErrorArray;
  
  if(errorArray == null)
    return 0;
    
  return errorArray.length;
}

// Check and display error if any
function checkError(errorArray) {
  if(errorArray == null)
    errorArray = validationErrorArray;

  if(errorArray != null && errorArray.length > 0) {
    var i, focus,
    msg = "Some fields were not entered correctly:\n\n";
    
    // Add each error to output
    for(i = 0; i < errorArray.length; i += 2) {
      msg += errorArray[i] + "\n";
      
      //if(focus == null && errorArray[i + 1] != null)
        //focus = errorArray[i + 1];
        
    }

    clearErrors(errorArray);

    alert(msg);
    
    //if(focus != null)
      //focus.focus();
    return false;
  }
  return true;
}

/***********************************************************************************
 * Field validation functions
 ***********************************************************************************/

// Author:      MM
// Date:        Feb 2003
// Description:  Check for apostrophes in a filename
function checkFileName(item, field, min, max) {
  if(!checkString(item, field, min, max))
    return false;

  var length = trim(item.value).length;
  
  // Check for apostrophes in the filename
  if (item.value.indexOf("'") != -1) {
    return addError(field + " must not contain apostrophes.", item, null, field == null);
  }
}


// Check if a field is empty
function checkString(item, field, min, max) {
  if(!checkItem(item, field))
    return false;
  
  var length = trim(item.value).length;
  if(min == null) 
    min = 1;

  if(length < min && min == 1 && max == null)
    return addError(field + " is required.", item, null, field == null);
  else if(length < min && max == null)
    return addError(field + " must be at least " + min + " characters long.", item, null, field == null);
  else if(length < min || (max != null && length > max))
    return addError(field + " must be between " + min + " and " + max + " characters long.", item, null, field == null);
  return true;
}

//Check IFrame is not empty
function checkIframeText(item) {
    
  if (item.document.body.innerHTML == "")
    return addError("Body is required",ifEdit);
  return true;  
  
}

// Check if the first item is selected
function checkDropdown(item, field) {
  if(!checkItem(item, field))
    return false;

  if(item.selectedIndex == 0)
    return addError(field + " must be selected.", item, null, field == null);    
  return true;
}

// Check if at least min items are selected
function checkMultiDropdown(item, field, min, max) {
  if(!checkItem(item, field))
    return false;

  var count = 0;
  
  for(var i = 0; i < item.options.length; i++) {
    if(item.options[i].selected)
      count++;
  }
  
  if(count < min)
    return addError(field + " must have at least " + min + " item" + (min > 1 ? "" : "s") + " selected", item, null, field == null);
  else if(max != null && count > max)
    return addError(field + " may only have " + max + " item" + (max > 1 ? "" : "s") + " selected", item, null, field == null);
  return true;
}

// Check for a valid number from character set
function checkNumberCharSet(item, field, required, charSet) {
  if(!checkItem(item, field))
    return false;

  var number = item.value;
  
  if(required && number == "")
    return addError(field + " is required.", item);
  else {
    if(!checkCharSet(number, charSet)) // || isNaN(number))
      return addError(field + " may only contain valid numbers.", item, null, field == null);
    return true;
  }
}


// Check for a valid number from character set
function checkLetterCharSet(item, field, required, charSet) {
  if(!checkItem(item, field))
    return false;

  var number = item.value;
  
  if(required && number == "")
    return addError(field + " is required.", item);
  else {
    if(!checkCharSet(number, charSet)) // || isNaN(number))
      return addError(field + " may only contain letters.", item, null, field == null);
    return true;
  }
}

//Check for letters only
function checkLetters(item, field, required) {
  return checkLetterCharSet(item, field, required, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzfSOZsozYÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ' \t\r\n\f");
}


// Check for a valid number from character set
function checkLetterNumberCharSet(item, field, required, charSet) {
  if(!checkItem(item, field))
    return false;

  var number = item.value;
  
  if(required && number == "")
    return addError(field + " is required.", item);
  else {
    if(!checkCharSet(number, charSet)) // || isNaN(number))
      return addError(field + " may only contain letters or numbers.", item, null, field == null);
    return true;
  }
}

//Check for letters and numbers only
function checkLettersAndNumbers(item, field, required) {
  return checkLetterNumberCharSet(item, field, required, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzfSOZsozYÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ' \t\r\n\f");
}

// Check for a valid number
function checkNumber(item, field, required) {
  return checkNumberCharSet(item, field, required, "0123456789.,' '");
}

// Check for a valid currency number
function checkCurrency(item, field, required) {
  if (!checkNumberCharSet(item, field, required, "0123456789.,")) 
    return false;
}

// Check for a valid phone number
function checkPhone(item, field, required) {
  return checkNumberCharSet(item, field, required, "0123456789/-+ ");
}

// Check for a valid phone number
function checkAlphaNum(item, field, required) {
  if(!checkItem(item, field))
    return false;

  if(required && item.value == "")
    return addError(field + " is required.", item);
  
  if(checkCharSet(item.value, "0123456789"))
    return addError(field + " must contain letters.", item);
}

// Check for a valid email
function checkEmail(item, field, required) {
  if(!checkItem(item, field))
    return false;

  var email = trim(item.value);
  
  if(required && email == "")
    return addError(field + " is required.", item, null, field == null);
  else if(!required && email == "")
    return true;

  var reg1 = /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/; // not valid
  var reg2 = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/; // valid
  if (!reg1.test(email) && reg2.test(email))  // if syntax is valid  
    return true;

  return addError(field + " requires a valid e-mail address.", item, null, field == null);
}

// Check for a valid date
function checkDate(item, field, required) {
  if(!checkItem(item, field))
    return false;

  if(!required && item.value == "")
    return true;
    
  if(!isDate(item.value))
    return addError(field + " requires a valid date.", item, null, field == null);
  return true;
}

// Check for a valid date group (assumes each field have suffixes _day, _month, _year)
function checkDateGroup(form, itemPrefix, field, required) {
  return checkDateGroupSep(  
    form.elements[itemPrefix + "_day"], 
    form.elements[itemPrefix + "_month"], 
    form.elements[itemPrefix + "_year"], field, required);
}

// Check for a valid date group
function checkDateGroupSep(itemDay, itemMonth, itemYear, field, required) {
  if(!checkItem(itemDay, field) || !checkItem(itemMonth, field) || !checkItem(itemMonth, field))
    return false;
  
  var day = getItemValue(itemDay);
  var month = getItemValue(itemMonth);
  var year = getItemValue(itemYear);
  
  if(!required && day == "" && month == "" && year == "")
    return true;

  if(!isDate(day + "/" + month + "/" + year))
    return addError(field + " requires a valid date.", itemDay, null, field == null);
  return true;
}

// Check if a checkbox is selected
function checkCheckbox(item, field) {
  if(!checkItem(item, field))
    return false;

  if(!item.checked)
    return addError(field + " needs to be checked.", item, null, field == null);
  return true;
}

// Check if a checkbox is selected
function checkRadiobox(items, field) {
  if(checkRadioboxItem(items) == -1)
    return addError(field + " needs to be selected.", items, null, field == null);
  return true;
}

// Check if a checkbox is selected
function checkRadioboxItem(items) {
  if(!checkItem(items))
    return -1;

  var i = 0;
  while(i < items.length && !items[i].checked)
    i++;

  return (i == items.length) ? -1 : i;
}

/***********************************************************************************/