 /**
 * Validator Javascript set use fo:	
 *	1.	Form Javascript validation set
 * File: validator.js
 *
 * @Created clloke <chenlin@jobstreet.com>
 */

/**
 * Casting Data Type
 * @param string sText. value to be cast.
 * @param string sType. data type
 * @return mix cast data type.
 */
function typeCasting(sText, sType)
{
	sType = sType.toLowerCase();
	switch(sType)
	{
		case 'int': 
		case 'integer': 
			sText = parseInt(sText);	
			break;		
		case 'float':
		case 'double':			
			sText = parseFloat(sText);	
			break;		
		case 'boolean': sText = Boolean(sText);	break;
		case 'date': break;
		case 'string': 
		default : 
			sText = sText.toString();	
			break;
	}
	return sText;
}

function changeDate(oCtrl, sName, bHandle)
{
	var oDate = document.getElementsByName(sName);	
	if(typeof(oDate) == 'undefined') return false;

	var bComplete = true;

	var oDay = document.getElementsByName(sName + '_day');	
	sDay = oDay[0].selectedIndex;
	if(typeof(sDay) == 'undefined' || sDay == 0) bComplete = false;
	
	var oMonth = document.getElementsByName(sName + '_month');	
	sMonth = oMonth[0].selectedIndex;
	if(typeof(sMonth) == 'undefined' || sMonth == 0) bComplete = false;

	var oYear = document.getElementsByName(sName + '_year');	
	sYear = oYear[0].selectedIndex;
	if(typeof(sYear) == 'undefined' || sYear == 0) bComplete = false;
		
	if(bComplete == false)	
	{
		oDate[0].value = '' ;
		return;
	}
	var sDate = oDay[0].value + '-' + oMonth[0].value + '-' + oYear[0].value ;
	oDate[0].value = sDate;	
	
	if(typeof(bHandle) != 'undefined' && bHandle == true) core_validator.onCheckComponent(oDate[0]);
}
	/*---------------------------------------------------------------------------------------------
		Validation Component Part
	---------------------------------------------------------------------------------------------*/

/**
 * Check Empty/Required
 * @param string sText. value to be check.
 * @return boolean. true = pass | false = fail
 */
function isRequired(sText)
{
	if(trim(sText) == '') return false;
	return true;
}

/**
 * Check on regex
 * @param string regex. regex.
 * @param string sText. value to be check.
 * @return boolean. true = pass | false = fail
 */
function checkRegEx(regex, sText)
{
	//no checking for empty value
	if(trim(sText) == '') return true; 

	sText = sText.toString();
	var strRegex = new RegExp(regex);

	if (strRegex.test(sText)) return true; 
	return false;
}

/**
 * Check on valid value like email, date
 * @param string sText. value to be check.
 * @param string sType. data type
 * @return boolean. true = pass | false = fail
 */
function checkValid(sText, sType)
{
	switch (sType)
	{
		case 'date':
			return checkDate(sText);
			break;
	}
	return true;
}

function checkDate(sText)
{
	var sDate = getStrDate(sText, '-');
	var aDate = sDate.split('-');
	var sDay = aDate[2];
	var sMonth = aDate[1];
	var sYear = aDate[0]; 

	if (sDay.charAt(0) == 0) sDay = sDay.substr(1,sDay.length);
	if (sMonth.charAt(0) == 0) sMonth = sMonth.substr(1,sMonth.length);

	var oDate = new Date(sYear, sMonth-1, sDay);
	if ((oDate.getMonth()+1 != sMonth) || (oDate.getDate() != sDay) || (oDate.getFullYear() != sYear))
	{
		return false;
	}
	return true;
}

/**
 * Check on min range
 * @param string minValue. minimum value
 * @param string sText. value to be check.
 * @param string sType. data type
 * @return boolean. true = pass | false = fail
 */
function checkRangeMin(minValue, sText, sType)
{
	//no checking for empty value
	if(trim(sText) == '') return true; 

	sText = typeCasting(sText, sType);
	minValue = typeCasting(minValue, sType);
	if(sType == 'date') 
	{
		sText = getStrDate(sText);
		minValue = getStrDate(minValue);
	}
	if (sText >= minValue) return true; 
	return false;
}

/**
 * Check on max range
 * @param string maxValue. maximum value
 * @param string sText. value to be check.
 * @param string sType. data type
 * @return boolean. true = pass | false = fail
 */
function checkRangeMax(maxValue, sText, sType)
{
	//no checking for empty value
	if(trim(sText) == '') return true; 

	sText = typeCasting(sText, sType);
	maxValue = typeCasting(maxValue, sType);
	if(sType == 'date') 
	{
		sText = getStrDate(sText);
		maxValue = getStrDate(maxValue);
	}
	if (sText <= maxValue) return true; 
	return false;
}

/**
 * Compare value
 * @param string strTag. compare tag
 * @param string strCompare. compare value
 * @param string sText. value to be check.
 * @param string sType. data type
 * @return boolean. true = pass | false = fail
 */
function checkCompare(strTag, strCompare, sText, sType)
{
	//no checking for empty value
	if(trim(sText) == '') return true; 
	if(sType == 'date') 
	{
		var sText = getStrDate(sText);
		var strCompare = getStrDate(strCompare);
		sType = 'integer';
	}
	
	sText = typeCasting(sText, sType);
	strCompare = typeCasting(strCompare, sType);	
	strTag = strTag.toString();	

	switch(strTag)
	{
		case ">"	: if (sText > strCompare) return true; break;
		case ">="	: if (sText >= strCompare) return true; break;
		case "<"	: if (sText < strCompare) return true; break;
		case "<="	: if (sText <= strCompare) return true; break;
		case "="	: if (sText == strCompare) return true; break;
		case "!="	: if (sText != strCompare) return true; break;
	}
	return false;
}

/**
 * recompile date in yyyy-mm-dd format
 * @param string sText. value to be recompiled.
 * @param string strDelimeter. delimeter
 * @return string.
 */
function getStrDate(sText, strDelimeter)
{
	//Support 4 delimeter /- . (slash,dash,dot,space) and year should be 4 char
	//Return server format in yyyy<strDelimeter>mm<strDelimeter>dd

	var arrDate = new Array();
	arrDate = sText.split("/");	
	if(arrDate.length != 3) arrDate = sText.split("-");
	if(arrDate.length != 3) arrDate = sText.split(".");	
	if(arrDate.length != 3) arrDate = sText.split(" ");	
	if(arrDate.length != 3) return false;	
	
	var year;
	var month;
	var day;
	if(arrDate[0].length == 4) 
	{
		year = arrDate[0];
		month = arrDate[1];
		day = arrDate[2];
	}
	else if(arrDate[2].length == 4)
	{
		year = arrDate[2];
		month = arrDate[1];
		day = arrDate[0];
	}
	else return false;	

	if(month.length == 1) month = '0' + month;
	if(day.length == 1) day = '0' + day;
	
	if(typeof(strDelimeter) == 'undefined' || strDelimeter == null) strDelimeter = '';

	var strDate = year + strDelimeter +  month + strDelimeter + day;
	return strDate;
}

/**
 * Check on min length
 * @param string intMin. minimum value
 * @param string sText. value to be check.
 * @return boolean. true = pass | false = fail
 */
function checkLengthMin(intMin, sText)
{
	sText = sText.toString();
	if (sText.length < parseInt(intMin)) return false;	
	return true;
}

/**
 * Check on max length
 * @param string intMax. maximum value
 * @param string sText. value to be check.
 * @return boolean. true = pass | false = fail
 */
function checkLengthMax(intMax, sText)
{
	sText = sText.toString();
	if (sText.length > parseInt(intMax)) return false;	
	return true;
}	

/**
 * Check on Required within a group
 * @param string sText. value to be check.
 * @param array group. other dom object to check
 * @return boolean. true = pass | false = fail
 */
function checkRequired(sText, aGroup)
{
	var bResult = isRequired(sText);
	if(bResult) return true;
	if(aGroup.length > 0)
	{
		for (var i =0; i<aGroup.length; i++)
		{
			var aObjCtrl = document.getElementsByName(aGroup[i]);
			for (var j=0; j<aObjCtrl.length ; j++ )
			{
				if(typeof(aObjCtrl[j].value) == 'undefined') continue;
				if(trim(aObjCtrl[j].value) == "") continue;
				bResult = true;
			}
		}
		return bResult;
	}	
}

/**
 * Check on Required within a group
 * @param string sText. value to be check.
 * @param array param. reserve param
 * @return boolean. true = pass | false = fail
 */
function checkRequiredList(oCtrl, sParam, bCoreValidation)
{
	var aParam = sParam.split(",");
	var intMin = aParam[0];
	var intMax = aParam[1];
	if(oCtrl.multiple == false)
	{
		if(oCtrl.length > 1 && intMin > 0) if(oCtrl.value == "" || oCtrl.value == "00") 
		{
			if(bCoreValidation) return vConfig.error.ERR_REQUIRED_SELECT ;
			else return false;
		}
	}
	else
	{
		var iCntSel = 0;
		for(var i=0; i < oCtrl.length ; i++) if(oCtrl.options[i].selected) iCntSel++;
		if(iCntSel < intMin ) 
		{
			if(bCoreValidation) return vConfig.error.ERR_REQUIRED_SELECT_MIN;
			else return false;
		}
		if(iCntSel > intMax)
		{
			if(bCoreValidation) return vConfig.error.ERR_REQUIRED_SELECT_MAX;
			else return false;
		}
	}
	return true;
}

/**
 * Check on Required within a group
 * @param string sText. value to be check.
 * @param array param. reserve param
 * @return boolean. true = pass | false = fail
 */
function checkRequiredCb(oCtrl, sParam, bCoreValidation)
{
	var aParam = sParam.split(",");
	var intMin = aParam[0];
	var intMax = aParam[1];

	var aCtrl = document.getElementsByName(oCtrl.name);
	if(aCtrl.length == 1)
	{
		if(oCtrl.checked == false)
		{	
			if(bCoreValidation) return vConfig.error.ERR_REQUIRED_CHECK;
			return false;
		}
	}
	else
	{
		var iCntSel = 0;
		for(var i=0; i < aCtrl.length ; i++) if(aCtrl[i].checked == true) iCntSel++;

		if(iCntSel < intMin ) 
		{
			if(bCoreValidation) return vConfig.error.ERR_REQUIRED_CHECK_MIN;
			else return false;
		}
		if(iCntSel > intMax)
		{
			if(bCoreValidation) return vConfig.error.ERR_REQUIRED_CHECK_MAX;
			else return false;
		}
	}
	return true;
}

/**
 * Check on Required within a group
 * @param string sText. value to be check.
 * @param array param. reserve param
 * @return boolean. true = pass | false = fail
 */
function checkRequiredRadio(oCtrl, aParam)
{ 
	var sName = oCtrl.name;
	var aElement = document.getElementsByName(sName);
	var bResult = false;
	for (var i =0; i<aElement.length; i++)
	{
		var aObjCtrl = aElement[i];
		if(aObjCtrl.checked == true)bResult = true;		
	}
	return bResult;
}

/**
 * Check on Required within a group
 * @param string sText. value to be check.
 * @param array group. other dom object to check
 * @return boolean. true = pass | false = fail
 */
function checkMatch(sText, aMatch)
{
	if(aMatch.length > 0)
	{
		var bResult = true;
		for (var i =0; i<aMatch.length; i++)
		{
			var aObjCtrl = document.getElementsByName(aMatch[i]);
			for (var j=0; j<aObjCtrl.length ; j++ )
			{
				if(typeof(aObjCtrl[j].value) == 'undefined') continue;
				if(trim(aObjCtrl[j].value) == "") continue;
				if(sText != aObjCtrl[j].value) bResult = false;
			}
		}
		return bResult;
	}
}

//sText=file name
//aConf=<max size>,<format seperate by |>
function checkFile(oCtrl, aConf)
{
	if(oCtrl.form.enctype == '')
	{
		// Developer Msg
		var sMsg = "Missing enctype in form tag";
		alert(sMsg);		
	}

	if(typeof(aConf[0]) != 'undefined')
	{
		//browser not allow to check file size
		var iMaxSize = aConf[0];
	}

	if(typeof(aConf[1]) != 'undefined')
	{
		var sFormat = aConf[1];
	}
	//current not yet solution for checking file at client side without activeX
	return true;
}

var vConfig = {
	//Validation Type
	type: {	
		TYP_REQUIRED: "REQUIRED",				//Required validation 
		TYP_REQUIRED_LIST: "REQUIRED_LIST",		//Required validation 
		TYP_REQUIRED_RADIO: "REQUIRED_RADIO",	//Required validation 
		TYP_REQUIRED_CB: "REQUIRED_CB",			//Required validation 
		TYP_FORMAT: "FORMAT",				//Format validation
		TYP_LENGTH_MIN: "LENGTH_MIN",		//Length min value
		TYP_LENGTH_MAX: "LENGTH_MAX",		//Length max value
		TYP_RANGE_MIN: "RANGE_MIN",		//Range min value
		TYP_RANGE_MAX: "RANGE_MAX",			//Range max value
		TYP_COMPARE_TAG: "COMPARE_TAG",		//Comparison tag
		TYP_COMPARE_VALUE: "COMPARE_VALUE",	//Comparison Target value
		TYP_CUSTOM_FUNC: "FUNCTION",			//Customize function 
		TYP_CUSTOM_PARAM: "PARAM",			//Customize function parameter
		TYP_MATCH: "MATCH",					//Matching
		TYP_FILE: "FILE",					//File
		TYP_TYPE: "TYPE",						//data type
		TYP_DIV: "EDIV",						//error msg div		
		TYP_LABEL: "LABEL",						//error msg label
		TYP_DELIMITER: "DELIMITER"						//error msg label
	},
	
	//Validation Expression
	exp: {
		EXP_INT_POSITIVE	: /^\d+$/ ,			//+ integer 
		EXP_INT_NEGATIVE	: /^-\d+$/ ,		//- integer 
		EXP_INT				: /^-{0,1}\d+$/ ,	//+/- integer 
		EXP_NUMBER_POSITIVE	: /^\d*\.{0,1}\d+$/ ,			//+ number
		EXP_NUMBER_NEGATIVE	: /^-\d*\.{0,1}\d+$/ ,		//- number
		EXP_NUMBER			: /^-{0,1}\d*\.{0,1}\d+$/ ,	//+/- number
		EXP_CURRENCY	: /^\d+(\.\d{0,2})?$/ ,		//+ currency with 2 decimal
		EXP_RATE		: /^\d+(\.\d{0,4})?$/ ,		//+ rate with 4 decimal
		EXP_STRING_ALPHA	: /^([a-zA-Z]+)$/ ,		//Alphabet only
		EXP_STRING_ALPHANUM	: /^([0-9A-Za-z]+)$/ ,		//Alphabet & Numeric only
		EXP_STRING			: /^([0-9A-Za-z_]+)$/ ,	//Alphabet & Numeric & _
		EXP_STRING_NAME		: /^([0-9A-Za-z_\.]+)$/ ,	//Alphabet & Numeric & _
		EXP_YEAR		: /^(19|20)[\d]{2,2}$/ ,	//Year From 1900 - 2099
		/* dd/mm/yyyy | dd-mm-yyyy */
		EXP_DATE_DMY	: /^([1-9]|0[1-9]|[12][0-9]|3[01])[\/|-]([1-9]|0[1-9]|1[012])[\/|-](19|20)\d\d$/ ,
		/* yyyy-mm-dd | yyyy/mm/dd */
		EXP_DATE_YMD	: /^(19|20)\d\d[\/|-]([1-9]|0[1-9]|1[012])[\/|-]([1-9]|0[1-9]|[12][0-9]|3[01])$/ , 
		EXP_DOMAIN : /^([a-z][a-z0-9\-]+(\.|\-*\.))+[a-z]{2,6}$/ ,				//Domain Name
		EXP_URL	   : /^https?:\/\/([-\w\.]+)+(:\d+)?(\/([\w\/_\.]*(\?\S+)?)?)?$/ ,	//Url
		/* Ip address */
		EXP_IPV4   : /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/ ,	
		/* Email */
		EXP_EMAIL  : /^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[@][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[.][a-zA-Z]{2,4}$/ 	
	},
	
	//Validation Error Code
	error: {
		ERR_REQUIRED	: "ERR_REQUIRED",	//required field missing
		ERR_REQUIRED_SELECT : "ERR_REQUIRED_SELECT",	//required field missing - select
		ERR_REQUIRED_SELECT_MAX : "ERR_REQUIRED_SELECT_MAX",	//required field at min - select
		ERR_REQUIRED_SELECT_MIN : "ERR_REQUIRED_SELECT_MIN",	//required field at max - select
		ERR_REQUIRED_CHECK :  "ERR_REQUIRED_CHECK",	//required field missing - check
		ERR_REQUIRED_CHECK_MAX : "ERR_REQUIRED_CHECK_MAX",	//required field at min - select
		ERR_REQUIRED_CHECK_MIN : "ERR_REQUIRED_CHECK_MIN",	//required field at max - select
		ERR_FORMAT		: "ERR_FORMAT",		//format error
		ERR_RANGE_MIN	: "ERR_RANGE_MIN",	//min value is required
		ERR_RANGE_MAX	: "ERR_RANGE_MAX",	//max value exceed
		ERR_COMPARE		: "ERR_COMPARE",	//compare error
		ERR_LENGTH_MIN	: "ERR_LENGTH_MIN",	//min length is required
		ERR_LENGTH_MAX	: "ERR_LENGTH_MAX",	//max length exceed
		ERR_CUSTOM		: "ERR_CUSTOM",		//custom function error
		ERR_INVALID		: "ERR_INVALID",		//invalid input
		ERR_MATCH		: "ERR_MATCH",		//match input
		ERR_FILE_MAXSIZE : "ERR_FILE_MAXSIZE",
		ERR_FILE_EXT : "ERR_FILE_EXT",		
		ERR_FILE_INI_SIZE : "ERR_FILE_INI_SIZE",		//STANDARD PHP FILE UPLOAD ERROR
		ERR_FILE_FORM_SIZE : "ERR_FILE_FORM_SIZE",		//STANDARD PHP FILE UPLOAD ERROR
		ERR_FILE_PARTIAL : "ERR_FILE_PARTIAL",			//STANDARD PHP FILE UPLOAD ERROR
		ERR_FILE_NO_TMP_DIR : "ERR_FILE_NO_TMP_DIR",	//STANDARD PHP FILE UPLOAD ERROR
		ERR_FILE_CANT_WRITE : "ERR_FILE_CANT_WRITE",	//STANDARD PHP FILE UPLOAD ERROR
		ERR_FILE_EXTENSION : "ERR_FILE_EXTENSION"		//STANDARD PHP FILE UPLOAD ERROR
	},

	form : "",
	
	key : "",

	getType:function(sType)
	{
		if(this.isKeyExist() == false) return "";
		var sJs = "var sVal = this.oKey." + sType ;
		eval(sJs);
		if(typeof(sVal) == 'undefined') return "";
		return sVal;
	},	
	
	getError:function(sKey)
	{	
		if(this.isFormExist() == false) return "";
		if(typeof(this.oFrom.error) == 'undefined') return "";
		sKey = sKey.replace("[]", "");
		if(typeof(this.oFrom.error[sKey]) == 'undefined') return "";
		return this.oFrom.error[sKey];	
	},

	getErrorInput:function(sKey)
	{	
		if(this.isFormExist() == false) return "";
		if(typeof(this.oFrom.errorInput) == 'undefined') return "";
		sKey = sKey.replace("[]", "");
		if(typeof(this.oFrom.errorInput[sKey]) == 'undefined') return "";
		return this.oFrom.errorInput[sKey];	
	},
	
	addError:function(sKey, sCode, sInput)
	{	
		if(this.isFormExist() == false) return "";
		if(typeof(this.oFrom.error) != 'object') this.oFrom.error = new Array();
		sKey = sKey.replace("[]", "");
		this.oFrom.error[sKey] = sCode;
		if(typeof(sInput) != 'undefined') 
		{
			if(typeof(this.oFrom.errorInput) != 'object') this.oFrom.errorInput = new Array();
			this.oFrom.errorInput[sKey] = sInput;
		}
	},
	
	killError:function(sKey)
	{
		if(typeof(this.oFrom.error) == 'undefined') return "";
		sKey = sKey.replace("[]", "");
		this.oFrom.error[sKey] = 'undefined';
	},

	getRegex:function(regex)
	{	
		var sJs = "var regex = vConfig.exp." + regex + ";";
		eval(sJs);
		return regex;
	},
	
	isKeyExist:function()
	{
		if(this.isFormExist() == false) return false;
		sKey = this.key.replace("[]", "");
		var sJs = "var oKey = vConfig." + this.form + "." + sKey + ";";
		eval(sJs);
		if(typeof(oKey) != 'object') return false;
		this.oKey = oKey;
		return true;
	},

	isFormExist:function()
	{
		var sJs = "var oForm = vConfig." + this.form + ";";
		eval(sJs);		
		if(typeof(oForm) != 'object') return false;
		this.oFrom = oForm;
		return true;
	}
	
	
};//end config object

	/*---------------------------------------------------------------------------------------------
		Core Validation Part
	---------------------------------------------------------------------------------------------*/

var core_validator = {
	onCheckComponent:function(oCtrl) {
		/**
		 * Check Component upon event
		 * @param object oCtrl. component
		 * @return boolean. true = pass | false = fail
		 */
		if(oCtrl == null) return true;
		var sText = trim(oCtrl.value);
		var sForm = oCtrl.form.name;
		var sKey = oCtrl.name; 

		//get js config form object
		vConfig.form = sForm;
		vConfig.key = sKey;
		var sType = vConfig.getType(vConfig.type.TYP_TYPE);
		var bResult = true;

		//check required
		var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED);
		var aRequired = sRequired.split(","); 
		if(aRequired[0] == 1 || aRequired[0] == 'true')
		{				
			aRequired.shift();
			if (!checkRequired( sText, aRequired ))
			{
				vConfig.addError(sKey, vConfig.error.ERR_REQUIRED);
				bResult = false;
			}
		}

		//check list
		var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED_LIST);			 
		if(sRequired != "")
		{		
			var sRequired = checkRequiredList(oCtrl, sRequired, true );
			if (!(sRequired == true))
			{
				vConfig.addError(sKey, sRequired);
				bResult = false;
			}
		}

		//check checkbox
		var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED_CB);
		if(sRequired != "")
		{		
			var sRequired = checkRequiredCb( oCtrl, sRequired , true);
			if (!(sRequired == true))
			{
				vConfig.addError(sKey, sRequired);
				bResult = false;
				//do uncheck here
				if(sRequired == vConfig.error.ERR_REQUIRED_CHECK_MAX) oCtrl.checked = false;
			}
		}

		//check radio
		var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED_RADIO);
		var aRequired = sRequired.split(","); 
		if(aRequired[0] == 1 || aRequired[0] == 'true')
		{		
			aRequired.shift();
			if (!checkRequiredRadio(oCtrl, aRequired ))
			{
				vConfig.addError(sKey, vConfig.error.ERR_REQUIRED_SELECT);
				bResult = false;
			}
		}

		//skip check on empty value
		if(bResult && sText == '') 
		{
			this.isValidInput(sForm,sKey);
			return true;
		}

		var aValue = new Array(sText);
		//Check for delimiter
		var sDelimiter = vConfig.getType(vConfig.type.TYP_DELIMITER);
		if(sDelimiter != "") var aValue = sText.split(sDelimiter);
	
		for (var i=0; i< aValue.length ; i++ )
		{
			var sSubText = trim(aValue[i]);
			//check format
			var strRegex = vConfig.getType(vConfig.type.TYP_FORMAT);
			if(bResult && strRegex != '')
			{
				strRegex = vConfig.getRegex(strRegex);
				if (!checkRegEx(strRegex,sSubText))
				{		
					vConfig.addError(sKey, vConfig.error.ERR_FORMAT, sSubText);
					bResult = false;
				}
			}

			//check min length
			var intLengthMin = vConfig.getType(vConfig.type.TYP_LENGTH_MIN);
			if(bResult && intLengthMin != '')
			{
				if (!checkLengthMin(intLengthMin, sSubText))
				{
					vConfig.addError(sKey, vConfig.error.ERR_LENGTH_MIN, sSubText);
					bResult = false;
				}
			}

			//check max length
			var intLengthMax = vConfig.getType(vConfig.type.TYP_LENGTH_MAX);
			if(bResult && intLengthMax != '')
			{
				if (!checkLengthMax(intLengthMax, sSubText))
				{
					vConfig.addError(sKey, vConfig.error.ERR_LENGTH_MAX, sSubText);
					bResult = false;
				}
			}

			//check valid
			if(bResult)
			{
				if (!checkValid(sSubText, sType))
				{
					vConfig.addError(sKey, vConfig.error.ERR_INVALID, sSubText);
					bResult = false;
				}
			}

			//check min range
			var mixRangeMin = vConfig.getType(vConfig.type.TYP_RANGE_MIN); 
			if(bResult && mixRangeMin != '')
			{
				if (!checkRangeMin(mixRangeMin, sSubText, sType))
				{
					vConfig.addError(sKey, vConfig.error.ERR_RANGE_MIN, sSubText);
					bResult = false;
				}
			}

			//check max range
			var mixRangeMax = vConfig.getType(vConfig.type.TYP_RANGE_MAX); 
			if(bResult && mixRangeMax != '')
			{
				if (!checkRangeMax(mixRangeMax, sSubText, sType))
				{
					vConfig.addError(sKey, vConfig.error.ERR_RANGE_MAX, sSubText);
					bResult = false;
				}
			}
			
			//check compare
			var strCompareTag = vConfig.getType(vConfig.type.TYP_COMPARE_TAG); 
			var strCompareValue = vConfig.getType(vConfig.type.TYP_COMPARE_VALUE);  
			if(bResult && strCompareTag != '' && strCompareValue != '')
			{ 
				if (!checkCompare(strCompareTag, strCompareValue, sSubText, sType))
				{
					vConfig.addError(sKey, vConfig.error.ERR_COMPARE, sSubText);
					bResult = false;
				}
			}
			if (!bResult) break;
		}//end for each delimiter

		//check match
		var sMatch =  vConfig.getType(vConfig.type.TYP_MATCH); 
		if(bResult && sMatch != '')
		{ 
			if (!checkMatch( sText, sMatch.split(",") ))
			{
				vConfig.addError(sKey, vConfig.error.ERR_MATCH);
				bResult = false;
			}
		}

		//check File
		var sFile =  vConfig.getType(vConfig.type.TYP_FILE); 
		if(bResult && sFile != '')
		{ 
			var sRequired = checkFile( oCtrl, sFile.split(",") );
			if (!(sRequired == true))
			{
				vConfig.addError(sKey, sRequired);
				bResult = false;
			}
		}
		
		//check custom
		var strCustomFunc = vConfig.getType(vConfig.type.TYP_CUSTOM_FUNC); 
		var aParam = vConfig.getType(vConfig.type.TYP_CUSTOM_PARAM);
		aParam = aParam.split(',');
		if(bResult && strCustomFunc != '')
		{	
			if (!eval(strCustomFunc + "(oCtrl, aParam)"))
            {
				vConfig.addError(sKey, vConfig.error.ERR_CUSTOM);            
                bResult = false;
            }
		}

		if(bResult) this.isValidInput(sForm, sKey);
		else this.onHandleErrorByKey(sForm, sKey);
	},//end onCheckComponent
	
	onCheckSubmit:function(oCtrl)
	{
		/**
		 * Check Component upon submit
		 * @param object oCtrl. component
		 * @return boolean. true = pass | false = fail
		 */
		if(oCtrl == null) return true;
		var sForm = oCtrl.form.name;
		vConfig.form = sForm;
		var sKey ;
	
		var sErrMsg ;
		var bError = false;

		var aField = oCtrl.form.getElementsByTagName('*');
		for (var i=0; i<aField.length; i++)
		{
			// Allow for multiple values being assigned to the class attribute
			sKey = aField[i].getAttribute('name');
			if(sKey == null) continue;
			if(sKey == '') continue;

			vConfig.key = sKey;
			
			var sText = trim(aField[i].value);
			
			var sType = vConfig.getType(vConfig.type.TYP_TYPE) ;
		
			//check required
			var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED);
			var aRequired = sRequired.split(","); 
			if(aRequired[0] == 1 || aRequired[0] == 'true')
			{		
				aRequired.shift();
				if (!checkRequired( sText, aRequired ))
				{
					vConfig.addError(sKey, vConfig.error.ERR_REQUIRED);
					bError = true;
					continue;
				}
			}

			//check list
			var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED_LIST);			 
			if(sRequired != "")
			{		
				var sRequired = checkRequiredList( aField[i], sRequired, true );
				if (!(sRequired == true))
				{
					vConfig.addError(sKey, sRequired);
					bError = true;
					continue;
				}
			}

			//check checkbox
			var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED_CB);
			if(sRequired != "")
			{		
				var sRequired = checkRequiredCb( aField[i], sRequired , true);
				if (!(sRequired == true))
				{
					vConfig.addError(sKey, sRequired);
					bError = true;
					continue;
				}
			}

			//check radio
			var sRequired = vConfig.getType(vConfig.type.TYP_REQUIRED_RADIO);
			var aRequired = sRequired.split(","); 
			if(aRequired[0] == 1 || aRequired[0] == 'true')
			{		
				aRequired.shift();
				if (!checkRequiredRadio( aField[i], aRequired ))
				{
					vConfig.addError(sKey, vConfig.error.ERR_REQUIRED_SELECT);
					bError = true;
					continue;
				}
			}

			//skip check on empty value
			if(sText == '') 
			{
				this.isValidInput(sForm,sKey);
				continue;
			}

			var aValue = new Array(sText);
			//Check for delimiter
			var sDelimiter = vConfig.getType(vConfig.type.TYP_DELIMITER);
			if(sDelimiter != "") var aValue = sText.split(sDelimiter);
		
			for (var j=0; j< aValue.length ; j++ )
			{
				var sSubText = trim(aValue[j]);
				var bSubError = false;

				//check format
				var strRegex = vConfig.getType(vConfig.type.TYP_FORMAT);
				if(strRegex != '')
				{
					strRegex = vConfig.getRegex(strRegex);
					if (!checkRegEx(strRegex,sSubText))
					{		
						vConfig.addError(sKey, vConfig.error.ERR_FORMAT, sSubText);
						bSubError = true;
						break;
					}
				}

				//check min length
				var intLengthMin = vConfig.getType(vConfig.type.TYP_LENGTH_MIN); 
				if(intLengthMin != '')
				{
					if (!checkLengthMin(intLengthMin, sSubText))
					{
						vConfig.addError(sKey, vConfig.error.ERR_LENGTH_MIN, sSubText);
						bSubError = true;
						break;
					}
				}

				//check max length
				var intLengthMax = vConfig.getType(vConfig.type.TYP_LENGTH_MAX);
				if(intLengthMax != '')
				{
					if (!checkLengthMax(intLengthMax, sSubText))
					{
						vConfig.addError(sKey, vConfig.error.ERR_LENGTH_MAX, sSubText);
						bSubError = true;
						break;
					}
				}

				//check valid			
				if (!checkValid(sSubText, sType))
				{
					vConfig.addError(sKey, vConfig.error.ERR_INVALID, sSubText);
					bSubError = true;
					break;
				}		

				//check min range
				var mixRangeMin = vConfig.getType(vConfig.type.TYP_RANGE_MIN); 
				if(mixRangeMin != '')
				{
					if (!checkRangeMin(mixRangeMin, sSubText, sType))
					{
						vConfig.addError(sKey, vConfig.error.ERR_RANGE_MIN, sSubText);
						bSubError = true;
						break;
					}
				}

				//check max range
				var mixRangeMax = vConfig.getType(vConfig.type.TYP_RANGE_MAX);
				if(mixRangeMax != '')
				{
					if (!checkRangeMax(mixRangeMax, sSubText, sType))
					{
						vConfig.addError(sKey, vConfig.error.ERR_RANGE_MAX, sSubText);
						bSubError = true;
						break;
					}
				}
				
				//check Compare
				var strCompareTag = vConfig.getType(vConfig.type.TYP_COMPARE_TAG); 
				var strCompareValue = vConfig.getType(vConfig.type.TYP_COMPARE_VALUE);  
				if(strCompareTag != '' && strCompareValue != '')
				{ 
					if (!checkCompare(strCompareTag, strCompareValue, sSubText, sType))
					{
						vConfig.addError(sKey, vConfig.error.ERR_COMPARE, sSubText);
						bSubError = true;
						break;
					}
				}
			}//end foreach delimiter value

			if(bSubError)
			{
				bError = true;
				continue;
			}

			//check match
			var sMatch =  vConfig.getType(vConfig.type.TYP_MATCH); 
			if(sMatch != '')
			{ 
				if (!checkMatch( sText, sMatch.split(",") ))
				{
					vConfig.addError(sKey, vConfig.error.ERR_MATCH);
					bError = true;
					continue;
				}
			}

			//check File
			var sFile =  vConfig.getType(vConfig.type.TYP_FILE); 
			if(sFile != '')
			{ 
				var sRequired = checkFile( aField[i], sFile.split(",") );
				if (!(sRequired == true))
				{
					vConfig.addError(sKey, sRequired);
					bError = true;
					continue;
				}
			}
			
			//check custom
			var strCustomFunc = vConfig.getType(vConfig.type.TYP_CUSTOM_FUNC); 
			var aParam = vConfig.getType(vConfig.type.TYP_CUSTOM_PARAM);
			aParam = aParam.split(',');
			if(strCustomFunc != '')
			{	
				if (!eval(strCustomFunc + "(aField[i], aParam)"))
				{		
					bError = true;
					continue;
				}
			}

			this.isValidInput(sForm, sKey);
		}

		if(bError)
		{
			this.onHandleError(oCtrl.form);
			return false;
		}
		return true;
	}, //end function onCheckSubmit

	isValidInput:function(sForm, sKey)
	{
		/* Public: Clear Error Msg */
		vConfig.form = sForm;
		vConfig.key = sKey;
		sDiv = vConfig.getType(vConfig.type.TYP_DIV);
		setDivMsg(sDiv, '');
		setObjVisibility(sDiv,'false'); 
		vConfig.killError(sKey);
	},
	
	onHandleError:function(oCtrl)
	{
		/* Public: Handle Error By Config */
		var sForm = oCtrl.name; 
		vConfig.form = sForm;

		var sKey;
		var sError;
		var aField = oCtrl.getElementsByTagName('*');
		for (var i=0; i<aField.length; i++)
		{
			// Allow for multiple values being assigned to the class attribute
			sKey = aField[i].getAttribute('name');
			if(sKey == null) continue; 
			sError = vConfig.getError(sKey);
			if(sError == "") continue;		
			this.onHandleErrorByKey(sForm, sKey);
		}		
	},

	onHandleErrorByKey:function(sForm, sKey)
	{
		/* Public: Handle Error By Config */
		vConfig.form = sForm;
		vConfig.key = sKey;

		var sDiv = vConfig.getType(vConfig.type.TYP_DIV);
		var sError = vConfig.getError(sKey);	
		var sMsg = this.getErrorMsg(sError);
		this.showError(sMsg, sDiv);		
	},
	
	getErrorMsg:function(sCode){
		/* Private: Pass Error Code, Handle Msg Variable, Return Error Msg */
		var sMsg = vConfig.getType(sCode) ; 
		if(sMsg == '') 
		{
			var sJs = "var sMsg = validator_error." + sCode + ";";
			eval(sJs);
		}
		if(typeof( sMsg ) == 'undefined') return "";

		var sLbl = vConfig.getType(vConfig.type.TYP_LABEL) ;
		var sVal = "";
		switch (sCode)
		{
			case vConfig.error.ERR_RANGE_MIN:
				sVal = vConfig.getType(vConfig.type.TYP_RANGE_MIN); 
				break;				
			case vConfig.error.ERR_RANGE_MAX:
				sVal = vConfig.getType(vConfig.type.TYP_RANGE_MAX); 
				break;	
			case vConfig.error.ERR_COMPARE:
				var sTag = vConfig.getType(vConfig.type.TYP_COMPARE_TAG); 
				var sValue = vConfig.getType(vConfig.type.TYP_COMPARE_VALUE);  
				sVal = sTag + ' ' + sValue;
				break;	
			case vConfig.error.ERR_LENGTH_MIN:
				sVal = vConfig.getType(vConfig.type.TYP_LENGTH_MIN); 
				break;	
			case vConfig.error.ERR_LENGTH_MAX:	
				sVal = vConfig.getType(vConfig.type.TYP_LENGTH_MAX);
				break;
			case vConfig.error.ERR_MATCH:	
				sVal = vConfig.getType(vConfig.type.TYP_MATCH); 
				sVal = this.getMatchValue(sVal);
				break;	
			case vConfig.error.ERR_REQUIRED_SELECT_MIN:	
				sVal = vConfig.getType(vConfig.type.TYP_REQUIRED_LIST); 
				sVal = sVal.split(",");
				sVal = sVal[0];
				break;
			case vConfig.error.ERR_REQUIRED_SELECT_MAX:	
				sVal = vConfig.getType(vConfig.type.TYP_REQUIRED_LIST); 
				sVal = sVal.split(",");
				sVal = sVal[1];
				break;
			case vConfig.error.ERR_REQUIRED_CHECK_MIN:	
				sVal = vConfig.getType(vConfig.type.TYP_REQUIRED_CB); 
				sVal = sVal.split(",");
				sVal = sVal[0];
				break;
			case vConfig.error.ERR_REQUIRED_CHECK_MAX:	
				sVal = vConfig.getType(vConfig.type.TYP_REQUIRED_CB); 
				sVal = sVal.split(",");
				sVal = sVal[1];
				break;
			case vConfig.error.ERR_FILE_EXT:
				sVal = vConfig.getType(vConfig.type.TYP_FILE); 
				sVal = sVal.split(";");
				sVal = sVal[1];			
				break;
		}
		
		var sKey = vConfig.key;
		var sIpt = vConfig.getErrorInput(sKey);		
		sMsg = sMsg.replace("lbl_label",sLbl);
		sMsg = sMsg.replace("lbl_value",sVal);
		sMsg = sMsg.replace("lbl_input",sIpt);
		return sMsg;
	},

	showError:function (sMsg, sDiv)
	{
		/*Private: Display Error*/ 
		if(sMsg == "") return;
		var oDiv = document.getElementById(sDiv);
		if(oDiv != null) 
		{
			setObjVisibility(sDiv, 'true'); 
			setDivMsg(sDiv, sMsg);			
		}
	},
	
	getMatchValue:function(sVal)
	{
		/*Private: Get Match Value*/ 
		var aVal = sVal.split(",");
		var sValue = "";
		if(aVal.length > 1)
		{
			for(var i=0; i<aVal.length; i++)
			{
				vConfig.key = aVal[i].toString();
				sValue += vConfig.getType(vConfig.type.TYP_LABEL) ;
				if(i < aVal.length -1)  sValue += " , ";
			}
		}
		else
		{
			vConfig.key = aVal.toString();
			sValue += vConfig.getType(vConfig.type.TYP_LABEL) ;
		}		
		return sValue;
	},
	
	unfoundConfig:function()
	{
		var sMsg = validator_error.ERR_TIMEOUT;
		alert(sMsg);
	}
};//end validate object

