/* 
 * essilab-form.js   Version 3.0
 * Licence LGPL
 * http://www.essilab.org
 * version 1.0
 * updated : 5 juin 2010.
 * autor : Michaël THOMAS.
 * require include before
 *  - prototype.js
 *  - scriptaculous 
 *  - essilab-message-box.js 
 *  
 */

if (typeof Essilab=='undefined') 
	var Essilab = {};
Essilab.Form = { 
		version : "3.0.7.1"

};
Essilab.Form.FormManager = Class.create({
	initOptions : function() {
		this.options = {
				prefix : "",
				url : 'not_defined',
				classes : 'GlobalFormDef BasicForm',
				action_label : 'Envoyer',
				method : 'post',
				tinyContext : false,
				tinyMceInit : {
					theme : "simple",
					entity_encoding : "raw",
					cleanup : true,
					mode : "exact",
					fix_nesting : true
				},
				url_media_add : '/file/widget_form_add',
				url_antispam_image : '/user/antispam',
				url_antispam_check : '/user/ajaxcheckspam',
				accept_charset : "utf-8",
				isAjaxSubmit : false,
				ajaxSubmitResponseContainer : null,
				enctype : 'multipart/form-data',
				submit_error : 'Le formulaire contient des champs invalides (marqués en rouge), merci de les corriger.',
				main :  'contentFormContainer'
		}
	},
	validators : {
		login         : /^[a-zA-Z0-9\-]{5,20}$/,
		password      : /^.{5,20}$/,
		normalized    : /^[a-z0-9A-Z\-\._]+$/,
		float 		  : /^[0-9\.]+$/,
		phone		  :/^[0-9\.+]{8,}$/,
		int 		  : /^[0-9]+$/,
		digit 		  : /^[0-9]+$/,
		autocompleter : /^[0-9]+$/,
		email 		  : /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]{2,}[.][a-zA-Z]{2,3}$/,
		notempty      : /[^\s\t]+/,
		datetime      : new RegExp("([012]{1}[0-9]{1}|3[01]{1})/(0[0-9]{1}|1[012]{1})/(19|20)[0-9]{2}[^0-9]*([01][0-9]{1}|2[0123]):[012345][0-9]")

	},
	initialize : function(options){
		// Check it for multiple instances... used in file upload use case?
		Essilab.Form.formInstance = this;
		this.initOptions();
		this.toValidate = new Array();
		for (var propertie in options) {
			this.options[propertie]=options[propertie];
		}
		this.hasBeenValidated = false;
		this.prefix= "_"+Math.round(Math.random()*1000)+"_";
		this.options['prefix'] = this.prefix;

		if (Object.isUndefined($(this.options['main'])) || null == $(this.options['main'])) {
			window.document.write('<div class="'+this.options['classes']+'" id="'+this.options['main']+'"></div>');
		}
		this.main = $(this.options['main']);	
		var form = new Element('form');
		form.id = this.options['main']+"Form";
		var formInner = new Element('div');
		formInner.id = this.options['main']+"FormInner";
		this.main.addClassName(this.options['classes']);

		form.appendChild(formInner);
		this.form = form;
		this.main.update(form);
		this.formInner = formInner;
		Element.extend(form);
		if (this.options['isAjaxSubmit'])
			this.options['enctype'] = "application/x-www-form-urlencoded";
		form.action = this.options['url'];
		form.method = this.options['method'];
		form.enctype = this.options['enctype'];
		form.acceptCharset = this.options['accept_charset'];
		form.addClassName('WideForm');


		if (Object.isUndefined(this.options['createdefaultfieldset']) || this.options['createdefaultfieldset'] ) {
			var fieldset = new Element('fieldset');
			this.legend = new Element('legend');
			this.legend.innerHTML = this.options['title'];
			fieldset.appendChild(this.legend);
			formInner.appendChild(fieldset);
			this.defaultFieldset = fieldset;
			this.container = new Element('ul');
			this.container.id = this.container.name = this.prefix;
			fieldset.appendChild(this.container);
		}
		var actionsBoxe = new Element('div');
		this.actionsBoxe = actionsBoxe;
		form.appendChild(actionsBoxe);    
		var br = $(new Element('br'));
		br.addClassName("Cleaner");
		form.appendChild(br);

		form.observe('submit',this.onSubmit.bind(this));
		this.addAction({action : this.options['url'], label : this.options['action_label'], id : this.prefix+'_default_action'});
	},

	onSubmit : function(params){
		if (this.options['tinyContext']) {
			tinyMCE.editors.each(function (e) {if (e.isDirty()) e.save();})
		}

		this.valid = true;
		for (var index = 0, len = this.toValidate.length; index < len; ++index) {
			var e = this.toValidate[index];
			if (null == $(e['elem'])) continue;
			if (/radio/.test(e['validator'])) {
				$A($(e['elem']).up().getElementsByTagName('input')).each(function(e){
					if (e.type == 'radio')
						if (e.selected || e.checked) {
							e.up().removeClassName("Error");
							throw $break;
						}
						else{ 
							this.valid = false;
							e.up().addClassName("Error");
						}  
				}, this);
			} else
				if (/ajax/.test(e['validator'])) {
					var r = this.ajaxCheck($(e['elem']),false);

					if ("true" != r){
						this.valid = false;
						$(e['elem']).addClassName("Error");
					}else
						$(e['elem']).removeClassName("Error");

				}
				else if (/minimum-choice/.test(e['validator'])) {
					if ($(e['elem']).min > $(e['elem']).current){
						this.valid = false;
						$(e['elem']).addClassName("Error");
					}else
						$(e['elem']).removeClassName("Error");
				}
				else {
					var elem = e['elem'];
					var regEval = true;
					if ('autocompleter' == e['validator']) elem +="Id";
					var txtEval = $F(e['elem']);
					var testResult = false;				
					if (/(less|greater)/.test(e['validator'])) {
						;

						var toCompare = $F(this.prefix+e['compareto']);

						// Seems to be a date.
						if (this.validators.datetime.test(txtEval)) {
							var splitter = new RegExp("[/ @ :]+","g");
							var splitted = txtEval.split(splitter);
							var date1 = new Date();
							date1.setDate(splitted[0]);
							date1.setMonth(splitted[1]);
							date1.setFullYear(splitted[2]);
							date1.setHours(splitted[3]);
							date1.setMinutes(splitted[4]);
							splitted = toCompare.split(splitter);
							var date2 = new Date();
							date2.setDate(splitted[0]);
							date2.setMonth(splitted[1]);
							date2.setFullYear(splitted[2]);
							date2.setHours(splitted[3]);
							date2.setMinutes(splitted[4]);
							var diff = date1.getTime() - date2.getTime();
							//lert(diff);
							if (/greater/.test(e['validator']) && diff > 0) {
								testResult = true; 
							}
							else if (/less/.test(e['validator']) && diff < 0) {
								testResult = true;
							} 
						}
					}
					else {
						if (/sameas/.test(e['validator'])) 
							var reg = new RegExp("^"+$F(this.prefix+e['compareto'])+"$");
						else
							var reg = (e['reg'])?e['reg']:this.validators[e['validator']];
							if ($(e['elem']).tagName.match(/TEXTAREA/ig)) 
								txtEval =  $F(e['elem']) ;
							testResult = (!e['reginv'] == reg.test(txtEval));

					}
					if (testResult) {
						$(e['elem']).removeClassName("Error");
						if (null != $(e['elem']+"_icon_error"))
							$(e['elem']+"_icon_error").remove();
						if (null != $(e['elem']+"_error_message"))
							$(e['elem']+"_error_message").remove();
					}
					else {
						if (Object.isUndefined($(elem+"_icon_error")) || null == $(elem+"_icon_error")) {
							// set display none to tooltip.
							if (!Object.isUndefined($(elem+"_tooltip"))&& null != $(elem+"_tooltip"))
								$(elem+"_tooltip").setStyle({display:'none'});
							// create the error message icon
							var errorMessageIcon = $(new Element('span'));
							errorMessageIcon.addClassName("FormFieldIconError");
							errorMessageIcon.id = elem+"_icon_error";
							$(elem+"_message_container_icons").insertBefore(errorMessageIcon, $(elem+"_message_container_icons").firstChild);
							// create the error message

							var errorMessage = $(new Element('span'));
							errorMessage.id = elem+"_error_message";
							errorMessage.addClassName("FormFieldErrorMessage");
							//errorMessage.innerHTML = "test";
							errorMessage.innerHTML = e.error;
							// Display the error message in the message container.
							$(elem+"_message_container_messages").appendChild(errorMessage);

							$(errorMessageIcon).observe('click', 
									function(e){
								// getting the message container.
								var messageContainer = $(e.element().id.replace("_icon_error", "_message_container_messages"));
								var messages = $A(messageContainer.getElementsByTagName("span"));
								messages.each( function (m){
									if (!m.id.match("_error_message")) m.hide();
								});
								Effect.toggle(e.element().id.replace("_icon_error", "_error_message"), 'appear');
							}
							);
							$(e['elem']).addClassName("Error");
						}
						this.valid = false;
					}
				}
		}
		if (!this.valid){
			new Essilab.Form.Message(params['sender'], this.options['submit_error']); 
			return false;
		}
		//event.stop();
		else {this.form.getElements().each(function(e){e.name = e.name.replace(new RegExp(this.prefix),'');}, this);
		//this.form.submit();
		return true;
		}
	},
	addSelectAjaxLoad : function(params){
		var select = this.addSelect(params);
		new AjaxQueryRequest(select, params['ajaxurl'], false);
		return select;
	},
	addToggleBox : function(params){
		var box = new Element('div');
		params['container'].appendChild(box);
		var header = $(new Element('div'));
		box.appendChild(header);
		var toggle = new Element('a');
		toggle.update('+ '+ params['titleOpen']);
		toggle.href= 'javascript:void(0)';
		header.setStyle('border:1px solid #ababab;background-color:#f2f3f4;padding:2px;');
		header.appendChild(toggle);
		var content = new Element('div');
		content.id = params['id'];
		content.style.display = 'none';
		box.appendChild(content);
		var cleaner = new Element('hr');
		cleaner.addClassName('Cleaner');
		box.appendChild(cleaner);   
		params['content'] = content;
		params['toggle'] = toggle;
		params['toggled'] = true;
		toggle.observe('click', this.toggleBox.bind(params));  
		return content;
	},
	toggleBox : function(e){
		if (/\+/.exec(this['toggle'].innerHTML))
			this['toggle'].update('- '+this['titleClose']);
		else
			this['toggle'].update('+ '+this['titleOpen']); 
		Effect.toggle(this['content'], 'blind');
	},
	addFieldset : function(params){
		var fieldset = $(new Element('fieldset'));
		var legend = new Element('legend');
		legend.update(params['title']);
		fieldset.appendChild(legend);
		var ul = new Element('ul');
		fieldset.appendChild(ul);
		var container = this.formInner;
		if (!Object.isUndefined(params['container']))
			container = params['container'];
		if (!Object.isUndefined(params['id']))
			fieldset.id = params['id'];
		container.appendChild(fieldset);
		return ul;      
	},
	addAntispamForm : function(){
		var ul = this.addFieldset({title : 'Antispam'});
		var li = this.emptyLine({container : ul, id : 'asimage'});
		var img = new Element('img');
		img.src = this.options['url_antispam_image']+"?name=antispam&strlen=4";
		li.appendChild(img);
		this.addText({container : ul, label: 'Recopier le code antispam', id : 'antispam', validator:'ajax',url : this.options['url_antispam_check'], error : 'Code incorrect!.'});
	},
//	IFraming because we can't have a form inside another form.
	addMediaFileForm : function(params){
		var title = 'Description du véhicule';
		if (!Object.isUndefined(params['title'])) title = params['title'];
		var ul = this.addFieldset({title : title});
		if (!Object.isUndefined(params['description']))
			this.addTextarea({container : ul, id:'description', label:'Description', decorator:'tinymce', style:'width:99%;'});
		var li = new Element('li');
		var iframe = new Element('iframe');
		var ownerClass = (Object.isUndefined(params['ownerClass']))?'anonymous':params['ownerClass'];
		this.ownerClass = ownerClass;
		// Creating an external form to avoid form inclusion.
		iframe.src = this.options['url_media_add']+'?owner_class='+ownerClass+'&formId=iframe&container='+this.prefix+'Media';
		iframe.setStyle("height:80px; ;width:99%;border:none;padding:0;overflow:hidden;margin:0;");
		var mediaContainer = new Element('div');
		mediaContainer.id = this.prefix+'Media';
		li.appendChild(iframe);
		li.appendChild(mediaContainer);  
		ul.appendChild(li);
	},
	ajaxCheck : function(e, interactive){
		// le variable separator crée par momo pour que je peut envoyer des paramètres dans l'url
		var separator='?';
		if(-1!=e.url.toString().indexOf("?"))
			separator='&';
		var result = AjaxSimpleRequest(e.url+separator+$(e).name.replace(new RegExp(this.prefix),'')+'='+$F(e));
		if (interactive) {
			if ("false" == result){
				new Essilab.Form.Message(e, e.message_error);
				$(e).focus();
				$(e).addClassName('Error');
			} else
				$(e).removeClassName('Error');
		}; 
		return result; 
	},
	onAjaxCheck : function(e) {
		this.ajaxCheck(e.element(),true);
	},
	addMandatory : function(params){

		if (!Object.isUndefined(params['reg']) || !Object.isUndefined(params['validator'])) {
			var e = $(params['id']);
			while (e && !(/li/i).test(e.tagName )){e = e.up();}  
			if ($(e).down().select('.Mandatory').length < 1) {
				var span = $(new Element('span'));
				span.update('*');
				span.addClassName('Mandatory');
				$(e).down().appendChild(span);
			}
			if ('ajax' == params['validator']){
				$(params['id']).observe('blur', this.onAjaxCheck.bind(this));
				$(params['id']).url = params['url'];
			}

			var invert = (Object.isUndefined(params['reginv'])) ? false : true;
			if (Object.isUndefined(params['reg'])) 
				params['reg'] = false ;
			var v = (!Object.isUndefined(params['validator']))?params['validator']:false;


			if (params['reg'])
				this.toValidate.push({elem: params['id'] , name: params['name'], reg: params['reg'], reginv : invert, validator : false, message : params['message'], error :  params['error'], compareto : params['compareto']});    
			else

				if (v) {
					var validators = v.split(",");
					var errorMessages = (!Object.isUndefined(params['error'])) ? params['error'].split(",") : new Array("Undefinedddd");
					for (var i=0;i<validators.length;i++) {
						var errorMessage = errorMessages.length > i ? errorMessages[i]:errorMessages[0];
						this.toValidate.push({elem: params['id'] , name: params['name'], reg: params['reg'], reginv : invert, validator : validators[i], message : params['message'], error : errorMessage, compareto : params['compareto']});    
					}
				}

		}
	},
	remove : function (elemId){
		this.removeMandatory({id : this.prefix+elemId});
		$("li"+this.prefix+elemId).remove();
	},
	/**
	 * Remove the id from mandatory check, given id must contains prefix.
	 * @author Mika
	 * @updated_at 2011/06/01, Mika,  
	 */
	removeMandatory : function(params){
		var i = 0;
		// 2011/05/04, Mika,  Patching for multiples validators of the same element in the toValidate list.
		while ( i < this.toValidate.length) {
			if (this.toValidate[i]['elem'] == params['id'])
				this.toValidate.remove(i);
			else 
				i++;
		}
		// Remove '*' asterix char from field.
		if (!Object.isUndefined($('li'+params['id']).select(".Mandatory")[0]))
			$('li'+params['id']).select(".Mandatory")[0].remove();
	},
	hideLine : function(id){

	},
	/**
	 * Create an empty line into the params['container'] or if undefined 
	 * into this.container.
	 * A position can be defined using params['position']
	 * @author Mika.
	 */
	newLine : function(params) {
		var li = $(new Element('li'));
		li.id = 'li'+this.prefix+params['id'];
		if(undefined != params['classes'])
			li.className = params['classes'];
		var container = this.container;
		if (!Object.isUndefined(params['container']))
			container = params['container'];
		if (!Object.isUndefined(params['position'])) {
			var position = params['position'];
			if (0 == position || 1 == position)
				Element.insert(container, {top : li});	
		}else
			container.appendChild(li);
		return li;
	},
	emptyLine : function(params) {
		var li = this.newLine(params);
		if (!Object.isUndefined(params['label'])) {
			var label = $(new Element('label'));
			label.update(params['label']);
			li.appendChild(label);
		}
		return li;
	},
	addLine : function(params, elem) {

		li = this.emptyLine(params);

		if (!Object.isUndefined(params['change_callback'])){
			elem.observe('change', params['change_callback']);
		}
		if (!Object.isUndefined(params['click_callback'])){
			elem.observe('click', params['click_callback']);
		}


		if (!Object.isUndefined(params['class'])) 
			elem.addClassName(params['class']);
		if (!Object.isUndefined(params['style']))
			elem.setStyle(params['style']);
		if (!Object.isUndefined(elem)) {    
			elem.id = this.prefix+params['id'];
			elem.name = this.prefix+params['id'];
			li.appendChild(elem);
			this.addMandatory({id : elem.id, reg : params['reg'], reginv : params['reginv'], validator:params['validator'], message:params['message'], error:params['error'], url : params['url'], compareto : params['compareto']});

		}
		// Preparing tooltip, error container.
		var messageField = $(new Element('span'));
		messageField.id = elem.id+"_message_container";
		messageField.addClassName("MessageContainer");

		li.appendChild(messageField);

		var messageFieldIcons = $(new Element('span'));
		messageFieldIcons.id = elem.id+"_message_container_icons";
		messageField.appendChild(messageFieldIcons);
		var messageFieldMessages = $(new Element('span'));
		messageFieldMessages.id = elem.id+"_message_container_messages";
		messageField.appendChild(messageFieldMessages);

		// Checking fo tooltip information.
		if (!Object.isUndefined(params['error']))  
			$(elem).message_error = params['error'];
		if (!Object.isUndefined(params['tooltip']))  {
			var icon = $(new Element('span'));
			icon.id = elem.id+"_icon_tooltip";
			icon.addClassName("FormFieldIconTooltip");
			messageFieldIcons.appendChild(icon);

			var tooltip = $(new Element('span'));
			tooltip.id = elem.id+"_tooltip";
			tooltip.setStyle({display:"none"});
			tooltip.addClassName("FormFieldTooltip");
			tooltip.innerHTML = params['tooltip'];
			messageFieldMessages.appendChild(tooltip);

			$(icon).observe('click', 
					function(e){
				// getting the message container.
				var messageContainer = $(e.element().id.replace("_icon_tooltip", "_message_container_messages"));
				var messages = $A(messageContainer.getElementsByTagName("span"));
				messages.each( function (m){
					if (!m.id.match("_tooltip")) m.hide();
				});
				Effect.toggle(e.element().id.replace("_icon_tooltip", "_tooltip"), 'appear');
			}
			);


		}
		return li;
	},
	addSelect : function(params) {

		var elem = $(new Element('select'));
		var v = "";
		if (!Object.isUndefined(params['rawvalues'])) 
			v = params['rawvalues'];
		else if (!Object.isUndefined(params['value']))
			for (property in params['value'])
				v += "<option value=\""+property+"\">"+ params['value'][property]+"</option>";
		elem.update(v);
		this.addLine(params, elem);
		return elem;
	},
	addSelectOption : function (ownerId, value, text) {
		var elem = $(this.prefix + ownerId);
		if (!Object.isUndefined(elem)) {
			var option = $(new Element('option'));
			option.value = value;
			option.update(text);
			elem.appendChild(option);
		}
	},
	/** 
	 * Add a new Field, with ajax autocomplter behaviours.
	 *   - Select the response you want, add it.
	 *   - remove in the selected list, if you don't want it anymore.
	 * With this widget you can offer multi-choice with ajax/autocompleter supply.
	 * TODO implement it!
	 */
	addMultiAutocompleter : function(params) {

	},
	/**
	 * Allow multiselection by creating a select box, and on onchange event add the selected item to
	 * a list.
	 * awaited values :
	 *    id : future name of the element.
	 *    li : container.
	 *    min : minimum mandatory value to select.
	 *    max : maximum mandatory value to select.
	 * @author Mika
	 * @updated_at 2011/06/01, Mika, Adding Max behaviours, automatizing add by change event and removing add button.
	 */
	addMultiSelect : function(params){
		var elem = $(new Element('select'));
		var v = "<option value=\"select\">Selectionner.</option>";

		if (!Object.isUndefined(params['rawvalues'])) 
			v = params['rawvalues'];
		else if (!Object.isUndefined(params['value']))
			for (property in params['value'])
				v += "<option value=\""+property+"\">"+ params['value'][property]+"</option>";
		elem.update(v);
		if (!Object.isUndefined(params['confirm_message']))
			Object.extend(elem, {confirm_message : params['confirm_message']});

		var line = null;
		// Using li as container.
		if (Object.isUndefined(params['li']))
			line =this.addLine(params, elem);
		else {
			line = params['li'];
			elem.id = elem.name = this.prefix+params["id"];
			line.appendChild(elem);
		}
		/*
		var a = new Element('a');
		a.id = a.name = 'a_'+elem.id;
		a.href = "javascript:void(0);";
		a.update('Ajouter');
		line.appendChild(a);
		 */
		if (!Object.isUndefined(params['max']))  {
			Object.extend(elem, { max : params['max']});
			Object.extend(elem, { current : 0});
		}

		if (!Object.isUndefined(params['min']))  {
			Object.extend(elem, { min : params['min']});
			this.addMandatory({ id : elem.id, validator:"minimum-choice"})
		}

		Event.observe(elem, 'change',this.addMultiSelectElement.bind(this));

		var div = new Element('div');
		div.id = div.name = 'div_'+elem.id;
		line.appendChild(div);
		return elem;	
	},
	addMultiSelectAction : function(elem, value){
		var name = 'selected_'+elem.id+'_'+value;
		/// forbids multiplicity of same elements.
		if (null != $(name))
			return;
		if (!Object.isUndefined(elem.max)) {
			if (elem.current >= elem.max ) {
				alert("Nombre de choix maximum atteint.");
				return;
			} else elem.current++;
		}
		var container = new Element('div');
		
		var cid = $('div_'+elem.id);
		cid.appendChild(container);
		container.id = container.name = name;
		// Ajoute au container principal.
		var hidden = new Element('input');
		hidden.id = hidden.name = elem.id+'_'+value;
		hidden.type = 'hidden';
		hidden.value = value;
		var span = new Element('span');
		// Recherche l'option qui a cet id et récupère la valeur texte.
		for (var i=0;i<elem.options.length;i++)
			if (elem.options[i].value == value) {span.update(elem.options[i].text);break;}; 
			//span.update(elem.options[elem.selectedIndex].innerHTML);

			container.appendChild(hidden);
			container.appendChild(span);
			var remove = new Element('a');
			container.appendChild(remove);
			remove.id = remove.name = 'remove_'+elem.id+'_'+value;
			remove.href="javascript:void(0)";
			remove.update('X');
			remove.observe('click',this.removeMultiSelectElement.bind(this));

	},
	addMultiSelectElement : function(event){
		var elem = $(event.element());
		if (!(/select/).test($F(elem)))
			this.addMultiSelectAction(elem, $F(elem));
	},
	removeMultiSelectElement : function(event) {
		var a = $(event.element());
		var root = /remove_(.*)/.exec(a.id)[1];
		var elem = /(.*)_[0-9]+/.exec(root)[1];
		var selectSrc = /(.*)_[0-9]/.exec(root)[1];
		if (Object.isUndefined($(selectSrc).confirm_message) || confirm($(selectSrc).confirm_message)) {
			$('selected_'+root).remove();
			if (!Object.isUndefined($(elem).max)) {
				$(elem).current--;
			}
			Object.extend(event, { removed : true})
		}
		else 
			Object.extend(event, { removed : false})

	},
	addAntispam : function(params){

	},
	addHidden : function(params){
		var elem = new Element('input');
		elem.type = "hidden";
		elem.name = elem.id = this.prefix+params['id'];
		if (!Object.isUndefined(params['value']))
			elem.value = Base64.decode(params['value']);
		this.form.appendChild(elem);
	},
	addText : function(params){
		var elem = new Element('input');
		elem.type = "text";
		if (!Object.isUndefined(params['value']))
			elem.value = Base64.decode(params['value']);
		var li = this.addLine(params, elem);
		return elem;
	},
	addLabel : function (params){
		var li = this.newLine(params);
		var span = new Element('span');
		span.update(params['label']);
		li.appendChild(span);
		return span;
	},
	addLink : function(params){
		var li = this.newLine(params);
		var a = new Element('a');
		a.href = params['href'];
		a.id = params['id'];
		a.update(params['label']);
		li.appendChild(a);
		return a;
	},
	addPassword : function(params) {
		var elem = new Element('input');
		elem.type = "password";
		var li = this.addLine(params, elem);
		return elem;
	},
	addRadiogroup : function(params){
		var container = li = (Object.isUndefined(params['label'])) ? this.newLine(params) : this.emptyLine(params);
		var style="";
		if (!Object.isUndefined(params['displayer'])){
			var div = new Element('div');
			div.setStyle('float:right;width:65%;');
			container.appendChild(div);
			container = div;
			var style = "float:left;width:49%;";
		}

		for(property in params['value']){
			var elemBoxe = new Element('div');
			elemBoxe.setStyle(style);
			elem = new Element('input');

			elem.name = this.prefix+params['name'];
			elem.type = "radio";
			if (params['select'] == property)
				elem.checked = true;
			elem.value = property;
			elem.id = elem.name+'_'+property;
			span = new Element('label');
			span.setAttribute("for", elem.id);
			span.update(' '+params['value'][property]+' ');
			elemBoxe.appendChild(elem);
			elemBoxe.appendChild(span);
			container.appendChild(elemBoxe);
			if (!Object.isUndefined(params['callback'])){
				elem.observe('click', params['callback']);
			}
		}
		var cleaner = new Element('hr');
		cleaner.addClassName('Cleaner');
		li.appendChild(cleaner);
	},

	addCheckbox : function(params){
		var li = null;
		for(property in params['value']){

			elem = $(new Element('input'));
			elem.name = this.prefix+params['name']+'_'+property;
			elem.type = "checkbox";
			if(params['checked'])
				elem.checked = 'checked';
			elem.value = property;
			elem.id = elem.name;
			// Checking if callback is present.
			if (!Object.isUndefined(params['callback'])) {
				elem.observe("click", params['callback']);
			}
			span = new Element('span');
			span.update(' '+params['value'][property]+' ');
			if (null == li) li = this.addLine(params, elem);
			li.appendChild(elem);
			li.appendChild(span);
		}
		return li;
	},
	addCheckBoxAjaxLoad : function (params){
		/*
	      var r = AjaxSimpleRequest(this.prefix+"Media",'/carpoolin/ajaxmusicambiance);
	      r = r.split(';');
	      var h = new Hash();
	      for (var i=0, len =r.length; i<len; ++i) {
	       var t = r[i].split('/');
	       // Do the addLine.
	       params['label'] = r[1];
	       params['value'] = {r[1] : 'Oui'}
	       this.addCheckbox(params);
	      }
		 */
	},
	addDatetime : function(params){
		var elem = new Element('input');
		elem.type = "text";
		this.addLine(params, elem);
		Calendar.setup({
			inputField : elem.id,
			ifFormat : "%d/%m/%Y @ %H:%M",
			showsTime : true,
			timeFormat : "24"
		});
	},
	/**
	 *  id : used for name and id.
	 *  li : container
	 *  dataurl : ajax url supplier
	 *  must_exist : if set to true, the filled input must exists in back end ajax data
	 *  must_exist_message : error message.
	 */
	addAutocompleter : function(params){
		var elem = $(new Element('input'));
		elem.type = "text";

		var li;
		if (Object.isUndefined(params['li']))
			li = this.addLine(params, elem);
		else {
			li = params['li'];
			elem.id = elem.name = this.prefix+params["id"];
			li.appendChild(elem);
		}
		var span= $(new Element('span')); 
		li.appendChild(span);
		var indicator = $(new Element('img'));
		indicator.id = this.prefix+params['id']+'_indicator';
		indicator.src = "/res/styles/default/img/spinner.gif";
		indicator.setStyle("display:none"); 
		span.appendChild(indicator);

		var elemId = $(new Element('input'));
		elemId.type = "hidden";
		elemId.id = elemId.name = this.prefix+params['id']+"Id";

		Event.observe(elem, "keypress", this.cleanAutcomplete.bind(elemId));
		if (!Object.isUndefined(params['must_exist']) && true == params['must_exist']) {
			Object.extend(elem, { must_exist:true, instance : this, message : params['must_exist_message']})
			Event.observe(elem, "blur", this.onBlurAutocomplete.bind(elem));
		}

		li.appendChild(elemId); 
		var autocomplete = $(new Element('div'));
		autocomplete.id = this.prefix+params['id']+'_autocomplete';
		autocomplete.addClassName('autocomplete');
		autocomplete.setStyle("z-index:103;left:0;display:none");
		li.appendChild(autocomplete);
		params['prefix'] = this.prefix;
		new Ajax.Autocompleter(elem, autocomplete.id, params['dataurl'], {
			paramName: "value",
			minChars: 2,
			callback : this.prepostAutocompleter.bind(params),
			afterUpdateElement: this.updateAutocompleter.bind(elemId),
			indicator: indicator.id
		});

	},
	eventQueueHack : function(){
		if ("" != $F(this.id).trim()) {
			var a = {search:$F(this), id :null,label : ""};
			// Test if input is filled with an existing item.
			$A($(this.id+"_autocomplete").select("li")).each(function(e) {
				if (trim(this.search).toLowerCase() == trim(e.innerHTML).toLowerCase()){
					this.id = e.id;
					this.label = e.innerHTML;
				}
			}.bind(a));

			if (null == a.id) {
				alert(this.message);
			} else {
				$(this.id+"Id").value = a.id;	
			}
		}
	},
	onBlurAutocomplete : function(e){
		// Hack for waiting onClick to be handle before to check. // this is elem.
		setTimeout(this.instance.eventQueueHack.bind(this), 500);
	},
	cleanAutcomplete : function() {
		this.value = "";
	},
	prepostAutocompleter : function(elem, t){
		if (!Object.isUndefined(this['send'])) {
			var vars =this['send'].split(',');
			for (var i=0; i<vars.length; i++)
				t += '&'+vars[i]+'='+$F(this['prefix']+vars[i]);
		}
		return t;
	},
	updateAutocompleter: function(text, li){
		this.value = li.id;
	},
	addTextarea : function(params){
		var elem = $(new Element('textarea'));
		if (!Object.isUndefined(params['value']))
			elem.update(Base64.decode( params['value']));

		var li = this.addLine(params, elem);
		if (!Object.isUndefined(params['decorator'])) {
			if ('tinymce' == params['decorator']){

				var ed = new tinyMCE.Editor(elem.id,  params["tinyMceInit"] || this.options['tinyMceInit']);
				elem.editor = ed;
				ed.render();
				this.options['tinyContext'] = true;
			}
		}
		return li;
	},
	/**
	 * Use it when you want to allow to generate dynamically text fields input.
	 * Create a field, an add button, fill the field, click on add, a new fields 
	 * is generated with a remove button, the master one is cleaned.
	 */
	addDynamicFieldText : function (params){
		var elem = new Element('input');
		elem.type = "text";

		var li = this.addLine(params, elem);
		elem.id = elem.name = elem.id + "_new_0";
		var btn = new Element("input");
		btn.id = elem.id+"Btn";
		btn.type="button";
		btn.value = "Ajouter";
		btn.observe("click", this.onNewDynamicFieldClick.bind(this));
		Element.insert(elem, {after:btn});

		var container = $(new Element("div"));
		container.addClassName("Block");
		container.id = elem.id+"Ctn";
		container.setStyle({display:"block", clear:"both"});
		li.appendChild(container);
		ul = new Element("ul");
		ul.id = elem.id+"CtnUl";
		$(container).appendChild(ul);

	},
	setDynamicFieldText : function (ownerId, elemId, value) {
		var ul = $(this.prefix + ownerId + "_new_0CtnUl");
		var li = new Element("li");
		li.id = "li_"+elemId;
		ul.appendChild(li);

		var dst = new Element("input");
		dst.id = dst.name = elemId;
		dst.type = "text";
		dst.value = Base64.decode(value);
		li.appendChild(dst);

		var btn = new Element("input");
		btn.id = elemId + "Btn";
		btn.type = "Button";
		btn.value = "Supprimer";
		btn.observe("click", this.onNewDynamicFieldRemove.bind(this));
		li.appendChild(btn);
	},
	onNewDynamicFieldClick : function (e) {
		var src = $(e.element().id.replace('Btn',''));
		var i = 0;
		while (null != $(src.id.replace('0',i))) i++;
		this.setDynamicFieldText(src.id.replace(this.prefix, '').replace('_new_0',''), src.id.replace('0',i), Base64.encode(src.value));
		src.value = "";
	},
	onNewDynamicFieldRemove : function (e){
		if (confirm("Etes vous sur de vouloir supprimer le champs ?"))
			$('li_'+ e.element().id.replace('Btn','')).remove();
	},
	removeImage: function(id) {
		if (confirm("Etes vous sur de vouloir supprimer cette image ?")) 
			new AjaxQueryRequest(this.prefix+"Media",'/Content/AddRemovePicture?owner_class='+this.ownerClass+'&picture='+id);
	},
	/**
	 * can set value of Select / Textarea / input / Radio
	 */
	setValue : function(id, value){
		// Select / Textarea / input / Radio
		value = Base64.decode(value);

		//RADIO
		if ($(this.prefix+id+'_'+value)) 
			$(this.prefix+id+'_'+value).checked = true;

		if ($(this.prefix+id)) {
			if ("INPUT" == $(this.prefix+id).tagName) {
				$(this.prefix+id).value = value;
				$(this.prefix+id).checked = "true";
				$(this.prefix+id).selected = "selected";
			}

			if ("TEXTAREA" == $(this.prefix+id).tagName) {
				$(this.prefix+id).update(value);
			}

			if ("SELECT" == $(this.prefix+id).tagName) {
				var a = $(this.prefix+id).getElementsByTagName('option');
				for (var i=0; i<a.length; i++)	a[i].selected = (a[i].value == value)?"selected":"";
			}
		}
	},
	setOptions : function(params){
		var opt = "";
		for (property in params['value'])
			opt += '<option value="'+property+'">'+params['value'][property]+'</option>';
		if (!Object.isUndefined($(params['id'])) && null != $(params['id']))
			$(params['id']).update(opt);
	},
	addAction : function(params){
		// Add a button and on click change the form.action and submit the form.
		var action = new Element('a');
		this.actionsBoxe.appendChild(action);
		action.addClassName('Button');
		action.id = params['id'];
		action.setStyle('float:right');
		action.href = 'javascript:void(0)';
		action.action = params['action'];
		action.update(params['label']);
		action.observe('click', this.fireAction.bind(this));
	},
	fireAction : function(e) {
		var elem = $(e.element());
		this.form.action = elem.action;
		if (this.onSubmit({sender : elem})) {
			this.hasBeenValidated = true;
			//alert(this.form.id);
			if (this.options['isAjaxSubmit']) {
				this.form.request({ 
					parameters : {isAjax : true},
					onSuccess: function(t) {
						if (null != this.options['ajaxSubmitResponseContainer']) {
							var allscript = t.responseText.extractScripts();
							$( this.options['ajaxSubmitResponseContainer']).update(t.responseText.stripScripts());
							for(var i=0;i< allscript.length;i++)
								window.eval(allscript[i]);
						}
					}.bind(this) 
				});
			}
			//
			else
				this.form.submit();
		} 
		else
			this.hasBeenValidated = false;
	}

});



Essilab.Form.displayHint = function (sender,message){


	if (null == $('HINT_BOX')) {

		sender =$(sender);

		this.box = $(new Element('div'));

		this.box.style.width = $(sender).getWidth()+'px';
		//this.box.style.height = '75px';
		this.box.style.backgroundColor="white";
		this.box.style.border="1px solid #d0520a";
		this.box.style.position = 'absolute';
		this.box.id = "HINT_BOX";
		this.box.style.zIndex = 102;
		this.box.style.padding = "5px";

		//

		var mes = $(new Element('div'));
		mes.id="HINT_BOX_MESSAGE";
		this.box.appendChild(mes);

		// Angles, Pointe
		var pointe = $(new Element('div'));
		pointe.style.left= "25px";
		pointe.style.top= "-9px";
		pointe.style.backgroundImage = "url('/res/styles/default/img/message_box_bg.png')";
		pointe.style.backgroundPosition = "-10px 0px";
		pointe.style.width = "10px";
		pointe.style.height = "10px";
		pointe.style.position = "absolute";
		pointe.innerHTML = "&nbsp;";
		this.box.appendChild(pointe);
		$$('body').first().appendChild(this.box);
	}

	this.box.style.display = "block";
	this.box.style.left = Element.getX($(sender))+"px";
	this.box.style.top = (Element.getY($(sender))+$(sender).getHeight()+5)+"px";
	$('HINT_BOX_MESSAGE').innerHTML ='<b style="color:gray;font-weight:bold">'+message+'</b>'  ;
	//$('HINT_BOX').appear({duration:0.6, from:0, to:1});
};

Essilab.Form.hideHint = function(){
	if (null != $('HINT_BOX'))
		$('HINT_BOX').fade({duration:0.3});
};   

Essilab.Form.close = function(elem) {
	$(elem).remove();
};
Essilab.Form.addEvent = function ( obj, type, fn ) {
	if ( obj.attachEvent ) {
		obj['e'+type+fn] = fn;
		obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
		obj.attachEvent( 'on'+type, obj[type+fn] );
	} else
		obj.addEventListener( type, fn, false );
};
Essilab.Form.removeEvent = function ( obj, type, fn ) {
	if ( obj.detachEvent ) {
		obj.detachEvent( 'on'+type, obj[type+fn] );
		obj[type+fn] = null;
	} else
		obj.removeEventListener( type, fn, false );
};


Essilab.Form.Message = Class.create({
	initialize : function(sender, message){

		// Mask
		this.mask = $(new Element('div'));
		this.mask.id = "MESSAGE_BOX_MASK";
		this.mask.style.zIndex = 101;
		//this.mask.style.display ='none';
		this.mask.style.width = $$('html').first().getDimensions()['width']+"px";
		this.mask.style.height = $$('html').first().getDimensions()['height']+"px";
		this.mask.style.backgroundColor = "gray";
		this.mask.setOpacity(0.3);
		this.mask.style.position = "absolute";
		this.mask.style.top = 0;
		this.mask.style.left = 0;
		// Box

		this.box = $(new Element('div'));
		this.box.style.width = '200px';
		//this.box.style.height = '75px';
		this.box.style.backgroundColor="white";
		this.box.style.border="1px solid #d0520a";

		this.box.style.position = 'absolute';
		this.box.id = "MESSAGE_BOX";
		this.box.style.zIndex = 102;
		this.box.style.padding = "5px";
		this.box.style.paddingBottom = "25px";
		this.box.style.left = Element.getX($(sender))+"px";
		this.box.style.top = (Element.getY($(sender))+$(sender).getHeight()+5)+"px";
		this.box.innerHTML = message + '<a style="text-align:right;width:inherit;bottom:5px;position:absolute;display:block;border-top:1px solid #ECECEC;" href="javascript:void(0);" onclick="Essilab.Form.close(\'MESSAGE_CONTAINER\');">Fermer</a>';
		// Angles, Pointe
		var pointe = $(new Element('div'));
		pointe.style.left= "25px";
		pointe.style.top= "-9px";
		pointe.style.backgroundImage = "url('/res/styles/default/img/message_box_bg.png')";
		pointe.style.backgroundPosition = "-10px 0px";
		pointe.style.width = "10px";
		pointe.style.height = "10px";
		pointe.style.position = "absolute";
		pointe.innerHTMl = "&nbsp;";

		this.box.appendChild(pointe);

		this.container = new Element('div');
		this.container.id = "MESSAGE_CONTAINER";
		this.container.style.position = "ABSOLUTE";
		this.container.style.top = 0;
		this.container.style.left = 0;

		this.container.appendChild(this.mask);
		this.container.appendChild(this.box);
		$$('body').first().appendChild(this.container);
	}

});
