 /*****************************************
 /  Validator v 1.2                       /
 /  Client Side Form Validator            /
 /                                        /
 /  Author: Emre Trker                   /
 /  Date: 23-04-2004                      /
 /                                        /
 / emre_turker@gmail.com                  /
 *****************************************/

// variables that keeps the validation message and validation status
var OK=true;
var MESSAGE="";

// reqular expression patterns
var NUMBER = /^[\-]?\d*$/ ;
var REAL = /^[\-]?\d*\.?\d*$/;

var TEXTONLY = /^[a-zA-Z\.\- sSiIçÇüÜöÖgG ]*$/ ;
var PASSWORD = /^\w+$/ ;
var TEXT = /^[^<^>]*$/;

var DATE = /^(\d{1,2})\-(\d{1,2})\-(\d{4})$/;
var TIME = /^(\d{1,2})\:(\d{1,2})\:(\d{1,2})$/;

var EMAIL = /^[\w-\.]+\@[\w\.-]+\.[a-z]{2,4}(\.[a-z]{2,4})*$/;
var PHONE = /^[\d\s\-]+$/;

// variables that keeps the element to be focused after error message
var focusElement;
var first=0;

// main validation function
function validate(a)
{
	// variable a refers to the form to be posted
	
	// initialize variables
	focusElement = null;
	OK=true;
	MESSAGE="";
	var i,x;
	
	/* 	set validation status to true
		if no error is found it will stay as true */
	var ok = true;
	
	// get the number of elements in the form
	i = a.elements.length;
	
	// cycle through each element in the form
	for (x=0;x<i;x++)
	{
		// get the elements that includes "mis336" tag	
		if(a.elements[x].attributes.getNamedItem('mis336'))
		{
			// set each elements style to mis336
			if (document.getElementById(a.elements[x].name + 'Lbl'))
				document.getElementById(a.elements[x].name + 'Lbl').className="mis336";
				
			// call splitVal function to split the values that mis336 tag has	
			splitVal(a.elements[x]);
		}
	}
	
	/* 	Final Operation :
		if variable OK is true then it means that validation is ok.
		if it is false it means that there are fields that is not validated. */
	if (!OK)
	{
		// Show generated message
		alert(MESSAGE);
		// focus the first element that has an error
		focusElement.focus();
		// if the element type is text select the text entered.
		if(focusElement.type=="text" || focusElement.type=="textarea" || focusElement.type=="password")
			focusElement.select();
	}
	return OK;
}

function splitVal(a)
{
	var z=0;
	// split the values in the mis336 tag by "|" character
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	
	// call appropriate function according to the first value in the mis336 tag
	switch(splits[0])
	{
		case "integer":
			return validateInteger(a);
			break;
		
		case "float":
			return validateFloat(a);
			break;
		
		case "textonly":
			return validateString(a,TEXTONLY);
			break;
			
		case "password":
			return validateString(a,PASSWORD);
			break;
			
		case "text":
			return validateString(a,TEXT);
			break;
			
		case "email":
			return validateString(a,EMAIL);
			break;
			
		case "phone":
			return validateString(a,PHONE);
			break;			
						
		case "select":
			return validateSelect(a);
			break;
			
		case "radio":
			return validateRadio(a);
			break;
			
		case "checkbox":
			return validateCheckBox(a);
			break;			
			
		case "date":
			return validateDate(a);
			break;
			
		case "time":
			return validateTime(a);
			break;		
			
		case "match":
			return validateMatch(a);
			break;				
			
		default:
			
	}
}

// the function that checks wheter two fields match or not
function validateMatch(a)
{
	// split the value in the mis336 tag and find the element to be compared with
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	controlToMatch=splits[1];

	// check wheter two fields match
	if (a.value==document.getElementById(controlToMatch).value)
		return true;
	else
		// call the function that processes the error
		return finish(a,splits);
}

// function checks the value if it is a date or not
function validateDate (a) 
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');

	// is it a required field
	if (isEmptyOk(a))
		return true;
	
	// regular expression check
	if (!DATE.test(a.value))
		return finish(a,splits)
	// check allowed ranges	for months and days
	if (RegExp.$1 > 31 || RegExp.$2 > 12)
		return finish(a,splits)
	// check number of day in month
	var dt_test = new Date(RegExp.$3, Number(RegExp.$2-1), RegExp.$1);
	if (dt_test.getMonth() != Number(RegExp.$2-1))
		return finish(a,splits);
	return true;
}

// function checks the value if it is a time or not
function validateTime(a) 
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	// check format
	if (isEmptyOk(a))
		return true;
	// regular expression check
	if (!TIME.test(a.value))
		return finish(a,splits);
	// check allowed ranges	
	if (RegExp.$1 > 23 || RegExp.$2 > 59 || RegExp.$3 > 59)
		return finish(a,splits);
	return true;
}

// function that checks wheter a value is selected or not in a combo box
function validateSelect(a)
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	// if selected index is below 1, it means that there is no selected value
	if (a.selectedIndex<1)
		return finish(a,splits);
}

// checks wheter a value selected or not in a group of radio buttons
function validateRadio(a)
{
	var checked=false;
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	// get all input tags in the document
	var inputs = document.getElementsByTagName ('input');
	if (inputs) 
	{
		// cycle through all input elements
		for (var i = 0; i < inputs.length; ++i) 
		{
			// look at the matched radio elements
			if (inputs[i].type == 'radio' && inputs[i].name == a.name)
				if (inputs[i].checked)
					checked=true; 
		}
	}
	if (!checked)
		return finish(a,splits);
}

// checks wheter required values are checked or not in a group of checkboxes
function validateCheckBox(a)
{
	var checked=false;
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	if (splits.length==2) 
		return false;
		
	var groupName=splits[1];
	var atLeastChecked=splits[2];
	var currentChecked=0;
	
	// get all input tags in the document	
	var inputs = document.getElementsByTagName ('input');
	if (inputs) 
	{
		// cycle through all input elements
		for (var i = 0; i < inputs.length; ++i) 
		{
			// look at the matched checkbox elements
			if (inputs[i].type == 'checkbox')
			{
				var attrSplits=inputs[i].attributes.getNamedItem('mis336').value.split('|');
				if (attrSplits[1]==groupName && inputs[i].checked)
					// if checkbox belongs to specified group and checked increse the counter by 1
					currentChecked++;
			}
		}
	}
	// if total checked elements meets the requirement then validation result is true
	if (currentChecked>=atLeastChecked)
		checked=true;

	if (!checked)
		return finish(a,splits);
}

// makes validation of a string acoording to a regular expression pattern
function validateString(a,regX)
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');

	// if the field is required and empty than return false
	if (isEmptyErr(a))
	{
		return finish(a,splits);
	}

	// if the field is not required and empty then return true
	if (isEmptyOk(a))
		return true;
	
	// call the function that checks the string values.
	if (!isStringOK(a.value,regX))
	{
		return finish(a,splits);
	}

	/* 	if third value is numeric and the number of values 
		in the mis336 tag is more than 3 
		it means that there are additional criteria to match */
	if (splits[2])
	{
		if (isNumeric(splits[2]) && splits.length>3)
		{
			// the minimum number of characters
			var minimum=splits[2];
			// maximum number of characters
			var maximum=splits[3];
			if ((a.value.length < parseInt(minimum)) || (a.value.length > parseInt(maximum)))
				return finish(a,splits);
			else
				return true;
		}
		else
			return true;
	}
	
}

// checks wheter the value is integer
function validateInteger(a)
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	
	// if the field is required and empty than return false
	if (isEmptyErr(a))
	{
		return finish(a,splits);
	}
	
	// if the field is not required and empty then return true
	if (isEmptyOk(a))
		return true;
	
	// call the function that checks the number
	if (!isNumeric(a.value))
	{
		return finish(a,splits);
	}
	
	/* 	if third value is numeric and the number of values 
		in the mis336 tag is more than 3 
		it means that there are additional criteria to match */	
	if (splits[2])
	{
		if (isNumeric(splits[2]) && splits.length>3)
		{
			// minumum value that the field can take
			var minimum=splits[2];
			// maximum value that the field can take			
			var maximum=splits[3];
			if ((a.value < parseInt(minimum)) || (a.value > parseInt(maximum)))
				return finish(a,splits);
			else
				return true;
		}
		else
			return true;
	}
}

// checks wheter the the value is a floating number
function validateFloat(a)
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');

	// if the field is required and empty than return false
	if (isEmptyErr(a))
	{
		return finish(a,splits);
	}
	
	// if the field is not required and empty then return true
	if (isEmptyOk(a))
		return true;
	
	// call the function that checks the floating number
	if (!isFloat(a.value))
	{
		return finish(a,splits);
	}

	/* 	if third value is numeric and the number of values 
		in the mis336 tag is more than 3 
		it means that there are additional criteria to match */	
	if (splits[2])
	{
		if (isFloat(splits[2]) && splits.length>3)
		{
			// minumum value that the field can take
			var minimum=splits[2];
			// maximum value that the field can take		
			var maximum=splits[3];
			if ((a.value < parseFloat(minimum)) || (a.value > parseFloat(maximum)))
				return finish(a,splits);
			else
				return true;
		}
		else
			return true;
	}
}

function isStringOK(sText,regX)
{
	return regTest(regX,sText);
}

function isNumeric(sText)
{
	return regTest(NUMBER,sText);
}

function isFloat(sText)
{
	return regTest(REAL,sText);
}

// function that makes regular expression tests
function regTest(regEx,strToTest)
{
	if(regEx.test(strToTest))
	{
		return true;
	}
	else
		return false
}

// if the field is not required and empty then return true
function isEmptyOk(a)
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	if (splits[1]=="false" && a.value=="")
	{
		return true;
	}
}

// if the field is required and empty than return false
function isEmptyErr(a)
{
	var splits=a.attributes.getNamedItem('mis336').value.split('|');
	if (splits[1]!="false" && a.value=="")
	{
		return true;
	}
}

// process the error
function finish(a,splits)
{
	// get the error message and add to the variable message with new line character
	MESSAGE += splits[splits.length-1] + "\n";
	
	// change the value of OK variable to false means that validation result is false
	OK=false;
	
	// change the style of the label ot element that has error to mis336Error
	if (document.getElementById(a.name + 'Lbl'))
		document.getElementById(a.name + 'Lbl').className = "mis336Error";

	// if focus element variable is not set, set it
	if(!focusElement) 
		focusElement=a; 
	return false;
}