/***********************************************************************************
 * 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) {
	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;
}


// 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(checkYear(year),10)) )
			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);
}

function checkYear(year) { 
return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) ? 1 : 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);
}



// Converts an item group to a date object
function itemGroupToNewDate(form, itemPrefix) {
	var day = getItemValue(form.elements[itemPrefix + "_day"]);
	var month = getItemValue(form.elements[itemPrefix + "_month"]);
	var year = getItemValue(form.elements[itemPrefix + "_year"]);
    var NewDate;
	if(day == null || month == null || year == null || !isDate(day + "/" + month + "/" + year))
		return null;

	else{
		
		NewDate = day + '/' + month + '/' + year;
		//alert(NewDate);
		return NewDate;
	}
}

// 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
 ***********************************************************************************/

// 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 (reg1.test(item.value))
	//	return addError(" Invalid characters in "+field , 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 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 || (max != null && count > max))
		return addError(field + " must have at least " + min + " item" + (min > 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
function checkNumber(item, field, required) {
	return checkNumberCharSet(item, field, required, "0123456789.,");
}

// 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;

     if (email.indexOf(" ")!=-1){
        return addError(field + " cannot contain spaces.", item, null, field == null);
     }
	 
	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.", item, 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;
}

/***********************************************************************************/
