//--------------------------------------------------------------
// GenVali (C) 2002, Dino Cherian K
//--------------------------------------------------------------
// Send your comments and patches to dinocherian@yahoo.com
// Feel free to contact me for support.
//--------------------------------------------------------------

// See README.txt for details of using this script.
// See LICENSE.txt for details about the license.

//---------                                            ---------
//-------    Editing below this line is not advisable    -------
//---------                                            ---------

var isOpera = -1 != navigator.userAgent.toLowerCase().indexOf('opera');

function CheckAllowedChars(strToCheck, allowedChars)
{
	var acLen	= allowedChars.length;
	var stcLen	= strToCheck.length;
	strToCheck	= strToCheck.toLowerCase();
	var i;
	var j;
	var rightCount = 0;
	for(i = 0; i < acLen; i++)
	{
		switch(allowedChars.charAt(i))
		{
		case 'A':
			for(j = 0; j< stcLen; j++)
			{
				rightCount += strToCheck.charAt(j) >= 'a' && strToCheck.charAt(j) <= 'z';
			}
			break;
		case 'N':
			for(j = 0; j< stcLen; j++)
			{
				rightCount += strToCheck.charAt(j) >= '0' && strToCheck.charAt(j) <= '9';
			}
			break;
		default:
			for(j = -1; -1 != (j = strToCheck.indexOf(allowedChars.charAt(i), j + 1)); rightCount++);
			break;
		}
	}
	if(rightCount == stcLen)
	{
		return true;
	}
	return false;
}

function CheckNotAllowedChars(strToCheck, unAllowedChars)
{
	var acLen	= unAllowedChars.length;
	var stcLen	= strToCheck.length;
	strToCheck	= strToCheck.toLowerCase();
	var i;
	var j;
	var rightCount = 0;
	for(i = 0; i < acLen; i++)
	{
		switch(unAllowedChars.charAt(i))
		{
		case 'A':
			for(j = 0; j< stcLen; j++)
			{
				if(strToCheck.charAt(j) >= 'a' && strToCheck.charAt(j) <= 'z')
				{
					return false;
				}
			}
			break;

		case 'N':
			for(j = 0; j< stcLen; j++)
			{
				if(strToCheck.charAt(j) >= '0' && strToCheck.charAt(j) <= '9')
				{
					return false;
				}
			}
			break;

		default:
			if(strToCheck.indexOf(unAllowedChars.charAt(i)) != -1)
			{
				return false;
			}
			break;
		}
	}
	return true;
}

function TrimSpace(frmElement)
{
	var stringToTrim = frmElement.value;
	var len = stringToTrim.length;
	var front;
	var back;

	if(HumanEditable(frmElement))
	{
		for(front = 0; front < len && (stringToTrim.charAt(front) == ' ' || stringToTrim.charAt(front) == '\n' || stringToTrim.charAt(front) == '\r' || stringToTrim.charAt(front) == '\t'); front++);
		for(back = len; back > 0 && back > front && (stringToTrim.charAt(back - 1) == ' ' || stringToTrim.charAt(back - 1) == '\n' || stringToTrim.charAt(back - 1) == '\r' || stringToTrim.charAt(back - 1) == '\t'); back--);

		frmElement.value = stringToTrim.substring(front, back);
	}
}

function HumanEditable(frmElement)
{
	var finType = frmElement.type;
	return (finType == "textarea" || finType == "text" || finType == "password");
}

function NoChkBoxSelected(frmElement)
{
	var i;
	if(eval(frmElement + isOpera? '.length': '[1]'))
	{
		var len = eval(frmElement+'.length');
		for(i = 0; i < len; i++)
		{
			if(eval(frmElement + '[' + i + '].checked'))
			{
				break;
			}
		}
		if(i < len)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	else
	{
		if('checkbox' == eval(frmElement+'.type'))
		{
			return !(eval(frmElement+'.checked'));
		}
		else
		{
			return false;
		}
	}
}

function CountOccurance(str, charecter)
{
	var j;
	var count;
	for(j = -1, count = 0; -1 != (j = str.indexOf(charecter, j + 1)); count++);
	return count;
}

function CheckEmail(email, mandatory)
{
	if((mandatory && !(email.length))
	 || (email.length && !(CheckAllowedChars(email, 'AN@-_.<>')
		&& CountOccurance(email, '@') == 1
		&& email.indexOf('@') != 0
		&& email.lastIndexOf('@') != (email.length - 1)
		&& CountOccurance(email, '<') <= 1
		&& CountOccurance(email, '>') <= 1
		&& ((email.lastIndexOf('>') == (email.length - 1) && email.indexOf('<') != -1)
			|| (email.indexOf('>') == -1 && email.indexOf('<') == -1))
		&& CountOccurance(email, '.') >= 1
		&& email.indexOf('..') == -1
		&& email.indexOf('.') != 0
		&& email.lastIndexOf('.') != (email.length - 1))))
	{
		return false;
	}

	afterAt = email.substring(email.indexOf('@') + 1);
	if(!(afterAt.indexOf('.') != 0 && afterAt.lastIndexOf('.') != (afterAt.length - 1)))
		return false;

	beforeAt = email.substring(0, email.indexOf('@'));
	if(!(beforeAt.indexOf('_') != 0
	 && beforeAt.indexOf('-') != 0
	 && beforeAt.indexOf('.') != 0
	 && beforeAt.lastIndexOf('.') != (beforeAt.length - 1)))
	{
		return false;
	}
	return true;
}

/*
 * CheckDateString(dateString, dateFormat, seperator)
 *
 * dateString	The string that is to validated.
 * dateFormat	The format in which the date is expected to be present in dateString. {dmy for ddmmyyyy, ymd for yyyymmdd}
 * seperator	The seperator that seperates the day, month & year from each other. Its possible values are - and /
 *
 * Returns true if the date that you give is correct. Else it returns false.
 */

function CheckDateString(dateString, dateFormat, seperator)
{
	var dmy = new Array();
	var day, month, year;

	dateFormat = dateFormat.toLowerCase();

	if(!CheckAllowedChars(dateFormat, 'dmy'))
	{
		alert('CheckDateString: Function usage error.\n    Invalid date format.');
		return false;
	}

	if(seperator)
	{
		if(!CheckAllowedChars(seperator, '/-'))
		{
			alert('CheckDateString: Function usage error.\n    Invalid seperator.');
			return false;
		}
	}
	else
		seperator = '-';

	if(!CheckAllowedChars(dateString, 'N' + seperator))
		return false;

	dmy = dateString.split(seperator);
	if(dmy.length == 3)
	{
		i = 0;
		while(dateFormat.length > 0)
		{
			fmtLen = CountOccurance(dateFormat, dateFormat.charAt(0));

			switch(dateFormat.charAt(0))
			{
			case 'd':
				day = dmy[i];
				break

			case 'm':
				month = dmy[i];
				break

			case 'y':
				year = dmy[i];
				break
			}
			dateFormat = dateFormat.substring(fmtLen);
			i++;
		}

		if(!(day.length > 0 && month.length > 0 && year.length > 0))
			return false;

		return _CheckDate(day, month, year);
	}
	return false;
}

/*
 * CheckDate(day, month, year)
 *
 * As you expect day, month and year are the strings that contains the corresponding values.
 *
 * Returns true if the date that you give is correct. Else it returns false.
 */

function CheckDate(day, month, year)
{
	if(!CheckAllowedChars(day + month + year, 'N'))
		return false;

	if((day.length <= 0) || (month.length <= 0) || (year.length <= 0))
		return false;

	return _CheckDate(day, month, year);
}

function _CheckDate(day, month, year)
{
	year = parseInt(year, 10);
	if(year <= 0)
		return false;

	month = parseInt(month, 10);
	if(!((month > 0) && (month < 13)))
		return false;

	var daysInMonth = new Array();
	daysInMonth[ 0] = 31;					//Jan
	daysInMonth[ 1] = IsLeap(year) == true? 29: 28;	//Feb
	daysInMonth[ 2] = 31;					//Mar
	daysInMonth[ 3] = 30;					//Apr
	daysInMonth[ 4] = 31;					//May
	daysInMonth[ 5] = 30;					//Jun
	daysInMonth[ 6] = 31;					//Jul
	daysInMonth[ 7] = 31;					//Aug
	daysInMonth[ 8] = 30;					//Sep
	daysInMonth[ 9] = 31;					//Oct
	daysInMonth[10] = 30;					//Nov
	daysInMonth[11] = 31;					//Dec

	day = parseInt(day, 10);
	if(!((day > 0) && (day <= daysInMonth[month - 1])))
		return false;

	return true;
}

function IsLeap(year)
{
	if((year % 4) == 0)
	{
		if((year % 100) == 0)
		{
			if((year % 400) == 0)
				return true;
			else
				return false;
		}
		return true;
	}
	return false;
}

function CheckDropDown(dropDown, alertMsg, moveNext)
{
	if(dropDown.options[dropDown.selectedIndex].value == '')
	{
		if(alertMsg != '')
			alert(alertMsg);

		if(moveNext)
			dropDown.selectedIndex++;

		return false;
	}
	return true;
}


function A_TrimSpace(frm, A_frmElement)
{
	var i;
	var feName = A_frmElement.name;
	if(A_frmElement.type.substring(0, 7) == "select-")
		return;
	if(frm[feName][isOpera? 'length': 1])
	{
		for(i = 0; i < frm[feName].length; i++)
			TrimSpace(frm[feName][i]);
	}
	else
		TrimSpace(A_frmElement);
}



// Validation Functions
//---------------------

//Define error object
var err, otherErr, firstErr, errStatus;

//Define Input types
var inTypes
inTypes = new Array();


function SetInputProp(idx, mandatory, trim, syntax, desc)
{
	inTypes[idx] = new Array();
	inTypes[idx][0] = mandatory;
	inTypes[idx][1] = trim;
	inTypes[idx][2] = syntax;
	inTypes[idx][3] = desc;
}

function SetError(idx)
{
	errStatus = true;
	err[idx] = true;
	if(firstErr == -1)
		firstErr = idx;
}

function SetOtherError(errMsg, idx)
{
	errStatus = true;
	if(idx != -1)
	{
		err[idx] = true;
		if(firstErr == -1)
			firstErr = idx;
	}
	else
		otherErr[otherErr.length] = errMsg;
}

function ShowError(frm)
{
	var msg = "";
	if(firstErr != -1)
	{
		frm.elements[firstErr].focus();
		msg = "Please fillout the following input(s), properly\n"
		for(j = 0; j < err.length; j++)
			if(typeof err[j] != "undefined")
				msg += (" » " + inTypes[j][3] + "\n");
	}
	for(j = 0; j < otherErr.length; j++)
		msg += ("\n" + otherErr[j] + "\n");

	if(errStatus == true)
		alert(msg);
}

function NoDataIn(frm, feIdx)
{
	feName = frm.elements[feIdx].name;

	if(frm[feName][isOpera? 'length': 1])
	{
		if(frm[feName].type)
		{
			if(frm[feName].type.substring(0, 7) == "select-")
			{
				return IsEmpty(frm[feName])
			}
		}

		for(k = 0; k < frm[feName].length; k++)
			if(!IsEmpty(frm[feName][k]))
				return false;
		return true;
	}
	else
		return IsEmpty(frm[feName])
}

function IsEmpty(fele)
{
	switch(fele.type)
	{
	case "text":
	case "textarea":
		return fele.value == "";
		break;

	case "select-one":
	case "select-multiple":
		return fele.selectedIndex == -1 || fele.options[fele.selectedIndex].value == "";
		break;

	case "checkbox":
	case "radio":
		return !fele.checked;
		break;
	}
}

function CheckForm(frm, displayError)
{
	//(Re)initialize error objects
	err = new Array();
	otherErr = new Array();
	firstErr = -1;
	errStatus = false;

	var i = 0;

	for(i = 0; i < inTypes.length; i++)
	{
		if(typeof inTypes[i] != "undefined")
		{
			if(inTypes[i][isOpera? 'length': 1])
				A_TrimSpace(frm, frm.elements[i]);

			if(inTypes[i][0] && NoDataIn(frm, i))
			{
				SetError(i);
				continue;
			}

			if(inTypes[i][2] != "" && HumanEditable(frm.elements[i]))
			{
				switch(inTypes[i][2])
				{
				case "<email>":
					if(!CheckEmail(frm.elements[i].value, false)) SetError(i);
					break;
				case "<date>":
					if(!CheckDateString(frm.elements[i].value, 'ymd')) SetError(i);
					break;
				default:
					if(inTypes[i][2].charAt(0) == '!')
					{
						if(!CheckNotAllowedChars(frm.elements[i].value, inTypes[i][2].substring(1,inTypes[i][2].length)))
							SetError(i);
					}
					else if(inTypes[i][2].substring(0, inTypes[i][2].indexOf('.')) == '<date')
					{
						var m = inTypes[i][2].match(/^<date\.([dmy]{3})((>)|\.([\/-])>)$/);
						if(m)
						{
							var format = m[1];
							var sep = m[2] == '>'? '-': m[4];
	
							if(!CheckDateString(frm.elements[i].value, format, sep))
								SetError(i);
						}
						else
						{
							alert('Error in date-format specifier.');
							return false;
						}
					}
					else
					{
						if(!CheckAllowedChars(frm.elements[i].value, inTypes[i][2]))
							SetError(i);
					}
					break;
				}
			}
		}
	}

	if(displayError) ShowError(frm);

	return !errStatus;
}
