/** 
General JavaScript validation functions
*/

/*
validationLevel must have 3 states:
0 - VALIDATE_NONE no elements are validated at all
1 - VALIDATE_PARTIALLY - validation is partial: only filled in elements format is validated, required fields are not checked.
    Used when a form has been loaded but not submitted yet
2 - VALIDATE_ALL_EXCEPT_SPECIAL - validation is made for all elements, except "special" elements (e.g. elements which use AJAX functionality and require special treatment)
3 - VALIDATE_ALL - all elements including special are validated.
    Use when the form is submitted.

validationLevel works with active validation in the following way: when validation is made active,
the elemets is validated on onblur() (or onchange() for select elements) but according to the current validationLevel
    
Also custom validation which is marked as "individual" must be checked only on this particular element onblur() (or onchange() for select elements)
in the case of partially active or active validation or when the form is submitted.
*/
var validationLevel = 0;
var firstReportedElement = false; // the topmost element which has not passed the validation

/**
The AJAX code must be executed only 
when this particular element loses focus
when button submit is clicked
*/

/**
General validation routine

Called 
when the button submit is clicked
*/
function onFormSubmit()
{
 var bSuccess = true;
 
 firstReportedElement = false;
 
 validationLevel = 3; // validate all elements 
 
 makeValidationActive(a_top); // by default we have only 1 array

 bSuccess = validateArray(a_top);
 
 validationLevel = 2; // validate all except "special" elements
 
 if(!bSuccess) // set the focus to the topmost not validated element
 {
 	firstReportedElement.focus();
 }
 
 return bSuccess;
}

/**
Validation procedure which is clicked on onblur/onchange when validation is active

Called 
when Page_ValidationActive===true onblur or onchange (for select element)
*/
function validate(e)
{
	// Event
	e = e || window.event;
	
 var bSuccess = validateArray(a_top,e);
 
 return bSuccess;
}

/**
a - is an object of the type ValidationArrays
func - function which will be called when the elements lose focus
*/
function makeValidationActive(a)
{
	var el;
	
	for(var id in a)
	{
	 el = document.getElementById(id);
	 if('select'==el.tagName.toLowerCase()) // take into accouunt select elements
	 {
	 	if(typeof el.onchange != 'function') // do not rewrite the existing handler (the handler with function validate() must be attached separately in this case)
	 	{
	   el.onchange = validate;
	 	} 
	 } else {
	 	if(typeof el.onblur != 'function') // do not rewrite the existing handler (the handler with function validate() must be attached separately in this case)
	 	{
	   el.onblur = validate; // e.g. document.getElementById("username").onblur = validate;
	 	} 	 	
	 }
	}
} // end function makeValidationActive(a)


/**
Validate the elements according to the given array (e.g. a_top)

e - event object
*/
function validateArray(a,e)
{
 var res = true;
 
 for(var id in a)
 {
  if(!validateElement(id,a[id],e))
  {
  	if(!firstReportedElement && !firstReportedElement.disabled)
  	{
  		firstReportedElement = document.getElementById(id);
  	}
  	
   res = false;
  }
 } // end for(var id in a)
 return res; // validation is successful
} // end function vlaidateArray(...)

/**
Run all types of validation for 1 element
id - element id
a - array defining which types of validation are required
e - event object
*/
function validateElement(id,a,e)
{
 var res = true;
 var retcode;
 var mes;
 for(var chktype in a)
 {
  mes = a[chktype];
  if(chktype==1) {
   // do not validate the "required" element if validationLevel<2
   retcode = (validationLevel>=2)?validateRequired(id,mes):true;
  } else if(chktype==50) {
   retcode = (validationLevel>=1)?validateRange(id,mes):true;
  } else if(chktype==100) {
   retcode = (validationLevel>=1)?validateRegExp(id,mes):true;
  } else if(chktype==101) {
   retcode = (validationLevel>=1)?validateCustom(id,mes,e):true;
  } else {
   alert("VlaidateArray(): Unknown check type: "+chktype);
  }
  if(!retcode)
  {
   res = false;
   break;
  }
 }
 return res;
} // end function Validate(...)

/**
General function trim()
*/
if (typeof String.prototype.trim == "undefined")
{
 String.prototype.trim = function() 
 {
  var str = this.replace(/^\s*/,"");
  return str.replace(/\s*$/, "");
 }
}

/**
Show or hide an error message
id - id of the element for which the check has been run
For this id the related <span> id will be determined
mes - message text to display
display - if true, show the span, if false, hide the span.
*/
function showError(id,mes,display)
{
 // Get id of the related span where the message will be displayed
 var mes_id = 'mes_'+id;
 var el = document.getElementById(mes_id);
 
 if(el!==null)
 {
  if(display)
  {
   el.style.display = "";
   el.innerHTML = mes;
  } else {
   el.style.display = "none";
  }
 }
}

// Validate text - just checking that the field is filled in
function validateRequired(id,mes)
{
 var el = document.getElementById(id);
 // the value
 var str = el.value;

 var valid = false;
 if(el.type==='checkbox') // for checkboxes "checked" attribute must be checked, not the value
 {
  valid = el.checked; // under "required" for checkbox we understand that checkbox must be checked
 } else { // other types of elements
  // check the value and return true or false
  str = str.trim();
  valid = ((str!=null && str!=""))?true:false;
 } // end if

 if(valid)
 {
  showError(id,'',false);
  return true;
 } else {
  // display error message
  showError(id,mes,true);
  return false;
 }
} 

function validateRange(id,a)
{
	var mes = '';
	
 // the value
 var str = document.getElementById(id).value;
 str = str.trim();


 if(str==null || str=="") // for empty strings the "required" validation is used
 {
  showError(id,'',false);  
  return true;  
 } else {
  var type = a[1];
  switch(type)
  {
   case 'date':
    var re1 = new RegExp('^\\d{1,2}/\\d{1,2}/\\d{4}$');
    if(!str.match(re1)) // date format validation
    {
    	// display the message
    	mes = a[0];
    	showError(id,mes,true);
    	return false;
    } else { // range validation
    	var a1 = a[2].split('/');
    	var min = new Date(parseInt(a1[2]),parseInt(a1[0])-1,parseInt(a1[1]));
    	a1 = a[3].split('/');
    	var max = new Date(parseInt(a1[2]),parseInt(a1[0])-1,parseInt(a1[1]));
    	a1 = str.split('/');
 				var val = new Date(parseInt(a1[2]),parseInt(a1[0])-1,parseInt(a1[1]));
 				if(val<min || val>max || parseInt(a1[0])>12 || parseInt(a1[1])>31) // a1 must contain the entered date month and day here
 				{
     	// display the message
     	mes = a[0];
     	showError(id,mes,true);
     	return false;
 				} else {
 					showError(id,'',false);  
      return true;  
 				}
    } // end if
    break;
    
   default:
    mes = 'The range validation of type ' + type + ' is not supported.';
    showError(id,mes,true);
    return false;
  }
 } // end if(str==null || str=="")
 
 return true;
} // end function validateRegExp(id,a)


function validateRegExp(id,a)
{
 // the value
 var str = document.getElementById(id).value;
 str = str.trim();

 // the regular expression
 var regexp = a[1];
 var re1 = new RegExp(regexp);

 if(str==null || str=="" || str.match(re1)) // for empty strings the "required" validation is used
 {
  showError(id,'',false);  
  return true;  
 } else {
  // error message
  var mes = a[0];  
  // display the message
  showError(id,mes,true);
  return false;
 }

 return true;
} // end function validateRegExp(id,a)

/**
Custom validator (by a user function)
a[0] - error message to show
a[1] - validation function
e - even object
*/
function validateCustom(id,a,e)
{
 // the value
 var str = document.getElementById(id).value;
 str = str.trim();

 if(str==null || str=="") // empty strings are validated by the "required" validation is it is set for this element
 {                                   
  showError(id,'',false);
  return true;
 } 
 
 // Ņall the custom function. The custom function will return true or false
 // true - validation successful, clear the error messsage
 // false - validation not successful, show an error message 
 var val = a[1](id,e); 
 if(val) // validated
 {
  showError(id,'',false);
  return true;
 } else { // not validated
  // error message
  var mes = a[0];  
  // display the message
  showError(id,mes,true);
  return false;
 }

 return true;
} // end function validateCustom(id,a)

