function formValidator(theForm,lang,pageSection){

    if ( document.getElementById('server_msg_paragraph') ) {
		document.getElementById('server_msg_paragraph').className = 'hide'
	}
	
	// VALIDATES ALL FORM ELEMENTS WITHIN A FORM USING THE validInput CHECK ON SUBMIT OF THE FORM
	var lang = document.body.id;
	var thisFormFails = false;
	var errorMssgAr = "<strong>هناك بعض الأخطاء في ارسال بيانات هذه الصفحة:</strong> الرجاء مراجعة المُدخلات المشار اليها بلون مختلف.";
	var errorMssgEn = "<strong>There was a problem submitting this form:</strong> Please review the highlighted fields below and try submitting again.";
	var errorMssgFr = "<strong>Une erreur s'est produite lors de la soumission du formulaire:</strong> Veuillez vérifier les champs ci-dessous.";
	switch(lang) {
		case "ar" :
			var errorMssg = errorMssgAr;
		break
		case "fr" :
			var errorMssg = errorMssgFr;
		break
		default :
			var errorMssg = errorMssgEn;
	}
	var elementsTypeArray = new Array("select","input","textarea"); // array of all elements to validate
	for (var x = 0; x < elementsTypeArray.length; x++){
		var theElements = theForm.getElementsByTagName(elementsTypeArray[x]); // run through elements array in the form
		for (var i = 0; i < theElements.length; i++){
			var thisElement = theElements[i];
			if (thisElement.tagName != "SELECT" &&
			thisElement.getAttribute("type") != "checkbox" &&
			thisElement.getAttribute("type") != "radio" &&
			thisElement.getAttribute("type") != "file" ) thisElement.value = trim(thisElement.value) // ie trims select elements as well
			if (!validInput(thisElement)) thisFormFails = true; // the validation function
		}
	}
	if (!thisFormFails){
		return true;
	} else {
		if (!document.getElementById("submit-alert-message")){
			var formErrorMssg = document.createElement("P");
			formErrorMssg.id = "submit-alert-message";
			formErrorMssg.className = "alert";
			formErrorMssg.innerHTML = errorMssg;
			theForm.insertBefore(formErrorMssg,theForm.firstChild)
		} else {
			document.getElementById('submit-alert-message').className = 'alert';
		}
		if (!pageSection) {var pageSection = '';}
		document.location.href='#'+pageSection;
		return false;
	}
}

function inputValidator(){
	// VALIDATES A FORM ELEMENT USING THE validInput CHECK ONBLUR PER ELEMENT
	
	var elementsTypeArray = new Array("select","input","textarea"); // array of all elements to validate
	for (var i = 0; i < elementsTypeArray.length; i++){
		var theElements = document.getElementById("content").getElementsByTagName(elementsTypeArray[i]); // run through elements array in the form
		for (var j = 0; j < theElements.length; j++){
			var thisElement = theElements[j]; // run through elements array in the form
			thisElement.onfocus = function(){
				this.style.background = "#ffd";
				if (this.className.indexOf("cleartext") > -1 && this.value == this.defaultValue) this.value = "";
			}
			thisElement.onblur = function(){
				this.style.background = "#fff";
				if (this.className.indexOf("cleartext") > -1 && this.value == "") this.value = this.defaultValue; // note: elements with "cleartext" do not go through validation here
				else validInput(this);
			}
		}
	}	
}

function validInput(theElement){
	// CHECKS IF A FORM ELEMENT IS VALID ACCORDING TO THE FOLLOWING VALUES IN THE FORM ELEMENT CLASS ATTRIBUTE
	// 	req = required field
	// 	alpha = alpha-numeric field (no spaces, punctuation, etc.)
	// 	number = numeric field
	// 	mutiNumber = numeric fields sperated by spaces or carriage return
	//		min-n = minumum number of characters is n (where n is a specified number)
	//		max-n = string: maximum number of characters is n (where n is a specified number)
	//		max-n = multiselect: maximum number of selections is n (where n is a specified number)
	//		email = email field - searches for "@" and "."
	//		match-elementname = checks if the current field and the field in "elementname" are equal (for confirm password)
	// ALL REQUIRE <span class="error" id="err-elementname"></span> IN THE FORM, WHERE "elementname" IS THE NAME OF THE ELEMENT
	var lang = document.body.id;
	var pass = true;
	var theErrorMessage = "";
	var theString = trim(theElement.value);
	var theClasses = theElement.className.split(" ");
	var errorHolder = document.getElementById("err-" + theElement.name);
	
	var mssgRequiredEn = "This field is required.<br />";
	var mssgRequiredAr = "يجب ادخال بيانات لهذا المُدخل.<br />";
	var mssgAlphanumEn = "This field may contain numbers and letters only (with no spaces).<br />";
	var mssgAlphanumAr = "يجب ادخال إما رقم أو حرف لاتيني في هذا المُدخل.<br />";
	var mssgNumEn = "This field may contain numbers only.<br />";
	var mssgNumAr = "يجب ادخال أرقام فقط في هذا المُدخل.<br />";
	var mssgEmailEn = "This field must be a valid email address.<br />";
	var mssgEmailAr = "يجب ادخال عنوان بريد الكتروني صحيح في هذا المُدخل.<br />";
	var mssgEmailDomainEn = "The email address, <b>1s</b>, contains an invalid domain. Only the following email domain is allowed: <span dir=\"ltr\"><b>@2s</b></span>.<br />";
	var mssgEmailDomainAr = "البريد الذي قمت بإدخاله، <b>1s</b>، غير صحيح. يرجى الإلتزام بالصيغ التالية المسوح بها: <span dir=\"ltr\"><b>@2s</b></span>.<br />";
	var mssgMaxEn = "This field cannot exceed :x: characters.<br />"
	var mssgMaxAr = "لقد تجاوزت العدد المسموح للأحرف لهذا المُدخل.<br />"
	var mssgMinEn = "This field must contain at least :x: characters.<br />"
	var mssgMinAr = "يجب احتواء المُدخل على x أحرف.<br />"
	var mssgMatchEn = "This field does not confirm.<br />"
	var mssgMatchAr = "لم يتطابق تأكيد المٌدخل.<br />"
	var mssgMaxSelectionEn = "Too many selections: :y: options are selected out of a limit of :x:.<br />"
	var mssgMaxSelectionAr = "Too many selections: :y: options are selected out of a limit of :x:.<br />"
	var mssgDateDoesNotExistEn = "This date field is incomplete or incorrect.<br />"
	var mssgDateDoesNotExistAr = "This date field is incomplete or incorrect.<br />"
	var mssgDateMatchEn = "End date should be greater than start date.<br />"
	var mssgDateMatchAr = "تاريخ البداية و النهايه غير متوافقان, يرجى تصحيح الخطأ.<br />"
	var mssgDateMaxEn = "This date should not be greater than today's date.<br />"
	var mssgDateMaxAr = "لا يمكن للتاريخ أن يكون أكبر من التاريخ الحالي, يرجى تصحيح الخطأ.<br />"
	var mssgDateMinEn = "This date should be greater than today's date.<br />"
	var mssgDateMinAr = "لا يمكن للتاريخ أن يكون أصغر من التاريخ الحالي, يرجى تصحيح الخطأ.<br />"
	var mssgMaxValEn = "This field should be less than or equal to :x:.<br />"
	var mssgMaxValAr = "This field should be less than or equal to :x:.<br />"
	
	// search into the array of classes to find "locked" class,  if its found then nothing should done here, the validation criteria should be skipped.
	var skipValidation = theElement.className.search("invalid")
	if (skipValidation > -1 ) {
		pass=false;
		theErrorMessage = document.getElementById("err-" + theElement.name).innerHTML;
		return pass;
	}
	
	// run through the form element classes to decide how to validate
	for (var i = 0; i < theClasses.length; i++){
		var thisClass = theClasses[i];
		switch(thisClass) {	
		case "alpha" :
			var filter = /^[a-zA-Z0-9_]+$/;
			if (theString != "" && !(filter.test(theString))) { 
				pass = false;
				theErrorMessage = (lang == "ar") ? mssgAlphanumAr : mssgAlphanumEn;
			}
			break;
		case "date" :
			// detect all date fields by getting the base name and then submitting to checkDate
			var baseName = theElement.name.slice(0,theElement.name.lastIndexOf("_"));
			var errorHolder = document.getElementById("err-" + baseName + "_month");
			if (!checkDate(baseName)){
				pass = false;
				theErrorMessage = (lang == "ar") ? mssgDateDoesNotExistAr : mssgDateDoesNotExistEn;
			}
			var thisYearElement = document.getElementById("id-" + baseName + "_year")
			if (thisYearElement){
				thisYearElement.style.background = (!pass) ? "#fff9f9" : "#fff";
				thisYearElement.style.borderColor = (!pass) ? "#b00" : "";
			}
			var thisMonthElement = document.getElementById("id-" + baseName + "_month")
			if (thisMonthElement){
				thisMonthElement.style.background = (!pass) ? "#fff9f9" : "#fff";
				thisMonthElement.style.borderColor = (!pass) ? "#b00" : "";
			}
			var thisDayElement = document.getElementById("id-" + baseName + "_day")
			if (thisDayElement){
				thisDayElement.style.background = (!pass) ? "#fff9f9" : "#fff";
				thisDayElement.style.borderColor = (!pass) ? "#b00" : "";
			}
			break;
		case "email" :
			var filter = /^[0-9a-zA-Z!#$%&'*+/=?^_`{|}~-]+(\.[0-9a-zA-Z!#$%&'*+/=?^_`{|}~-]+)*@(([a-zA-Z0-9]-?)*\.)+([a-zA-Z0-9]){2,}$/;
			if (theString != "" && !(filter.test(theString))) {
				pass = false;
				theErrorMessage = (lang == "ar") ? mssgEmailAr : mssgEmailEn;
			}
			break;
		case "number" :
			var filter = /^([0-9]*)$/;
			if (theString != "" && !(filter.test(theString))) { 
				pass = false;
				theErrorMessage = (lang == "ar") ? mssgNumAr : mssgNumEn;
			}
			break;
		case "multinumber" :
			var filter = /^([0-9]*\s*)*$/;
			if (theString != "" && !(filter.test(theString))) { 
				pass = false;
				theErrorMessage = (lang == "ar") ? mssgNumAr : mssgNumEn;
			}
			break;	
		case "float" :
			theString = theString.replace("(","");
			theString = theString.replace(")","");
			theString = theString.replace("-","");
			theString = theString.replace("+","");
			theString = theString.replace(" ","");
			theElement.value = theString;
			if (isNaN(theString)){
				pass = false;
				theErrorMessage = (lang == "ar") ? mssgNumAr : mssgNumEn;
			}
			break; 
		case "req" :
			if (theElement.tagName == "SELECT") {
				// need both checks for various browsers
				if (theElement.getAttribute("multiple") == "multiple" || eval(theElement.getAttribute("multiple"))){
					if (theElement.selectedIndex < 0) pass = false;
				} else if (theElement.selectedIndex == 0) pass = false;
			} else {
				if (isWhitespace(theString)) pass = false;
			}
			if (!pass) theErrorMessage = (lang == "ar") ? mssgRequiredAr : mssgRequiredEn;
			break
		default :
			if (theElement.tagName == 'SELECT') {
				var theString = '';
				for (var j = 0; j < theElement.length; j++) {
					if (theElement.options[j].selected ) theString = theElement.options[j].value + ' ';
				}
			}
			// dual-value classes (creating a name and value by splitting the class from "-")
			if (thisClass.split("-").length > 1 && !isWhitespace(theString)){
				thisClass = thisClass.split("-");
				var thisClassName = thisClass[0];
				var thisClassValue = thisClass[1];
				
				switch (thisClassName){
				case "min" :
					if (theString.length < thisClassValue){
						pass = false;
						mssgMinEn = mssgMinEn.replace(":x:",thisClassValue);
						mssgMinAr = mssgMinAr.replace(":x:",thisClassValue);
						theErrorMessage = (lang == "ar") ? mssgMinAr : mssgMinEn;
					}
					break;
				case "maxval" :
					var maxValue = parseInt(thisClassValue);
					var enteredValue = parseInt(theString);
					if (enteredValue >  maxValue){
						pass = false;
						mssgMaxValEn = mssgMaxValEn.replace(":x:",thisClassValue);
						mssgMaxValAr = mssgMaxValAr.replace(":x:",thisClassValue);
						theErrorMessage = (lang == "ar") ? mssgMaxValAr : mssgMaxValEn;
					}
					break;
				
				case "max" :
					if (theElement.tagName == "SELECT"){
						var counter = 0;
						for (var i = 0; i < theElement.length; i++) {
							if (theElement.options[i].selected ) counter = counter + 1;
						}
						if (counter > thisClassValue) {
							pass = false;
							mssgMaxSelectionEn = mssgMaxSelectionEn.replace(":x:",thisClassValue)
							mssgMaxSelectionEn = mssgMaxSelectionEn.replace(":y:",counter)
							mssgMaxSelectionAr = mssgMaxSelectionAr.replace(":x:",thisClassValue)
							mssgMaxSelectionAr = mssgMaxSelectionAr.replace(":y:",counter)
							theErrorMessage = (lang == "ar") ? mssgMaxSelectionAr : mssgMaxSelectionEn;
						}
					} else if (theString.length > thisClassValue) {
						pass = false;
						mssgMaxEn = mssgMaxEn.replace(":x:",thisClassValue)
						theErrorMessage = (lang == "ar") ? mssgMaxAr : mssgMaxEn;
					}
					break;
				case "datemax" :
					var baseName = theElement.name.slice(0,theElement.name.lastIndexOf("_"));
					var maxDate = parseInt(thisClassValue);
					var yearElement = document.getElementById("id-" + baseName + "_year");
					var monthElement = document.getElementById("id-" + baseName + "_month");
					var dayElement = document.getElementById("id-" + baseName + "_day");
					var day = (dayElement) ? dayElement.value : '00';
					var enteredDate = parseInt(yearElement.value + monthElement.value + day);
					if (enteredDate > maxDate){
						pass = false;
						theErrorMessage = (lang == "ar") ? mssgDateMaxAr : mssgDateMaxEn;
					}
					break;
				case "datemin" :
					var baseName = theElement.name.slice(0,theElement.name.lastIndexOf("_"));
					var minDate = parseInt(thisClassValue);
					var yearElement = document.getElementById("id-" + baseName + "_year");
					var monthElement = document.getElementById("id-" + baseName + "_month");
					var dayElement = document.getElementById("id-" + baseName + "_day");
					var day = (dayElement) ? dayElement.value : '00';
					var enteredDate = parseInt(yearElement.value + monthElement.value + day);
					if (enteredDate < minDate){
						pass = false;
						theErrorMessage = (lang == "ar") ? mssgDateMinAr : mssgDateMinEn;					
					}
					break;
				case "match" :
					// ADEL - TRY USING getElementById
					var matchElement = document.getElementsByName(thisClassValue);
					if (theElement.value != matchElement[0].value){
						pass = false;
						theErrorMessage = (lang == "ar") ? mssgMatchAr : mssgMatchEn;
					}
					break;
				case "datematch" :
					// make sure month is not 'Present' (or any other non numerical string) before doing the check
					if (!isNaN(theElement.options[theElement.options.selectedIndex].value)) {
						var baseName = theElement.name.slice(0,theElement.name.lastIndexOf("_"));
						var startYearElement = document.getElementById("id-" + thisClassValue + "_year");
						var startMonthElement = document.getElementById("id-" + thisClassValue + "_month");
						var startDayElement = document.getElementById("id-" + thisClassValue + "_day");
						var endYearElement = document.getElementById("id-" + baseName + "_year");
						var endMonthElement = document.getElementById("id-" + baseName + "_month");
						var endDayElement = document.getElementById("id-" + baseName + "_day");
						
						var startYear = startYearElement.options[startYearElement.options.selectedIndex].value;
						var startMonth = startMonthElement.options[startMonthElement.options.selectedIndex].value;
						var startDay = (startDayElement) ? startDayElement.options[startDayElement.options.selectedIndex].value : '00';
						var endYear = endYearElement.options[endYearElement.options.selectedIndex].value;
						var endMonth = endMonthElement.options[endMonthElement.options.selectedIndex].value;
						var endDay = (endDayElement) ? endDayElement.options[endDayElement.options.selectedIndex].value : '00';
						
						var startDate = startYearElement.value + startMonthElement.value + startDay;
						var endDate = endYearElement.value + endMonthElement.value + endDay;
						
						if (startDate > endDate){
							pass = false;
							theErrorMessage = (lang == "ar") ? mssgDateMatchAr : mssgDateMatchEn;
						}
					}
					break;
				case "emailDomain" :
					// check the email domain validation
					if (theErrorMessage=="") {
						var userEmailDomin = theString.split('@')[1];
						userEmailDomin = userEmailDomin.toLowerCase();
						var validDominArr = thisClassValue.split(',');
						var validFlag=0; // validFlag = 1 => the Domain is valid , else invalid 
						for (var count=validDominArr.length-1 ; count>=0 ; count--) {
							if (validDominArr[count].toLowerCase()==userEmailDomin){
								// valid domain
								validFlag=1
								break;
							}
						}
						if (validFlag==0) {
							pass = false;
							theErrorMessage = (lang == "ar") ? mssgEmailDomainAr : mssgEmailDomainEn;
							theErrorMessage = theErrorMessage.replace('1s',theString);
							var orOperator = (lang == "ar") ? ' أو ' : ' or ';
							theErrorMessage = theErrorMessage.replace('2s',validDominArr.join('</b> '+orOperator+'<b>@'));
						}
					}
					break;
				}
			}
		}
	}
	// insert the error message in its relative <span> location
	if (errorHolder){
		var innerHTMLText = (!pass) ? theErrorMessage : "";
		$("#err-" + theElement.name).html(innerHTMLText);
		theElement.style.background = (!pass) ? "#fff9f9" : "#fff"; 
		theElement.style.borderColor = (!pass) ? "#b00" : "";
	}
	// clear the default text for elements with class "cleartext"
	if (theElement.className.indexOf("cleartext") > -1 && theElement.value == theElement.defaultValue ) theElement.value = "";
	return pass;
}

function checkDate(baseName){
	var pass = true;
	var thisDayElement = document.getElementById("id-" + baseName + "_day")
	var thisMonthElement = document.getElementById("id-" + baseName + "_month")
	var thisYearElement = document.getElementById("id-" + baseName + "_year")
	
	// make sure month is not 'Present' before doing the check
	if(!isNaN(thisMonthElement.options[thisMonthElement.options.selectedIndex].value)) {
		var day = (thisDayElement) ? thisDayElement.options[thisDayElement.options.selectedIndex].value : "";
		var month = (thisMonthElement) ? thisMonthElement.options[thisMonthElement.options.selectedIndex].value : "";
		var year = (thisYearElement) ? thisYearElement.options[thisYearElement.options.selectedIndex].value : "";
		var monthLength = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
		
		if (year/4 == parseInt(year/4)) monthLength[1] = 29;
		if (day > monthLength[month-1]) pass = false;
		
		var lengthCompare = 8;
		var lengthCompare = (thisYearElement) ? lengthCompare : lengthCompare - 4;
		var lengthCompare = (thisMonthElement) ? lengthCompare : lengthCompare - 2;
		var lengthCompare = (thisDayElement) ? lengthCompare : lengthCompare - 2;
		if ((year + month + day).length > 0 && (year + month + day).length < lengthCompare ) pass = false
	}
	return pass;
}

// USED IN END DATE: WHEN MONTH = PRESENT, HIDE THE YEAR AND DON'T CHECK IT FOR VALIDITY
function checkPresent(dateName){
	var date = dateName;
	var theMonth = "";
	var theYear = "";
	
	for (i = 1; i <= 4; i++) {
		theMonth = "id-" + date + "_month";
		theMonth = document.getElementById(theMonth);
		theYear = "id-" + date + "_year";
		theYear = document.getElementById(theYear)
		
		if (theMonth) {
			if (theMonth.selectedIndex == 1){
				theYear.className = theYear.className.replace('req', 'hide');
				theYear.selectedIndex = 0;
			} else {
				theYear.className = theYear.className.replace('hide', 'req');
			}
			// NOT TO GO THROUGH NEEDLES LOOPS
			if (date == dateName) {
				break;
			 } else {
			 	date = "end"+i;
			 }
		} else {
			date = "end"+i;
		}
	}
}

// ***** HIDE FORM ROW ***** //
// SHOW/HIDE A SPECIFIED NODE ACCORDING TO A CHECKED RADIO BUTTON
// theElement = the current field element that causes the action
// theRow = the node that holds the field element to be shown/hidden
// theValue = the value of thisElement at which thisRow is shown
function hideFormRow(theElement,theRow,theValue){
	var thisRow = document.getElementById(theRow);
	var compareValue = "";
	var thisElementName = document.getElementsByName(theElement.name);
	if (thisRow){
		for (var i = 0; i < thisElementName.length; i++){
			if(thisElementName[i].checked == true) compareValue = thisElementName[i].value;
			else compareValue = "";
			break
		}
		if (theValue == compareValue) thisRow.className = "hide";
		else thisRow.className = "show";
	}
}

function check_availability (field_name) {
		$(document).ready(function() {			
		var url = (field_name == "username") ? 'register-username-check' : 'register-email-check';
		var loading_span = (field_name == "username") ? 'span_username_loading' : 'span_othermail_loading';
		$("#"+loading_span).show();
		var field_value = $('input[name='+field_name+']').val();
		$("#register").attr("disabled", "true");
		$("[name=check_id]").attr("disabled", "true");
		$.bayt ('/app/index',
				{body:url,s:field_value} ,
				function (data) {
					$('#err-'+field_name).html('');
					$('#success-'+field_name).remove();
					$("#"+loading_span).hide();
					$('input[name='+field_name+']').removeClass("invalid");
					$('input[name='+field_name+']').css({ borderColor:"", background:"#fff" });
					$("#register").removeAttr("disabled");
					$("[name=check_id]").removeAttr("disabled");
					$('<span style=\"color:#008800\" id=success-'+field_name+'>'+data+'</span>').insertBefore('input[name='+field_name+']');
				},
				function (xhr) { 
					$('#err-'+field_name).html(xhr.responseText);
					$("#"+loading_span).hide();
					$('input[name='+field_name+']').addClass("invalid");
					$('input[name='+field_name+']').css({ borderColor:"#b00", background:"#fff9f9" });
					$("#register").removeAttr("disabled");
					$("[name=check_id]").removeAttr("disabled");
					$('#success-'+field_name).remove();
				}
				)
	});
}