// forms_validation.js || source modifier le 7 Mai 2003
// validation routines for forms

//IE et Netscape -> vois aucun probleme pour l'instant mais demande d'info sur la ligne 212
//fonction modifier -> isEmail, isDate, isInteger, isFloat, isSignedFloat, isSignedInteger, isDateEuro

var bIsSubmitted = false;
var callBackFunction = null;
var first_field_in_error = null;
var validation_error_msg = null;



// ***********************************************************************************************
//
// ***********************************************************************************************
function validForm(form)
{
	// This function analyses some properties that can be defined for any inputfield.
	// These properties are:
	//       - eB_validation_type: TypeChecking, RegExp, Mask, Range
	//       - eB_validation_string: isNumeric, isDate, isBirthdate, ...   --> TypeChecking
	//                                .+, ...                               --> RegExp
	//                                AA#####, ...                          --> Mask
	//                                x:y                                   --> Range
	//       - eB_input_required: true/false
	// The validation is not made if and only if the button pressed has the style: eB_validation_required=false
	//  
	// if a global validation needs to be made, a function globalValidation must be defined in the HTML
	// it will be called automatically at the end of the "field per field" validation.
	//
	// If the validation is OK, we check if there is no confirmation box to send
	//
	// If the user has confirmed, then we can submit but before we will grey all the buttons to avoid double posting

	var form_correct = true;
	var input_correct = true;
	
	first_field_in_error = null;
	validation_error_msg = null;
	
	debug = false;

	// Do the form already been submitted ?

	//
	// On recupere le numéro du formulaire	
	for(num_form=0; num_form<document.forms.length && document.forms[num_form].name != form.name; num_form++)
	{
	}
	
	// MODIF le 30 mars 2006
	//
	// Find and replace => document.forms[0] -> document.forms[num_form]
  
   	
	if (bIsSubmitted){
		alert(form.hdValidationDoubleSubmission.value);
		if (debug) alert("The page has already been submitted, return false");
		return false;
	}
	var i =0;
	while (i < form.length && form[i].type != "submit")
	{ 
        i++; 
    }
    
    var boutonEnvoyer = null ;
    if (i<form.length)
    {
        boutonEnvoyer = new validFormulaire(form[i].lang);
    }
    else
    {
        boutonEnvoyer = new validFormulaire("");
    }
	
	if ((boutonEnvoyer.getValue("eB_validation_required") == null)|| (boutonEnvoyer.getValue("eB_validation_required") == "true")){

		for (var i = 0; i < form.length; i++){

			var current_field = form[i];
			input_correct = true;
			
			//
			// input TEXT ou TEXTAREA	
			if (current_field.type == "text" || current_field.type == "textarea"){
				if (navigator.appName == "Microsoft Internet Explorer"){
					modifStyle(current_field, "borderColor", "");
				}
				else{
					modifStyle(current_field, "border-color", "auto");
				}
			}
			
			//
			// input SELECT
			if (current_field.type == "select-one"){
				current_field.offsetParent.style.border = "none";
			}

			// if the field is disabled, then we can skip the validation
			if (current_field.disabled){
				if (debug) alert("Disabled? Field Name: " + current_field.name + "\nValidation type: " + current_field.style["eB_validation_type"] + "()");
				continue;
			}
		
			currentInput = new validFormulaire(current_field.lang);
			
			// first check if input is required
			if ( (currentInput.getValue("eB_input_required") != null) && (currentInput.getValue("eB_input_required") == "true")){
				
				//
				// input TEXT ou TEXTAREA
				if (current_field.type == "text" || current_field.type == "textarea"){
					if (! checkString(current_field, "You must specify a value", false)){
							input_correct = false;
							modifStyle(current_field, "border", "1px solid red");
					}
				}

				if (current_field.type == "select-one"){
					if (current_field.selectedIndex == -1 || current_field.options[current_field.selectedIndex].value == "" ){
							input_correct = false;
							modifStyle(current_field.offsetParent, "border", "1px solid red");
					}
				}
			}
			
			//
			//
			if (currentInput.getValue("eB_validation_type") != null && input_correct){
				// a validation is required

				switch (currentInput.getValue("eB_validation_type")){
					
					case "TypeChecking":
						// This validation implies that the function name is in the eB_validation_string
						if (! eval(currentInput.getValue("eB_validation_string") + "(current_field)") ){
							input_correct = false;
							modifStyle(current_field, "border", "1px solid red");
						}
						break;

					case "RegExp":
						// The pattern is in the eB_validation_string
						// If the field is empty, we do not check the regexp.
						if (!isEmpty(current_field.value)){
							var exp = currentInput.getValue("eB_validation_string");
							// correct a bug in IE when style are passed without '
							// if {} is used in parameter, the } is lost!!!
							// just re-add it at the end
							var ipos = 1;
							var nbBracket = 0; // nbr of { - nbr of }
							var expLength = exp.length;
							while (ipos < expLength) {
								if (exp.charAt(ipos) == "{") {
									nbBracket++;
								}
								if (exp.charAt(ipos) == "}") {
									nbBracket--;
								}
								ipos++;
							}
							if (nbBracket != 0) {
								// ok, if nbBracket == 1, we can close the } but where?
								// assume we can close it at the end
								if (debug) alert(" readd '}' to " + exp);
								exp += "}";
								if (nbBracket != 1) {
									alert(" Validation Regexp : Problem not known with '}'.  Please, inform the eB team ");
								}
								
								
							}
							
							var pattern = new RegExp(exp);
							if (debug) alert(" filtre "+ exp);
							if (!pattern.test(current_field.value)){
								input_correct = false;
								modifStyle(current_field, "border", "1px solid red");
							}
						}
						break;

					case "Mask":
						// eB_validation_string contains a NetDynamics compatible mask composed of A,#,*
						if (debug) alert("current_field.value : "+current_field.value + "\ncurrent_field.style[eB_validation_string] :" +current_field.style["eB_validation_string"]);

						if (! validateMask(current_field.value,currentInput.getValue("eB_validation_string"))){
							input_correct = false;
							modifStyle(current_field, "border", "1px solid red");
						}
						break;

					case "Range":
						// eB_validation_string contains lower-bound:upper-bound
						var part = currentInput.getValue("eB_validation_string").match(/([^:]*):(.*)/);
						if (! checkIntegerInRange(current_field,part[1],part[2],'',true)){
							input_correct = false;
							modifStyle(current_field, "border", "1px solid red");
						}
						break;

					default:
						alert("Unknown eB_validation_type: " + currentInput.getValue("eB_validation_type"));
						break;
				} // end of switch
			}
			
		
			if (!input_correct && first_field_in_error == null) {
				first_field_in_error = current_field;
			}
			form_correct = form_correct && input_correct;
		}

		if (typeof(globalValidation) == "function") {
			form_correct = globalValidation() && form_correct;
			if (!form_correct && first_field_in_error == null) {
				alert("Dear eB Developer: please set the first_field_in_error in your globalValidation function");
				first_field_in_error = document.forms[num_form].elements[0];
			}
		}
		
		//
		// formulaire incorrect
		if (!form_correct){
			if (validation_error_msg == null) {
				//
				// on affiche le message se trouvant dans l'input hidden de nom "hdValidationGenericErrorMessage"
				alert(document.forms[num_form].hdValidationGenericErrorMessage.value);
			}
			else if (validation_error_msg != "") {
 				alert(validation_error_msg);
			}
			
			// else the message is not null but empty.
			// It has been set to "" in the global validation -> the global validation don't want any message to be displayed.

			// we call a call-back function if one has been defined by the page.
			if (callBackFunction != null){
				eval(callBackFunction + "(first_field_in_error)");
			}

			// first_field_in_error may have been set on a field that is disabled. Check to avoid javascript error.
			if (first_field_in_error.disabled == false) {			
				if (first_field_in_error.type == "text" || first_field_in_error.type == "textarea"){
					first_field_in_error.select();
				}
				first_field_in_error.focus();
			}

			if (debug) alert("return form_correct 1 ");
			return form_correct
		}
	}

	// The validation is OK. Is there any confirmation message to send ?
	/*activeButtonName = privateDocumentActiveElement.name.substring(0,privateDocumentActiveElement.name.indexOf("_"));
	for (var i = 0; i < document.forms[num_form].length; i++){

		var current_field = document.forms[num_form].elements[i];
		if (    (current_field.type == "hidden")
			&&  (current_field.name == activeButtonName)
		   ){
			if (!confirm(current_field.value)){
				if (debug) alert("! confirm, return false");
				return false;
			}
			break;
		}
	}*/

	// The user has confirmed. We will disable all visible buttons.
	DisableButtons();

	if (debug) alert("return form_correct 2");
	return form_correct;
}

// ***********************************************************************************************
function validateMask(s,mask) {

		var i = 0;
		var j = mask.length;
//alert("s :"+s+"\nmask:"+mask);

		for(var k = 0; k < j; k++)
		{
			var c = mask.charAt(k);
			switch(c)
			{
				case "*": // '*'
					break;

				case "\\": // '\\' 
					if(s.charAt(i) != mask.charAt(++k))
						return false;
					break;

				case "#": // '#' 
					if(!isDigit(s.charAt(i)))
						return false;
					break;

				case "A": // 'A' 
					if(!isLetter(s.charAt(i)))
						return false;
					break;

				default:
					if(s.charAt(i) != c)
						return false;
					break;

			}
			i++;
		}

		return i == s.length ? true : false;
	}

// ***********************************************************************************************
// Function isXXX(s)
// ***********************************************************************************************
function isEmpty(s) {
	// Check whether string s is empty.
	return ((s == null) || (s.length == 0));
	}

function isWhitespace (s) {
	// Check whether string s is empty or whitespace characters only.
	var whitespace = " \t\n\r";
	var i;
	if (isEmpty(s)) return true;

	// Search through string's characters one by one
	// until we find a non-whitespace character.
	// When we do, return false; if we don't, return true.
	for (i = 0; i < s.length; i++) {
		var c = s.charAt(i);
		if (whitespace.indexOf(c) == -1) return false;
		}
	return true;
	}

function isDigit (c) {
	// Check whether character c is a digit 
	return ((c >= "0") && (c <= "9"));
	}

function isLetter (c) {
	// Check whether character c is a letter 
	return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) );
	}

function isCchar (c) {
	// Check whether character c is a letter, digit or underscore
	return (isLetter(c) || isDigit(c) || c=="_");
	}

function isInteger (s, emptyOK) {
	// isInteger (STRING s [, BOOLEAN emptyOK])
	// Check whether all characters in string s are numbers.
	// Accepts non-signed integers only. Does not accept floating 
	// point, exponential notation, etc.
	// We don't use parseInt because that would accept a string
	// with trailing non-numeric characters.
	if (isInteger.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	var exp = /^[\d]+$/;
	return exp.test(s);
	}

function isFloat (s, emptyOK) {
	// isFloat (STRING s [, BOOLEAN emptyOK])
	// Check whether all characters in string s are numbers.
	// Decimal separator '.' or ',' are also accepted.
	// the , is only accepted once (can only be used as decimal separator)
	// if . is used more than once, it is the grouping character
	// The size of group caracters must be 3.

	if (isFloat.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	var exp = /^[\d]+[,.][\d]+$/;
	return exp.test(s);
}

function isSignedFloat (s, emptyOK)
{
	// isSignedFloat (STRING s [, BOOLEAN emptyOK])
	// first character is allowed to be + or - as well.
	if (isSignedFloat.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	var exp = /^[+-]?[\d]+[,.][\d]+$/;
	return exp.test(s);
}

function isSignedInteger (s, emptyOK) {
	// isSignedInteger (STRING s [, BOOLEAN emptyOK])
	// Check whether all characters are numbers; 
	// first character is allowed to be + or - as well.
	// Does not accept floating point, exponential notation, etc.
	// We don't use parseInt because that would accept a string
	// with trailing non-numeric characters.
	if (isSignedInteger.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	var exp = /^[+-]?[\d]+$/;
	return exp.test(s);
}

function isPositiveInteger (s, emptyOK) {
	// isPositiveInteger (STRING s [, BOOLEAN emptyOK])
	// Check whether string s is an integer > 0.
	if (isPositiveInteger.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	return (isSignedInteger(s, emptyOK) && (parseInt (s,10) > 0));
	}

function isNonnegativeInteger (s, emptyOK) {
	// isNonnegativeInteger (STRING s [, BOOLEAN emptyOK])
	// Check whether string s is an integer >= 0.
	if (isNonnegativeInteger.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	return (isSignedInteger(s, emptyOK) && (parseInt (s,10) >= 0));
	}

function isIntegerInRange (s, a, b, emptyOK) {
	// isIntegerInRange (STRING s, INTEGER a, INTEGER b [, BOOLEAN emptyOK])
	// Check whether string s is an integer within the range of integer arguments a and b, inclusive.
	if (isIntegerInRange.arguments.length < 4) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	// Catch non-integer strings to avoid creating a NaN below,
	// which isn't available on JavaScript 1.0 for Windows.
	if (!isSignedInteger(s, false)) return false;

	// Now, explicitly change the type to integer via parseInt
	// so that the comparison code below will work both on 
	// JavaScript 1.2 (which typechecks in equality comparisons)
	// and JavaScript 1.1 and before (which doesn't).
	var num = parseInt (s,10);
	return ((num >= a) && (num <= b));
	}

function isCsym (s, emptyOK) {
	// Check whether string c is a valid C symbol
	if (isCsym.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	var i;
	for (i = 0; i < s.length; i++) if (!isCchar(s.charAt(i))) return false;
	return true;
	}

function isInternationalPhoneNumber (s, emptyOK) {
	// Check whether string s is a valid international phone number.
	// Must be digits only; any length OK. May be prefixed by + character.
	// NOTE: A phone number of all zeros would not be accepted.
	//
	// NOTE: Strip out any delimiters (spaces, hyphens, parentheses, etc.)
	// from string s before calling this function.  You may leave in 
	// leading + character if you wish.
	if (isInternationalPhoneNumber.arguments.length < 2) emptyOK = false;
	var expression = /[0-9()+:]*/;
	if (isEmpty(s)) return emptyOK;

	return (expression.test(s));
	}

function isEmail(s, emptyOK)
{
	if (isEmail.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	/* Type : nom@domaine.ext */
	var expression = /^[^@\s]+@([\w\-\~]+\.){1,4}[a-zA-Z]{2,4}$/;
	/* Type :nom@ip */
	var expression2=  /^[^@\s]+@(([10]?\d{0,2}|2[0-4]\d|25[0-5])\.){3}([10]?\d{0,2}|2[0-4]\d|25[0-5])$/;

	return  (expression.test(s) || expression2.test(s)) ;
}

function isYear (s, emptyOK) {
	// isYear (STRING s [, BOOLEAN emptyOK])
	// Check whether string s is a valid Year number.  Must be 4 or 2 digits.
	// For Year 2000 compliance, you are advised to use 4-digit year numbers everywhere.
	if (isYear.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	if (!isNonnegativeInteger(s)) return false;
	return (s.length == 4);
	}

function isMonth (s, emptyOK) {
	// isMonth (STRING s [, BOOLEAN emptyOK])
	// Check whether string s is a valid month number between 1 and 12.
	if (isMonth.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	return isIntegerInRange (s, 1, 12);
	}

function isDay (s, emptyOK) {
	// isDay (STRING s [, BOOLEAN emptyOK])
	// Check whether string s is a valid  day number between 1 and 31.
	if (isDay.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	return isIntegerInRange (s, 1, 31);
	}

function isDate (year, month, day) {
	// isDate (STRING year, STRING month, STRING day)
	// Check whether string arguments year, month, and day form a valid date.
	// catch invalid years (not 2- or 4-digit) and invalid months and days.
	var expr_jour = /^([0]?[1-9]|[12][0-9]|3[01])$/;
	var expr_mois = /^([0]?[1-9]|1[0-2])$/;
	var expr_annee = /^(\d{4})$/;
	var error = true;

	if (expr_jour.test(day) && expr_mois.test(month) && expr_annee.test(year)){
		var datum = new Date(Number(year), Number(month)-1, Number(day));
		if ( datum.getMonth() != (Number(month)-1)){
			error = false;
		}
	}
	else{
		error = false;
	}

	return error;
}

function isDateEuro (s, emptyOK) {
	// isDateEuro (STRING s)
	// Check whether string s is a valid european date: dd-mm-yyyy
	// day AND month can have only 1 digit. e.g. 1/12/2000, 15/1/1962, 9/2/1961
	if (isDateEuro.arguments.length < 2) emptyOK = false;
	if (isEmpty(s)) return emptyOK;

	var expression = new RegExp("[-\/]"); // DD-MM-YYYY DD/MM/YYYY

	var tab = s.split(expression);
	return isDate (tab[2], tab[1], tab[0]);
}

function isBelgianBankAccount(s) {
	// isBelgianBankAccount (String s)
	// Check whether all characters in o object's value represent a valid
	// belgian bank account.
	// the format of the string is: xxx-xxxxxxx-xx or xxxxxxxxxxxx
	if (isEmpty(s)) return true;
	if ((!validateMask(s,"###-#######-##")) && (!validateMask(s,"############"))) return false;
	if (validateMask(s,"###-#######-##")) {
		var part1 = s.substr(0,3) + s.substr(4,7);
		var part2 = s.substr(12,2);
		if (part2 != (part1 % 97)) return false;
	}
	else if (validateMask(s,"############")) {
		var part1 = s.substr(0,10);
		var part2 = s.substr(10,2);
		if (part2 != (part1 % 97)) return false;
	}
	return true; 
}

// ***********************************************************************************************
// function check
// ***********************************************************************************************
function checkString (theField, s, emptyOK) {
	// checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
	// Check that string theField.value is not all whitespace.

	// Next line is needed on NN3 to avoid "undefined is not a number" error
	// in equality comparison below.
	if (checkString.arguments.length < 3) emptyOK = false;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (isWhitespace(theField.value)) return warnEmpty (theField, s);
	else return true;
	}

function checkIntegerInRange (theField, a, b, s, emptyOK) {
	// checkIntegerInRange (TEXTFIELD theField, INT a, INT b, STRING s, [, BOOLEAN emptyOK==false])
	// Check that string theField.value is an integer in the range a-b inclusive.

	if (checkIntegerInRange.arguments.length < 5) emptyOK = false;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (!isIntegerInRange(theField.value,a,b)) return warnInvalid (theField, s);
	else return true;
	}

function checkRadio (theField, s, emptyOK) {
	// checkRadio (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
	// Check that radio theField.value is set.

	if (checkRadio.arguments.length < 3) emptyOK = false;
	var i;
	for (i=0; i<theField.length; i++) if (theField[i].checked) return true;
	if (emptyOK == true) return true;
	alert(s);
	return false;
	}

function checkUserid (theField, s, emptyOK) {
	// checkUserid (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
	// Check that string theField.value is a valid userid.

	if (checkUserid.arguments.length < 3) emptyOK = false;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (isWhitespace(theField.value)) return warnEmpty (theField, s);
	if (!isCsym(theField.value)) return warnInvalid (theField, s);
	else return true;
	}

function checkInternationalPhone (theField, s, emptyOK) {
	// checkInternationalPhone (TEXTFIELD theField [, BOOLEAN emptyOK==false])
	// Check that string theField.value is a valid International Phone.

	if (checkInternationalPhone.arguments.length < 3) emptyOK = false;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (!isInternationalPhoneNumber(stripCharsInBag(theField.value,"+().- "))) return warnInvalid (theField, s);
	else return true;
	}

function checkEmail (theField, s, emptyOK) {
	// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false])
	// Check that string theField.value is a valid Email.

	if (checkEmail.arguments.length < 3) emptyOK = false;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (!isEmail(theField.value, false)) return warnInvalid (theField, s);
	else return true;
	}

function checkDate (yearField, monthField, dayField, sy, sm, sd, s, emptyOK) {
	// checkDate (yearField, monthField, dayField, sy, sm, sd, s [, BOOLEAN emptyOK==false])
	// Check that yearField.value, monthField.value, and dayField.value form a valid date.

	if (checkDate.arguments.length < 8) emptyOK = false;
	if (!isYear(yearField.value)) return warnInvalid (yearField, sy);
	if (!isMonth(monthField.value)) return warnInvalid (monthField, sm);
	if ((emptyOK == true) && isEmpty(dayField.value)) return true;
	if (!isDay(dayField.value)) return warnInvalid (dayField, sd);
	if (isDate (yearField.value, monthField.value, dayField.value))	return true;
	alert (s);
	return false;
	}

function checkDateEuro (lang, theField, s, emptyOK) {
	// checkDate (theField, s [, BOOLEAN emptyOK==false])
	// Check that theField.value form a valid date.

	if (checkDateEuro.arguments.length < 3) emptyOK = false;
	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	if (!isDateEuro (theField.value)) return warnInvalid(theField,s);
	theField.value = fmtDate(lang, theField.value.substr(6), theField.value.substr(3,2), theField.value.substr(0,2));
	return true;
	}

//----------------------------------------------------------------------
// Check if the key pressed is a digit.
// return true if it is a digit and false if not a digit
// must be called during onKeyPress (not onKeyDown).
//----------------------------------------------------------------------
function checkDigit() 
{
	var key = event.keyCode;

	if (48 <= key && key <= 57) {
		// digit
		return true;
	}

	if (key == 13) {
		// Return key
		return true;
	}

	if (key == 27) {
		// ESCAPE key
		return true;
	}

	return false;
}

//-----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------
// Check if the key pressed is a digit.
// must be called during onKeyPress (not onKeyDown).
//----------------------------------------------------------------------
function checkDigitOnKeyPress() 
{
	if (checkDigit() == true) {
		return true;
	}

	event.returnValue = false;
	event.cancelBubble = true;
	return false;
}

//----------------------------------------------------------------------
// Check if the key pressed is a digit.
// must be called during onKeyPress (not onKeyDown).
//----------------------------------------------------------------------
function checkIntegerOnKeyPress() 
{
	return checkDigitOnKeyPress();
}

//----------------------------------------------------------------------
// Check if the key pressed is a digit a + or -
// must be called during onKeyPress (not onKeyDown).
//----------------------------------------------------------------------
function checkSignedIntegerOnKeyPress()
{
	if (checkDigit() == true) return true;

	var key = event.keyCode;

	// accept + and -
	if (key == 43 || key == 45) {
		return true;
	}

	event.returnValue = false;
	event.cancelBubble = true;
	return false;
}

//----------------------------------------------------------------------
// Check if the key pressed is a digit, '+', '-', '.' or ','
// must be called during onKeyPress (not onKeyDown).
//----------------------------------------------------------------------
function checkFloatOnKeyPress() 
{
	if (checkDigit() == true) return true;

	var key = event.keyCode;

	// accept + and -
	if (key == 43 || key == 45) {
		return true;
	}

	// accept . and ,
	if (key == 46 || key == 44) {
		return true;
	}

	event.returnValue = false;
	event.cancelBubble = true;
	return false;
}

//----------------------------------------------------------------------
// Check if the key pressed is a digit, '+', '-', '.' or ','
// must be called during onKeyPress (not onKeyDown).
//----------------------------------------------------------------------
function checkDateOnKeyPress() 
{
	if (checkDigit() == true) return true;

	var key = event.keyCode;

	// accept /
	if (key == 47) {
		return true;
	}

	event.returnValue = false;
	event.cancelBubble = true;
	return false;
}

// ***********************************************************************************************
// validation routines
// ***********************************************************************************************
function isNumeric (o) {
	// isNumeric (OBJECT o)
	// Check whether all characters in o object's value are numbers.
	// Accepts non-signed integers only. Does not accept floating 
	// point, exponential notation, etc.
	// We don't use parseInt because that would accept a string
	// with trailing non-numeric characters.
	return (isInteger(o.value,true));	
}

function isPhoneNumber(o)
{		
	// authorized characters
	// numéric + ( ) : /
	var expr = /^[0-9\+\.\/ ]*$/;	return expr.test(o.value);
}

function isSignedNumeric (o) {
	// isNumeric (OBJECT o)
	// Check whether all characters in o object's value are numbers.
	// Accepts signed integers. Does not accept floating 
	// point, exponential notation, etc.
	// We don't use parseInt because that would accept a string
	// with trailing non-numeric characters.
	return (isSignedInteger(o.value,true));	
}

function isValidEmail (o) {
	// isEmail (OBJECT o)
	// Check if it's a valid email
	return (isEmail(o.value,true));	
}

function isBankAccount(o) {
	// isBankAccount (OBJECT o)
	// Check whether all characters in o object's value represent a valid bank account.
	if (isEmpty(o.value)) return true;

	// at present time, only belgian bank account supported
	return isBelgianBankAccount(o.value);
}

function isVAT (o) {
	// isVAT (OBJECT o)
	// Check whether the o object's value is a valid VAT number.
	// The following format is allowed: [a-zA-Z]{2}\d{4,16}  || \d{4,16}
	// For BE: the last two numbers are the result of : 97 - modulo(the remaining part/97)
	// Other countries are not yet implemented

	if (isEmpty(o.value)) return true;

	var result;
	var VATnumber;
	var country = "BE";
	var pattern1 = /([a-zA-Z]{2})(\d{4,16})/;
	var pattern2 = /(\d{4,16})/;
	var patternForRemainder = /^(.*)(\d{2})$/;

	if ((result=pattern1.exec(o.value)) == null){
		if ((result=pattern2.exec(o.value)) == null){
			// format invalid
			return false;
		} else {
			VATnumber = patternForRemainder.exec(result[1]);
		}
	} else {
		country = result[1].toUpperCase();
		VATnumber = patternForRemainder.exec(result[2]);
		}
	switch (country) {
		case "BE":
			if (VATnumber[2] != (97 - (VATnumber[1] % 97))){
				return false;
			}
			break;

				default:
					break;
	}

	return true;	
}

function isDecimal (o) {
	// isDecimal (OBJECT o)
	// Check whether all characters in o object's value are floating numbers.
	var startPos = 0;
	if ((o.value.charAt(0) == "-") || (o.value.charAt(0) == "+")) startPos = 1;    
	return (isFloat(o.value.substring(startPos, o.value.length), true));
}

function isValidDate (o) {
	// isValidDate (OBJECT o)
	// Check whether object o value is a valid date: dd/mm/yyyy, d/mm/yyyy, dd/m/yyyy, d/m/yyyy or ddmmyyyy
	// Anyway, the object's value will be replaced by dd/mm/yyyy

	if (isEmpty(o.value)) return true;

	// check if it's only 8 digits, then reformat
	if (o.value.length == 8 && isInteger(o.value, false)) {
		o.value = o.value.substr(0,2) + "/" + o.value.substr(2,2) + "/" + o.value.substr(4);
	} 

	var c;
	var day		= "";
	var month	= "";
	var year	= "";
	var i = 0;
	var s = o.value;

	c = s.charAt(i++);
	day += c;

	c = s.charAt(i++)
	if (c != '/') {
		day += c;
		c = s.charAt(i++);
	}
	
	if (c != '/') {
		return false;
	}
	
	c = s.charAt(i++);
	month += c;

	c = s.charAt(i++)
	if (c != '/') {
		month += c;
		c = s.charAt(i++);
	}
	
	if (c != '/') {
		return false;
	}

	year = s.substring(i);

	if (!isDate (year, month, day)) {
		return false;
	}

	if (o.value.length != 10) {
		// reformat the date to be sure to have 2 char for the day and the month and 4 for the year.
		o.value = fmtDate("fr", year, month, day);
	}

	return true;
}


function isBeforeToday(o)
{
	// Checks whether the given date is strictky before today. => from prehistory till yesterday
	// Following date format are allowed: (ddmmyyyy or dd/mm/yyyy)
	//

	if (isEmpty(o.value)) return true;
	if (!isValidDate(o)) return false;

	givenDate = new Date(o.value.substr(6,4), o.value.substr(3,2) - 1, o.value.substr(0,2), 23,59,59,999);
	now = new Date();

	if (givenDate.getTime() < now.getTime()){
		return true;
	}
	
	return false;
}

function isNotBeforeToday(o)
{
	// Checks whether the given date is not strictly before today. => from today till infinity.
	// Following date format are allowed: (ddmmyyyy or dd/mm/yyyy)
	//

	if (isEmpty(o.value)) return true;
	if (!isValidDate(o)) return false;

	givenDate = new Date(o.value.substr(6,4), o.value.substr(3,2) - 1, o.value.substr(0,2), 23,59,59,999);
	now = new Date();

	if (givenDate.getTime() >= now.getTime()){
		return true;
	}
	
	return false;
}

function isAfterToday(o)
{
	// Checks whether the given date is not strictly after today. => from tomorrow till infinity
	// Following date format are allowed: (ddmmyyyy or dd/mm/yyyy)
	//

	if (isEmpty(o.value)) return true;
	if (!isValidDate(o)) return false;

	givenDate = new Date(o.value.substr(6,4), o.value.substr(3,2) - 1, o.value.substr(0,2), 0, 0, 0, 0);
	now = new Date();
		
	if (givenDate.getTime() > now.getTime()){
		return true;
	}
	
	return false;
}

function isNotAfterToday(o)
{
	// Checks whether the given date is not strictly after today. => from prehistory till today
	// Following date format are allowed: (ddmmyyyy or dd/mm/yyyy)
	//

	if (isEmpty(o.value)) return true;
	if (!isValidDate(o)) return false;

	givenDate = new Date(o.value.substr(6,4), o.value.substr(3,2) - 1, o.value.substr(0,2), 0, 0, 0, 0);
	now = new Date();
		
	if (givenDate.getTime() <= now.getTime()) {
		return true;
	}
	
	return false;
}

// ***********************************************************************************************
//
// ***********************************************************************************************
function makeArray(n) {
	//*** BUG: If I put this line in, I get two error messages:
	//(1) Window.length can't be set by assignment
	//(2) daysInMonth has no property indexed by 4
	//If I leave it out, the code works fine.
	//   this.length = n;
	for (var i = 1; i <= n; i++) {this[i] = 0} 
	return this;
	}

function daysInFebruary (year) {
	// daysInFebruary (INTEGER year)
	// February has 29 days in any year evenly divisible by four,
	// EXCEPT for centurial years which are not also divisible by 400.
	return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
	}

function fullYear (year) {
	// fullYear (INTEGER year)
	if (year >= 100) return year;
	var today = new Date();
	var toyear = today.getYear();
	if (toyear < 100) return year + 1900;
	else return year + toyear - toyear%100;
	}

function stripCharsInBag (s, bag) {
	// Removes all characters which appear in string bag from string s.
	var i;
	var returnString = "";

	for (i = 0; i < s.length; i++) {   
		var c = s.charAt(i);
		if (bag.indexOf(c) == -1) returnString += c;
		}

	return returnString;
	}

function fmtDate (lang, yy, mm, dd) {
	// isDate (lang, STRING yy, STRING mm, STRING dd)
	if (!isDate(yy,mm,dd)) return "";
	var y = "0000" + fullYear(parseInt(yy,10));  y = y.substr(y.length-4,4);
	var m = "00" + mm;  m = m.substr(m.length-2,2);
	var d = "00" + dd;  d = d.substr(d.length-2,2);
	if (lang=="en") return m + "/" + d + "/" + y;
	if (lang=="fr") return d + "/" + m + "/" + y;
	if (lang=="de") return d + "." + m + "." + y;
	return m + "/" + d + "/" + y;
	}

function warnEmpty (theField, s) {
	// warnEmpty (TEXTFIELD theField, STRING s)
	// Notify user that required field theField is empty.
//	alert(s);
//	theField.focus();
	return false;
	}

function warnInvalid (theField, s) {
	// warnInvalid (TEXTFIELD theField, STRING s)
	// Notify user that contents of field theField are invalid.
//	alert(s);
//	theField.focus();
//	theField.select();
	return false;
	}

function getRadioButtonValue (radio) {
	// Get checked value from radio button.

	for (var i = 0; i < radio.length; i++) if (radio[i].checked) return radio[i].value;
	return "";
	}

function goBody() {
	// activate the first element in the first form

	if (document.forms[num_form]==null) return;
	if (document.forms[num_form].elements[0]==null) return;
	document.forms[num_form].elements[0].focus();
	}

function validHREF() 
{
	if (bIsSubmitted){
		alert(document.forms[num_form].hdValidationDoubleSubmission.value);
		//alert("The page has already been submitted");
		return false;
	}
	
	DisableButtons(); // side-effect: set bIsSubmitted (the side effect don't work in the pgEmpty because there is no button).
	bIsSubmitted = true;                

	return true;
}

function DisableButtons() 
{
	for (var i = 0; i < document.forms[num_form].length; i++){

		var current_field = document.forms[num_form].elements[i];
		if ( (current_field.type == "submit") || (current_field.type == "reset")){
			bIsSubmitted = true;                
			current_field.style.color = "THREEDSHADOW";
		}
	}
	// The disabling is valid for 270 seconds
	EnableTimeOutID = window.setTimeout("EnableButtons()",270000);
}

function EnableButtons() 
{
		// After a certain laps of time, we have to re-enable the visible buttons
		for (var i = 0; i < document.forms[num_form].length; i++){
			var current_field = document.forms[num_form].elements[i];
			if ( (current_field.type == "submit") || (current_field.type == "reset")){
				bIsSubmitted = false;                
				current_field.style.color = "black";
			}
		}
		window.clearTimeout("EnableTimeOutID");
}

function clickButton(name)
{
	var bHide=false;
	var el=document.all[name + "_onWebEvent(" + name + ")"];
	if (typeof(el) == "undefined") {
		el=document.all[name];
		if (typeof(el) == "undefined") {
			return false;
		}
	}
	if (el.style.visibility == "hidden") {
		el.style.visibility = "visible";
		bHide=true;
	}

	documentActiveElement = el; // for validation.
	el.focus();
	el.click();

	if (bHide) {
		el.style.visibility = "hidden";
	}
	
	return true;
}

//----------------------------------------------------------------------
// this is the equivalent of the javascript function "encode" . But the "encode" function is not doing well on IE 4.01
//----------------------------------------------------------------------
function urlEncode(url) {
	var newUrl = "";
	var	i;
	
	for (i = 0; i < url.length; i++) {
		c = url.charAt(i);
		if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9')) {
			newUrl += c;
		}
		else if (c == ' ') {
			newUrl += '+';
		}
		else {
			newUrl += '%' + url.charCodeAt(i).toString(16);
		}
	}
	
	return newUrl;	
}
