
var StartYear = 1900;
var EndYear = 2049;

var StartVersion = 1;
var EndVersion = 9999;

/*		Constants definitions		*/
var gOPTIONAL		= 1;
var gREQUIRED		= 2;

var gDATE			= 4;
var gCHARACTER		= 8;
var gNUMBER			= 16;

var gNSNlength = 16;

var VOID_ELEMENT	= "XX";

var CHECK_INPUT_COUNT         = 1;
var DONT_CHECK_INPUT_COUNT    = 2;

var NO_ELEMENT_IN_FORM_STR  = "יש למלא לפחות ערך אחד בטופס";
var NO_ELEMENT_IN_FORM_CODE = -1;


// object that stores meta information for each input
function metaDataObject(name,type){
	this.name = name;
	this.type = type;
}

/* ---------------- Auxillary methods  -------------------------- */
/*
NAME	: parseMetaData
INPUT	: str	: the meta information regarding a form input object
				  the information is saved in the 'meta' attribute of 
				  the object.
OUTPUT	: a metaDataObject that contains the fields of the title attribute
DESC	: The object type is determined by a 2 letters combination
		  [O:gOPTIONAL;R:gREQUIRED][D:gDATE;C:gCHARACTER;N:gNUMBER] 
REMARK	: The delimeter must be a comma
*/

function parseMetaData(str){
	if (str==VOID_ELEMENT || isEmpty(str))
		tempObj = new metaDataObject(str,0);
	else{
		elementArr = str.split(",");
		if (elementArr.length<=1){
			tempObj = new metaDataObject(str,0);
		}
		else{
  			var tempType = -1;
			var tempTypeStr = elementArr[1];
			if (tempTypeStr.charAt(0) == "R")
				tempType = gREQUIRED;
			else if (tempTypeStr.charAt(0) == "O")
				tempType = gOPTIONAL;
				
			switch (tempTypeStr.charAt(1)){
				case "D" : tempType+=gDATE;break;
				case "C" : tempType+=gCHARACTER;break;
				case "N" : tempType+=gNUMBER;break;
			}		
			tempObj = new metaDataObject(elementArr[0],tempType);
		}
	}
	return tempObj;
}

/*
NAME	: validateForm
INPUT	: A form object and the 'action' requested.
OUTPUT	: an empty string if there are no errors otherwise an array
		  with the meta information about the input that caused the 
		  error
DESC	: The method traverse over the fields of a form, parses the
		  meta information and validates the forms input according to
		  its type.
		  If there is no meta data for a file or the meta data is
		  "XX" than no validation is taken place for that object.
		  If in optional fields there is a value we validate it also.
REMARK	: The following files must be included in the current file:
		  libFunctions.js and validationFunction.js
		  
*/

function validateForm(formObj,mode){
	hasValueCount = 0;
	if (formObj==null)
		return false;
	numOfElements = formObj.length;
	
	var errMessages = new Array();		// Accumulates the error messages
	for (k=0;k<numOfElements;k++){		// traverse
		
		currentObj  = formObj.elements[k];
		
		// Parse the meta data
		elementMeta = parseMetaData(currentObj.meta);
				
		// Check wether there is a need to make a validation   
		if (elementMeta.name!=VOID_ELEMENT || isEmpty(elementMeta.name)){
			
			// get field value
			currentVal = getFieldValue(currentObj);
						
					/*alert(elementMeta.name);
					alert(elementMeta.type);
					alert(currentVal);*/
					
			
			tempResult = true;
			
			// if the value is not empty				
				switch (elementMeta.type){
					
					case gREQUIRED + gDATE		: tempResult = isDate(currentVal);hasValueCount++;break;
					case gOPTIONAL + gDATE		: if (!isEmpty(currentVal)){
														tempResult = isDate(currentVal);hasValueCount++;}
												  break;
					case gREQUIRED + gCHARACTER   : tempResult = !isEmpty(currentVal);hasValueCount++;break;
					case gOPTIONAL + gCHARACTER	: if (!isEmpty(currentVal)){
														tempResult = !isEmpty(currentVal);hasValueCount++;}
												  break;
					case gREQUIRED + gNUMBER		: tempResult = isNumber(currentVal);hasValueCount++;break;
					case gOPTIONAL + gNUMBER		: if (!isEmpty(currentVal)){
														tempResult = isNumber(currentVal);hasValueCount++;}
												  break;
					default : tempResult = true;
				}
			
			if (tempResult==false)
				errMessages[errMessages.length++] = elementMeta; 
		}
				// Inorder to keep track of how many fields have values
				// we have to check also fields with no meta data
				/*else{
					currentVal = getFieldValue(currentObj);			
					if (!isEmpty(currentVal))
						hasValueCount++;	
				}*/
	}
	if (mode==CHECK_INPUT_COUNT && errMessages.length==0 && hasValueCount==0){
		errMessages[errMessages.length++] = new metaDataObject(NO_ELEMENT_IN_FORM_STR,NO_ELEMENT_IN_FORM_CODE);
	}
	return errMessages;
}



/*
NAME	: generateErr
INPUT	: The meta data object of an input that generated the error
OUTPUT	: The generated error message according to the input type (including
		  local errors coming from 'localValidation' function.
DESC	: 
REMARK	: Change this method to customize the error message
*/

function generateErr(errObj){
	tempResult = "";
	switch(errObj.type){
		case gOPTIONAL + gDATE		:
		case gREQUIRED + gDATE		: tempResult = "<br>" + "." + "הערך בשדה" + "&nbsp;&quot;" + errObj.name + "&quot;&nbsp;" + "אינו תאריך חוקי";break;
		case gOPTIONAL + gCHARACTER	:
		case gREQUIRED + gCHARACTER	: tempResult = "<br>" + "." + "הערך בשדה" + "&nbsp;&quot;" + errObj.name + "&quot;&nbsp;" + "ריק";break;
		case gOPTIONAL + gNUMBER		:
		case gREQUIRED + gNUMBER		: tempResult = "<br>" + "." + "הערך בשדה" + "&nbsp;&quot;" + errObj.name + "&quot;&nbsp;" + "אינו מספר חוקי";break; 
		
		case NO_ELEMENT_IN_FORM_CODE: tempResult = errObj.name;
	}
	return tempResult;
}

/*
NAME	: preSubmit
INPUT	: A form object, the mode of the check , the action requested,
          checkmetaflag - which recieves "on" - meaning validateForm
          function shall be executed or "off" - meaning it shall not.
OUTPUT	: The generated error message according to the input type
DESC	: If there is an error than an error message window appears
			with all the errors that were are accumulated in the 
			validateForm method.
		  There are 2 modes that the validation can take place:
		  1.CHECK_INPUT_COUNT  2.DONT_CHECK_INPUT_COUNT		  
REMARK	: The template for the error window is in the errorWindow.htm page
*/

function preSubmit(formObj,mode,action,checklocalflag,checkmetaflag){

	var checkmeta = "";
	var checkLocal = "";
	var i;
	
	if (checklocalflag == "on")  // Will execute the local validation function.
		checkLocal = localValidation(); //Local validation
	
	if (checkmetaflag == "on")  // Will check the Meta-data in form.
			checkmeta = validateForm(formObj,mode);
	
	if (!isEmpty(checkLocal) || !isEmpty(checkmeta)){   //(checkmeta.length>0 || !isEmpty(checkLocal))	
		result ="";
		result+=checkLocal;
		for(i=0;i<checkmeta.length;i++)
			result+=generateErr(checkmeta[i]);
		showMessage(result); }
	else
		submitForm(action);
}

/*
NAME	: localValidation
INPUT	: 
OUTPUT	: the local validation results, as a string
DESC	: 

function localValidation(){
	return "";
}
*/




/*
Name : isYear
Input: an object or a string
Desc : checks wether an object represents a year 
      (between StartYear and EndYear)
*/

function isYear(tempYear){
	if (isNumber(tempYear))
		if (tempYear>=StartYear && tempYear<=EndYear)
			return true;
	//showMessage("The entered Year isn't valid");
	return false;
}

/*
Name : isValidGirsa
Input: an object or a string
Desc : checks wether an object represents a valid Girsa 
      (between StartVersion to EndVersion)
*/

function isValidGirsa(version){
	if (isNumber(version))
		if (version>=StartVersion && version<=EndVersion)
			return true;
	//showMessage("The entered Version (Girsa) isn't valid");			
	return false;
}

/*
Name : isEmpty
Input: an object or a string
Desc : checks wether an object is null or empty
*/
function isEmpty(val){
	if (val==null || val=="")
		return true;
	return false;
}


/*
Name : isNumber
Input: a string
Desc : checks whether a string is a numeric (whole or decimal).
*/
function isNumber(val){
	if (isEmpty(val))
		return false;
	if (isNaN(val)==true)
		return false;
	return true;
}

/*
Name : isWholeNumber
Input: a string
Desc : checks whether a string is a numeric - whole positive number.
*/
function isWholeNumber(val){
	if (isEmpty(val))
		return false;
	if (isNaN(val)==true)
		return false;
	if (val.indexOf(".")!= -1)
		return false;
	if (val <= 0)
		return false;
	return true;
}

/*
Name : isWholeNumberMax10Length
Input: a string
Desc : checks whether a string is a numeric - whole number.
*/
function isWholeNumberMax10Length(val){
	if (isEmpty(val))
		return false;
	if (isNaN(val)==true)
		return false;
	if (val.indexOf(".")!= -1)
		return false;
	if (val.indexOf("-")!= -1)
		return false;
	if (val > 2147483647 || val <= 0)
		return false;
	return true;
}

/*
Name : isDecNumMax10NumBeforeDot
Input: a string
Desc : checks whether a string is a positive numeric - with max 10
	   numbers before dot and 2 after - meaning its a number 
	   between 0 to 9999999999.99
*/
function isDecNumMax10NumBeforeDot(val){
	if (isEmpty(val))
		return false;
	if (isNaN(val)==true)
		return false;
	if (val<=0 || val>9999999999.99)
		return false;
	return true;
}

/*
Name : isDecNumMax11NumBeforeDot
Input: a string
Desc : checks whether a string is a positive numeric - with max 11
	   numbers before dot and 2 after - meaning its a number 
	   between 0 to 99999999999.99 
*/
function isDecNumMax11NumBeforeDot(val){
	if (isEmpty(val))
		return false;
	if (isNaN(val)==true)
		return false;
	if (val<=0 || val>99999999999.99)
		return false;
	return true;
}

/*
Name : isLibDecNumMax11NumBeforeDot
Input: a string
Desc : checks whether a string is a positive numeric - with max 11
	   numbers before dot and 2 after - meaning its a number 
	   between 0 to 22075055187.63 (when transfering the number to a 
	   positive numeric - with max 10 numbers before dot and 2 after,
	   22075055187.63 transfers to the max number - 9999999999.99). 
*/
function isLibDecNumMax11NumBeforeDot(val){
	if (isEmpty(val))
		return false;
	if (isNaN(val)==true)
		return false;
	if (val<=0 || val>22075055187.63)
		return false;
	return true;
}



/*
Name : hasMax2NumAfterDot
Input: a string
Desc : checks whether a string has maximum 2 numbers after the dot.
*/
function hasMax2NumAfterDot(val){
	var lngindex;
	var length;
	var strsubstring;
	var sublength;
	if (isEmpty(val))
		return false;
	if (isNaN(val)==true)
		return false;
	lngindex = val.indexOf(".");
	if (lngindex != -1){  // meaning it's a decimal number
		length = val.length;
		strsubstring = val.substring(lngindex, length);
		sublength = strsubstring.length;
		if (sublength > 3)  // it counts the dot also.
			return false;
	}
	return true;
}

/*
Name : isDate
Input: an object or a string
Desc : checks wether an object/string represent a date
Remark : The date format that is checked is dd/mm/yyyy
*/

function isDate(val){		
	var tempDate;
	var tempDay;
	var tempMonth;
	var tempYear;
	var dataArray;
	var delimeteres = new Array("-","/","."," ");
	// Minimum size is 1/1/00 --> 6 characters	
	if (isEmpty(val) || val.length < 6)
		return false;

	// Checking which delimeter is being used in the string
	for (i=0;i<delimeteres.length;i++)
		if (val.indexOf(delimeteres[i])>-1)
			dataArray = val.split(delimeteres[i]);
	
	// There should be 3 parts to the date
	if (dataArray.length != 3)
		return false;
		
	/* Checking each data part separatly */
	// Checking the year
	
	tempYear = parseInt(dataArray[2]);	
	if (isNaN(tempYear) )
		return false;
	
	// Checking the Month	
	tempMonth = parseInt(dataArray[1]);	
	
	if (isNaN(tempMonth) || tempMonth==0){
			alert(tempMonth);

		return false;}
	
	if (tempMonth<1 || tempMonth>12)
		return false;
	
	
	// Checking the day
	tempDay = parseInt(dataArray[0]);		

	if (isNaN(tempDay) || tempDay==0)
		return false;
	
	// Checking for month that have 31 days per month
	if (((tempMonth==1) || (tempMonth==3) || (tempMonth==5) ||
		(tempMonth==7) ||  (tempMonth==8) || (tempMonth==10) || (tempMonth==12)) 
		&& (tempDay>31))
		return false;		
		
	// Checking for month that have 30 days per month
	if (((tempMonth==4) || (tempMonth==6) || (tempMonth==9) ||
		(tempMonth==11)) && (tempDay>30))
		return false;
	
	// Checking for february
	//If this is a special year there should be 29 days otherwise 28
	if (tempMonth==2)
		if (LeapYear(tempYear)){
			if (tempDay>29)
				return false;
			}
		else
			if (tempDay>28)
				return false;
			
	return true;
}

/*
Name : isDate4y
* the year  must contain 4 digits
Input: an object or a string
Desc : checks wether an object/string represent a date
Remark : The date format that is checked is dd/mm/yyyy
*/
function isDate4y(val){		
	var tempDate;
	var tempDay;
	var tempMonth;
	var tempYear;
	var dataArray;
	var delimeteres = new Array("-","/","."," ");
	// Minimum size is 1/1/1900 --> 8 characters	
	if (isEmpty(val) || val.length < 8){
		return false;
		}
	// Checking which delimeter is being used in the string
	for (i=0;i<delimeteres.length;i++)
		if (val.indexOf(delimeteres[i])>-1)
			dataArray = val.split(delimeteres[i]);
	
	// There should be 3 parts to the date
	if (dataArray.length != 3)
		return false;
		
	/* Checking each data part separatly */
	// Checking the year
	
	if (dataArray[2].length < 4 )
	return false;

	tempYear = parseInt(dataArray[2]);
	
	if (isNaN(tempYear) )
		return false;
		
		
	// Checking the Month	
	tempMonth = parseInt(dataArray[1]);	
	
	if (isNaN(tempMonth) || tempMonth==0){
		return false;}
	
	if (tempMonth<1 || tempMonth>12)
		return false;
	
	
	// Checking the day
	tempDay = parseInt(dataArray[0]);		

	if (isNaN(tempDay) || tempDay==0)
		return false;
	
	// Checking for month that have 31 days per month
	if (((tempMonth==1) || (tempMonth==3) || (tempMonth==5) ||
		(tempMonth==7) ||  (tempMonth==8) || (tempMonth==10) || (tempMonth==12)) 
		&& (tempDay>31))
		return false;		
		
	// Checking for month that have 30 days per month
	if (((tempMonth==4) || (tempMonth==6) || (tempMonth==9) ||
		(tempMonth==11)) && (tempDay>30))
		return false;
	
	// Checking for february
	//If this is a special year there should be 29 days otherwise 28
	if (tempMonth==2)
		if (LeapYear(tempYear)){
			if (tempDay>29)
				return false;
			}
		else
			if (tempDay>28)
				return false;
			
	return true;
}


/*
Name : LeapYear
Input : Checks for februray that the length of the month should be changed
*/
function LeapYear(intYear) {
if (intYear % 100 == 0) {
	if (intYear % 400 == 0) { 
		return true; 
	}
}
else {
	if ((intYear % 4) == 0) { 
		return true; 
	}
}
return false;
}


/*
	Name  : BothFieldsAreFilled(FirstField,SecondField)
	Input : Both fields of which only one can be filled.
	Desc  : returns true if both fields of which only one can be filled - are filled.
*/
function BothFieldsAreFilled(FirstField,SecondField){
	if(!isEmpty(FirstField.value) && !isEmpty(SecondField.value))		
		return true; 
	return false;
}


/*     NEED TO BE WRITTEN!!!!!!!!!!!!!!!!!!!   
/*
Name : isEnglishChar
Input: a string
Desc : checks wether a string is composed of english characters
*/
function isEnglishChar(val){
	if (isEmpty(val))
		return false;
	return true;	
}


/*
Method Name : checkTextAreaMaxLength
Input		: a textarea object
Description : In order that the method should work the maxlength
			  attribute should be defined in the textarea object.
			  The method prevents event bubbeling when the text
			  inside the textarea element exceeds the maxlength.
			  When the text has exceeded the maxlength only the
			  following keystorkes are enabled:
			  Delete(8,Main keyboard), Delete(46),arrows , Home 
			  , end , pageup and pagedown
*/
function checkTextAreaMaxLength(textAreaObj){
	var currentVal = textAreaObj.value;
	var maxLength = parseInt(textAreaObj.maxlength);
	if (currentVal.length<maxLength)
		return true;
	if (event.keyCode == 8 || event.keyCode == 46 || (event.keyCode>=33 && event.keyCode<=40))
		return true;	
	return false;
}
	
	
/*
Method Name : setLangToEnglishOnly
Input		: The input object that you want to limit its language
Description : 
*/
function setLangToEnglishOnly(inputObj){
	 if ((event.keyCode==32) || (event.keyCode>=65 && event.keyCode<=90) || (event.keyCode>=186 && event.keyCode<=190)) {
		inputLen = inputObj.value.length;
		lastChar = inputObj.value.charCodeAt(inputLen-1);
		if (lastChar>122)
			if (inputLen<2)
				inputObj.value = "";
			else{
				inputObj.value = inputObj.value.substring(0,inputLen-1);
			}	
	 }
}


/***********************************************************
Name  : isValidNumber
Input :          
Desc  : The method validates the obj - forcing it be a whole number. 
		Valid Inputs: numbers,arrows,backspace,home,end,delete,page up,
		              page down,insert,tab.
***********************************************************/
function isValidNumber(){   
	//alert(event.keyCode);
	if ((event.keyCode >= 8 && event.keyCode <= 9) || (event.keyCode >= 33 && event.keyCode <= 40) || (event.keyCode >= 45 && event.keyCode <= 46) || (event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105))
		return true;
	return false;	
}

/***********************************************************
Name  : isValidDecNumber
Input :          
Desc  : The method validates the obj - forcing it be a number. 
		Valid Inputs: numbers,arrows,backspace,home,end,delete,page up,
		              page down,insert,tab,dot.
***********************************************************/
function isValidDecNumber(){   
	//alert(event.keyCode);
	if ((event.keyCode >= 8 && event.keyCode <= 9) || (event.keyCode >= 33 && event.keyCode <= 40) || (event.keyCode >= 45 && event.keyCode <= 46) || (event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105) || (event.keyCode == 190) || (event.keyCode == 110))
		return true;
	return false;	
}

/**********************************************************
Name  : isValidTime
Input :          
Desc  : The method validates the obj - forcing it be a whole number. 
		Valid Inputs: numbers,arrows,backspace,home,end,delete,page up,
		              page down,insert,tab,:.
***********************************************************/
function isValidTime(){   
	//alert(event.keyCode);
	if ((event.keyCode >= 8 && event.keyCode <= 9) || (event.keyCode == 186) || (event.keyCode >= 33 && event.keyCode <= 40) || (event.keyCode >= 45 && event.keyCode <= 46) || (event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105))
		return true;
	return false;	
}


/**********************************************************
Name  : isTimeFormat(str)
Input : a string       
Desc  : The method validates the obj - needs to be of format:
		 00:00 or 0:00
**************************************************/
function isTimeFormat(strTime){   
	var length = strTime.length;
			
	if ( length==5 ){  //should be of format 00:00
		if (strTime.charAt(0)>2 || strTime.charAt(0)==":")
			return false;
		
		if (strTime.charAt(1)==":")
			return false;
		
		if (strTime.charAt(0)==2 && strTime.charAt(1)>3)
			return false;
				
		if (strTime.charAt(2)!=":")
			return false;
		
		if (strTime.charAt(3)>5 || strTime.charAt(3)==":")
			return false;
		
		if (strTime.charAt(4)==":")
			return false;
	}
	else{  //should be of format 0:00
		if (strTime.charAt(0)==":")
			return false;
		
		if (strTime.charAt(1)!=":")
			return false;
		
		if (strTime.charAt(2)>5 || strTime.charAt(2)==":")
			return false;	
		
		if (strTime.charAt(3)==":")
			return false;
		
	}
	return true;
}


/***********************************************************
Name  : TimeFormat
Input : an obj           
Desc  : The method enters ':' in the format of; 00:00
***********************************************************/
//	!!!! NOT FINISHED AND NOT IN USE !!!!!
function TimeFormat(obj){
//	alert(event.keyCode)
	if (event.keyCode != 8){
		var length = obj.value.length;
		var tempvalue = obj.value;
		if (event.keyCode != 186){  // meaning != ':'
			if (length==2){
					obj.value = tempvalue+":";
			}
		}
	}		
}

/***********************************************************
Name  : NSNFormat
Input : an obj           
Desc  : The method enters '-' in the format of: 9999-99-999-9999.
***********************************************************/
function NSNFormat(obj){
	if (event.keyCode != 8){
		var length = obj.value.length;
		var tempvalue = obj.value;
		if (length==4 || length==7 || length==11){
				obj.value = tempvalue+"-";
			}
	}		
}


/***********************************************************
Name  : isValidNSN
Input : an obj           
Desc  : The method checks the length and format of the obj. The length
		should be gNSNlength(16) and of format 9999-99-999-9999.
***********************************************************/
function isValidNSN(str){ 
	if (str.length != gNSNlength)
		return false;
	if ((str.charAt(4)!= "-") || (str.charAt(7)!= "-") || (str.charAt(11)!= "-") )
		return false;
	return true;
}		



