if(typeof(util)=="undefined")
{
	var util = new Object();
}

if(typeof(_ctx)=="undefined")
{
	_ctx = new Object();
}

if(_ctx.language==null)
{
	_ctx.language = "US";
}

util.form = new Object();

util.form.messageTemplate = function(lbMsg, usMsg, frMsg)
{
	this.LB = lbMsg;
	this.US = usMsg;
	this.FR = frMsg;
};

util.form.messages = new Object();
util.form.messages["mandatory"] = new util.form.messageTemplate(".\"الرجاء تعبئة الحقل \"{0}",
	"Please enter a value in the \"{0}\" field.",
	"Veuillez entrer une valeur dans le champ \"{0}\".");
util.form.messages["minLength"] = new util.form.messageTemplate(".الرجاء إدخال {0} حرف كحد أدنى في الحقل \"{1}\"",
	"Please enter at least {0} characters in the \"{1}\" field.",
	"Veuillez entrer au moins {0} catatères dans le champ \"{1}\".");
util.form.messages["maxLength"] = new util.form.messageTemplate(".الرجاء إدخال {0} حرف كحد أقصى في الحقل \"{1}\"",
	"Please enter at most {0} characters in the \"{1}\" field.",
	"Veuillez entrer au plus {0} catatères dans le champ \"{1}\".");
util.form.messages["int"] = new util.form.messageTemplate(".\"الرجاء إدخال رقم كامل في الحقل \"{0}",
	"Please enter an integer value in the \"{0}\" field.",
	"Veuillez entrer une valeur entière dans le champ \"{0}\".");
util.form.messages["minValue"] = new util.form.messageTemplate(".الرجاء إدخال قيمة أكبر من {0} في الحقل \"{1}\"",
	"Please enter a value superior to {0} in the \"{1}\" field.",
	"Veuillez entrer une valeur supérieure à {0} dans le champ \"{1}\".");
util.form.messages["maxValue"] = new util.form.messageTemplate(".الرجاء إدخال قيمة أصغر من {0} في الحقل \"{1}\"",
	"Please enter a value inferior to {0} in the \"{1}\" field.",
	"Veuillez entrer une valeur inférieure à {0} dans le champ \"{1}\".");
util.form.messages["float"] = new util.form.messageTemplate(".\"الرجاء إدخال رقم عشري في الحقل \"{0}",
	"Please enter a float value in the \"{0}\" field.",
	"Veuillez entrer une valeur décimale dans le champ \"{0}\".");
util.form.messages["date"] = new util.form.messageTemplate(".\"الرجاء إدخال تاريخ صحيح في الحقل \"{0}",
	"Please enter a valid date in the \"{0}\" field.",
	"Veuillez entrer une date valide dans le champ \"{0}\".");
util.form.messages["minDate"] = new util.form.messageTemplate(".الرجاء إدخال لا يتدنى {0} في الحقل \"{1}\"",
	"Please enter a date past or equal to {0} in the \"{1}\" field.",
	"Veuillez entrer une date ultérieure ou égale à {0} dans le champ \"{1}\".");
util.form.messages["maxDate"] = new util.form.messageTemplate(".الرجاء إدخال تاريخ لا يتعدى {0} في الحقل \"{1}\"",
	"Please enter a date prior or equal to {0} in the \"{1}\" field.",
	"Veuillez entrer une date antérieure ou égale à {0} dans le champ \"{1}\".");
util.form.messages["email"] = new util.form.messageTemplate(".\"الرجاء إدخال عنوان بريد إلكنروني صحيح في الحقل \"{0}",
	"Please enter a valid e-mail address in the \"{0}\" field.",
	"Veuillez entrer une adresse e-mail valide dans le champ \"{0}\".");
util.form.messages["pattern"] = new util.form.messageTemplate(".\"الرجاء إدخال {0} صحيح في الحقل \"{1}",
	"Please enter a valid {0} in the \"{1}\" field.",
	"Veuillez entrer un(e) {0} valide dans le champ \"{1}\".");
util.form.messages["select"] = new util.form.messageTemplate(".\"الرجاء تحديد خيار للحقل \"{1}",
	"Please select an option for \"{0}\".",
	"Veuillez choisir une option pour \"{0}\".");
util.form.messages["file"] = new util.form.messageTemplate(".\"الرجاء إدخال إسم ملف مع رمز\"{0}",
	"You are trying to upload a file for \"{0}\" with no extension. \r\nPlease add an extension to your file Name or select another file.",
	"Vous êtes en train d'essayer de charger un fichier pour \"{0}\" sans extension. Veuillez ajouter une extension au Nom de votre fichier ou choisir un autre fichier.");
util.form.messages["fileExtensions"] = new util.form.messageTemplate(".الرجاء إدخال إسم ملف للحقل \"{0}\" مع أحد الرموز التالية:\r\n\r\n{1}",
	"Please enter a file for \"{0}\" with one of the following extension(s) only:\r\n\r\n{1}",
	"Veuillez entrer un fichier pour \"{0}\" ayant une des extensions suivantes:\r\n\r\n{1}");
util.form.messages["unique"] = new util.form.messageTemplate(".الرجاء إدخال قيمة للحقل \"{0}\" مختلفة عن القيم التالية:\r\n\r\n{1}",
	"Value in field \"{0}\" must be different than any of the following values:\r\n{1}",
	"La valeur dans le champ \"{0}\" doit être différente des valeurs suivantes:\r\n\r\n{1}");
util.form.messages["selectEd"] = new util.form.messageTemplate(".الرجاء تحديد خيار للحقل \"{0}\" أو إدخال القيمة الخاصة لديك",
	"Please select a value for \"{0}\" from the list or enter your own value.",
	"Veuillez choisir une valeur pour \"{0}\" de la liste ou entrer votre propre valeur.");


util.form.checkDate = function(str)
{
	var d=str.Trim();
	if(d=='')
	{
		return(true);
	}
	
	var m_names = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

	// get separator
	var separator='';
	var separatorsList=new Array("-", "/", " ");
	
	for(var i=0; i<separatorsList.length; i++)
	{
		if(d.indexOf(separatorsList[i], 0)!=-1)
		{
			separator=separatorsList[i];
			break;
		}
	}
	
	// if separator is SPACE, then the date should be dd {mm} yyyy, where {mm} is the
	// 3-letters short for the month name
	if(separator=="")
	{
		return(false);
	}
	else
	{
		if(isNaN(Date.parse(d)))
		{
			return(false);
		}
	}

	// check if the entered date is the same as the javascript date.
	var dateArray=util.string.stringToArray(d, separator, false);

	var date=new Date(d);
	var dateDD, dateMM;
	if(separator==" ")
	{
		var m;
		dateArray[1] = dateArray[1].toLowerCase();
		for(m=0; (m<m_names.length) && (m_names[m].toLowerCase()!=dateArray[1]); m++);
		if(m==m_names.length)
		{
			return(false);
		}
		dateMM = m + 1;
		dateDD = parseInt(util.string.leftTrimChar(dateArray[0], "0"));
	}
	else
	{
		dateDD=parseInt(util.string.leftTrimChar(dateArray[1], "0"));
		dateMM=parseInt(util.string.leftTrimChar(dateArray[0], "0"));
	}
	var dateYYYY=parseInt(dateArray[2]);
	if(dateYYYY>9999)
	{
		return(false);
	}
	if((dateMM!=(date.getMonth()+1)) || (dateDD!=date.getDate()) || (dateYYYY!=date.getFullYear()))
	{
		return(false);
	}
	return(true);
};

util.form.checkEmail = function(str)
{
	var pattern =  /^[a-z]([\.\-\_]{0,}[a-z_0-9]|[a-z_0-9]\.[a-z_0-9])+@([a-z0-9]|[a-z0-9][\.\-][a-z0-9])+\.[a-z]{2,}$/i
  return pattern.test(str)
};

util.form.check = function(field, fieldName, empty, type, min, max, message, focusField, onError)
{
	if(field==null)
	{
		return(true);
	}
	this.field = field;
	this.fieldName = fieldName;
	this.focusField = focusField;
	this.onError = onError;

	var str = field.value;
	if(focusField!=null)
	{
		field = focusField;
	}
	if(empty && ((str=="") || (str==null)))
	{
		var p = new Array();
		p[0] = fieldName;
		FormUtilsShowMessage(this, "mandatory", p, message);
		if(field.type!="hidden")
		{
			field.focus();
		}
		return(false);
	}
	
	switch(type.toLowerCase())
	{
		case "string":
			if(empty || (!empty && str!=""))
			{
				if((min!=null) && (str.length<min))
				{
					var p = new Array();
					p[0] = min;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "minLength", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			if((max!=null) && (str.length>max))
			{
				var p = new Array();
				p[0] = max;
				p[1] = fieldName;
				FormUtilsShowMessage(this, "maxLength", p, message);
				if(field.type!="hidden")
				{
					field.select();
					field.focus();
				}
				return(false);
			}
			break;
		case "int":	
			if(empty || (!empty && str!=""))
			{
				if(isNaN(parseInt(str)))
				{
					var p = new Array();
					p[0] = fieldName;
					FormUtilsShowMessage(this, "int", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				str = parseInt(str);
				if((min!=null) && (str<min))
				{
					var p = new Array();
					p[0] = min;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "minValue", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				if((max!=null) && (str>max))
				{
					var p = new Array();
					p[0] = max;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "maxValue", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "float":	
			if(empty || (!empty && str!=""))
			{
				var num = parseFloat(str);
				if(isNaN(num) || (num.toString()!=str))
				{
					var p = new Array();
					p[0] = fieldName;
					FormUtilsShowMessage(this, "float", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				str = parseFloat(str);
				if((min!=null) && (str<min))
				{
					var p = new Array();
					p[0] = min;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "minValue", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				if((max!=null) && (str>max))
				{
					var p = new Array();
					p[0] = max;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "maxValue", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "date":
			if(min!=null)
			{
				min = util.string.dateRendererEx(min);
			}
			if(max!=null)
			{
				max = util.string.dateRendererEx(max);
			}
			if(empty || (!empty && str!=""))
			{
				if(!util.form.checkDate(str))
				{
					var p = new Array();
					p[0] = fieldName;
					FormUtilsShowMessage(this, "date", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				str = Date.parse(str);
				if((min!=null) && (str<Date.parse(min)))
				{
					var p = new Array();
					p[0] = min;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "minDate", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
				if((max!=null) && (str>Date.parse(max)))
				{
					var p = new Array();
					p[0] = max;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "maxDate", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "email":
			if(empty || (!empty && str!=""))
			{
				if(!util.form.checkEmail(str))
				{
					var p = new Array();
					p[0] = fieldName;
					FormUtilsShowMessage(this, "email", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
		case "pattern":
			if(empty || (!empty && str!=""))
			{
				if(!min.test(str))
				{
					var p = new Array();
					p[0] = max;
					p[1] = fieldName;
					FormUtilsShowMessage(this, "pattern", p, message);
					if(field.type!="hidden")
					{
						field.select();
						field.focus();
					}
					return(false);
				}
			}
			break;
	}
	return(true);
};

util.form.checkRadio = function(field, fieldName, message)
{
	if(field==null)
	{
		return(true);
	}
	for(var i=0; ((i<field.length) && (!field[i].checked)); i++);
	if(i==field.length)
	{
		var p = new Array();
		p[0] = fieldName;
		FormUtilsShowMessage(this, "select", p, message);
		return(false);
	}
	return(true);
};

util.form.checkSelect = function(field, fieldName, emptyValue, message)
{
	if(field==null)
	{
		return(true);
	}
	var selIn = field.selectedIndex;
	var ok = true;
	if(selIn==-1)
	{
		ok = false;
	}
	else
	{
		if(emptyValue!=null)
		{
			if(field.options[selIn].value==emptyValue)
			{
				ok = false;
			}
		}
	}
	if(!ok)
	{
		var p = new Array();
		p[0] = fieldName;
		FormUtilsShowMessage(this, "mandatory", p, message);
		if(field.type!="hidden")
		{
			field.focus();
		}
	}
	return(ok);
}

function FormUtilsShowMessage(ref, msgId, params, message)
{
	if(ref.onError!=null)
	{
		ref.onError(ref);
	}
	var msg = message;
	if(msg==null)
	{
		if(msgId!=null)
		{
			msg = util.form.messages[msgId][_ctx.language];
		}
		else
		{
			msg = "";
		}
	}
	var reg;
	if(params==null)
	{
		params = new Array();
	}
	for(var i=0; i<params.length; i++)
	{
		reg = new RegExp("\\{" + i + "\\}", "g");
		msg = msg.replace(reg, params[i]);
	}
	alert(msg);
}

util.form.getListItemName = function(options, value)
{
	var name;
	for(var i=0; i<options.length; i++)
	{
		if(options[i].value==value)
		{
			name = options[i].text;
			break;
		}
	}
	if(name==null)
	{
		name = "[undefined]";
	}
	return(name);
};

util.form.getListItemIndex = function(options, value)
{
	var i;
	for(i=0; i<options.length; i++)
	{
		if(options[i].value==value)
		{
			break;
		}
	}
	if(i==options.length)
	{
		i = -1;
	}
	return(i);
};

util.form.setRadio = function(fields, value)
{
	// finds the radio button inside a radio buttons list and checks the selected one. 
	// Returns {true} if the value was found, {false} otherwise.
	if(fields.length==null)
	{
		if(fields.value==value)
		{
			fields.checked = true;
			return(true);
		}
		return(false);
	}
	for(var i=0; i<fields.length; i++)
	{
		if(fields[i].value==value)
		{
			fields[i].checked = true;
			return(true);
		}
	}
	return(false);
};

util.form.makeRequest = function(forme)
{
	var str = new Array();
	var value, elt, history = new Object();
	for(var i=0; i<forme.elements.length; i++)
	{
		elt = forme.elements[i];
		if(elt.disabled)
		{
			continue;
		}
		if(history[elt.name]!=null)
		{
			continue;
		}
		history[elt.name] = 1;
		value = util.string.urlEncode(elt.name) + "=" ;
		switch(elt.tagName.toLowerCase())
		{
			case "input":
			{
				switch(elt.type.toLowerCase())
				{
					case "radio":
					{
						if(elt.checked)
						{
							str.push(value + util.string.urlEncode(elt.value));
						}
						break;
					}
					case "checkbox":
					{
						if(elt.checked)
						{
							var cV = elt.value;
							if(cV=="")
							{
								cV = "on";
							}
							str.push(value + util.string.urlEncode(cV));
						}
						break;
					}
					default:
					{
						str.push(util.string.urlEncode(elt.name) + "=" + util.string.urlEncode(elt.value));
						break;
					}
				}
				break;
			}
			case "select":
			{
				var sV = new Array();
				for(var i=0; i<elt.options.length; i++)
				{
					if(elt.options[i].selected)
					{
						sV.push(elt.options[i].value);
					}
				}
				str.push(util.string.urlEncode(elt.name) + "=" + util.string.urlEncode(sV.join(",")));
				break;
			}
			default:
			{
				str.push(util.string.urlEncode(elt.name) + "=" + util.string.urlEncode(elt.value));
				break;
			}
		}
	}
	return(str.join("&"));
};

util.form.validator = function(field, fieldName, empty, type, min, max, message, focusField, onError)
{
	this.validate = function()
	{
		return(util.form.check(field, fieldName, empty, type, min, max, message, focusField, onError));
	};
};

util.form.fileValidator = function(field, fieldName, typesList, message)
{
	this.validate = function()
	{
		var fileName = field.value;
		if(fileName=="")
		{
			return(true);
		}
		if(typesList==null)
		{
			typesList = new Array();
		}
		if(typesList.length>0)
		{
			fileName = fileName.split(".");
			if(fileName.length<2)
			{
				var p = new Array();
				p[0] = fieldName;
				FormUtilsShowMessage(this, "file", p, message);
				field.select();
				field.focus();
				return(false);
			}
		}
		var ext = fileName.pop().toLowerCase();
		if(util.string.arrayScan(typesList, ext)==-1)
		{
			var messageTypes = new Array();
			for(var i=0; i<typesList.length; i++)
			{
				messageTypes.push("*." + typesList[i]);
			}
			var p = new Array();
			p[0] = fieldName;
			p[1] = messageTypes.join(", ");
			FormUtilsShowMessage(this, "fileExtensions", p, message);
			field.select();
			field.focus();
			return(false);
		}
		return(true);
	};
};

util.form.radioValidator = function(field, fieldName, message)
{
	this.validate = function()
	{
		return(util.form.checkRadio(field, fieldName, message));
	};
};

util.form.selectValidator = function(field, fieldName, emptyValue, message)
{
	this.validate = function()
	{
		return(util.form.checkSelect(field, fieldName, emptyValue, message));
	};
};

util.form.uniqueValidator = function(field, fieldName, valuesList, message)
{
	this.validate = function()
	{
		var v = field.value;
		if(v=="")
		{
			return(true);
		}
		if(util.string.arrayScan(valuesList, v)>=0)
		{
			if(message==null)
			{
				message = "Value in field \"" + fieldName + "\" must be different than any of the following values:\r\n" +
					valuesList.join(",");
			}
			var p = new Array();
			p[0] = fieldName;
			p[1] = valuesList.join(", ");
			FormUtilsShowMessage(this, "unique", p, message);
			return(false);
		}
		return(true);
	};
};

util.form.customValidator = function(condition, message, focusField)
{
	this.validate = function()
	{
		if(!condition)
		{
			FormUtilsShowMessage(this, null, null, message);
			if(focusField!=null)
			{
				focusField.select();
				focusField.focus();
			}
		}
		return(condition);
	};
};

util.form.selectEdValidator = function(list, fieldName, required, voidValue, message)
{
	this.validate = function()
	{
		if(list.disabled)
		{
			return(true);
		}
		var o = list.getValue();
		var v = o.value;
		var t = o.text;
		if((v==null) || (v==voidValue))
		{
			if(required)
			{
				if(message==null)
				{
					message = "Please select a value for \"" + fieldName + "\"";
				}
				var p = new Array();
				p[0] = fieldName;
				FormUtilsShowMessage(this, "mandatory", p, message);
				return(false);
			}
			if((t=="") && (!list.allowNewValues))
			{
				if(message==null)
				{
					message = "Please select a value for \"" + fieldName + "\" from the list or enter your own value.";
				}
				var p = new Array();
				p[0] = fieldName;
				FormUtilsShowMessage(this, "selectEd", p, message);
				return(false);
			}
		}
		return(true);
	};
};

util.form.scanValidators = function(validators)
{
	var v;
	for(var i=0; i<validators.length; i++)
	{
		if(!validators[i].validate())
		{
			return(false);
		}
	}
	return(true);
};

util.form.getEltValue = function(elt)
{
	var val = null;
	if(elt.tagName==null)
	{
		if(elt.length==null)
		{
			return(null);
		}
		elt = elt[0];
	}
	switch(elt.tagName.toLowerCase())
	{
		case "textarea":
		{
			val = elt.value;
			break;
		}
		case "select":
		{
			var a = new Array();
			for(var i=0; i<elt.options.length; i++)
			{
				if(elt.options[i].selected)
				{
					a.push(elt.options[i].value);
				}
			}
			val = a.join(",");
			break;
		}
		case "input":
		{
			switch(elt.type)
			{
				case "checkbox":
				{
					val = elt.checked;
					break;
				}
				case "file":
				{
					val = elt.value;
					break;
				}
				case "hidden":
				{
					val = elt.value;
					break;
				}
				case "password":
				{
					val = elt.value;
					break;
				}
				case "text":
				{
					val = elt.value;
					break;
				}
				case "radio":
				{
					var forme = elt.form;
					var l = forme[elt.name].length;
					if(l==null)
					{
						if(forme[elt.name].checked)
						{
							val = forme[elt.name].value;
						}
					}
					for(var i=0; i<l; i++)
					{
						if(forme[elt.name][i].checked)
						{
							val = forme[elt.name][i].value;
							break;
						}
					}
					break;
				}
			}
			break;
		}
	}
	return(val);
};

util.form.getFormsDefaultValues = function()
{
	_ctx.formDefaultValues = new Object();
	var fL = document.forms.length;
	var l, o, forme, val;

	for(var i = 0; i<fL; i++)
	{
		forme = document.forms[i];
		o = new Object();
		l = forme.elements.length;
		for(var j=0; j<l; j++)
		{
			val = util.form.getEltValue(forme.elements[j]);
			if(val!=null)
			{
				o[forme.elements[j].name] = val;
			}
		}
		_ctx.formDefaultValues[forme.name] = o;
	}
};


util.form.hasChanges = function(forme, skipElements)
{
	if(skipElements==null)
	{
		skipElements = new Array();
	}
	var o = new Object();
	var l = forme.elements.length;
	var elt;
	var names = new Array();
	for(var i=0; i<l; i++)
	{
		elt = forme.elements[i];
		val = util.form.getEltValue(elt);
		if(val!=null)
		{
			o[elt.name] = val;
			names.push(elt.name);
		}
	}
	
	var hasChanged = false;
	var dNames = new Array();
	var dO = _ctx.formDefaultValues[forme.name];
	for(eltName in o)
	{
		if(skipElements.indexOf(eltName)==-1)
		{
			if(o[eltName]!=dO[eltName])
			{
/*
				alert("forme: " + forme.name + "\r\n" + eltName + " was " + dO[eltName] + ", is " + o[eltName] +
					"\r\n" + forme[eltName].outerHTML);
*/
				hasChanged = true;
				break;
			}
		}
		dNames.push(eltName);
	}
	if(!hasChanged)
	{
		names = names.sort();
		dNames = dNames.sort();
		if(names.length!=dNames.length)
		{
			// NOTE: getting here means that either the form controls have changed indeed, or that more than one control
			// with the same name exist within the same form.
			//alert("Form name: " + forme.name + "\r\nDefault controls: " + dNames + "\r\nActual controls: " + names);
			hasChanged = true;
		}
		else
		{
			for(var i=0; i<names.length; i++)
			{
				if(names[i]!=dNames[i])
				{
					hasChanged = true;
					break;
				}
			}
		}
	}
	return(hasChanged);
};

util.form.haveChanges = function()
{
	var fL = document.forms.length;
	var haveChanges = false;
	for(var i=0; i<fL; i++)
	{
		if(util.form.hasChanges(document.forms[i]))
		{
			haveChanges = true;
			break;
		}
	}
	return(haveChanges);
};

