
var Display = {};

/**
 * Affichage d'un message d'alerte ou d'info
 * Exemple : new Display.Message("Votre message", {cssClass: "adm-alerte"});
 */
Display.Message = Class.create();
Display.Message.prototype = {

	/**
	 * constructeur de la classe
	 */
	initialize: function(msg, options) {
		
		// Définition des parametres
		this.msg		= msg; // message HTML
		this.id_div		= 'message_alerte_123';
		this.id_cache	= 'cache-message';
		this.classCache = 'cache';
		this.cache		= false;
		this.id_ancre	= ''; // id de l'element ancre pour le positionnement
		this.plusTop	= 0;
		this.plusLeft	= 0;
		this.width		= 0;
		this.speed		= 0.4;
		this.duration	= 4; // duree d'affichage du message (en sec)
		this.cssClass	= 'adm-alerte';
		this.options	= {};
		
		Object.extend(this.options, options || {});
		
		// on affecte les propriétés des options
		for (var o1 in this) {
			for (var o2 in this.options) {
				if (o1==o2) {
					this[o1] = this.options[o2];
				}
			}
		}

		this.open();

	}, // fin du constructeur

	/**
	 * Affichage du message
	 */
	open: function () {
		
		// déclaration des variables
		duration = this.duration;
		speed = this.speed;
		activecache = this.cache;
		var obj = this;
			
		// on regarde si le div d'alerte existe, si oui on l'efface
		if ($(this.id_div)) {
			$(this.id_div).remove(); 
		}
		
		// on regarde si le div d'alerte existe, si oui on l'efface
		if ($(this.id_cache)) {
			$(this.id_cache).remove();
		}
		
		// création et affichage du cache
		var cache = document.createElement("div");
		document.body.appendChild(cache);
		cache.className = this.classCache;


		if (Prototype.Browser.IE) {
			var screenH = document.documentElement.clientHeight;
			var screenW = document.documentElement.clientWidth;
		} else {
			var screenH = window.innerHeight;
			var screenW = window.innerWidth;
		}

		if (activecache) {
			// on applique les attributs au div créé
			cache.id = this.id_cache;
			cache.style.display = "block";
			//cache.style.width = (screenW + document.documentElement.scrollLeft)+"px";
			cache.style.height = (screenH + document.documentElement.scrollTop)+"px";
		}
		
		// on créé le div en DOM et on le place dans le body
		var o = document.createElement("div");
		document.body.appendChild(o);
		
		// on applique les attributs au div créé
		o.id = this.id_div;		
		o = $(this.id_div);		
		o.setStyle({
			display: "none",
			position: "absolute"
		});
		o.update(this.msg);
		
		// choix de la classe en fonction du type d'alerte
		o.className = this.cssClass;
		
		// on close l'alerte qd on clique dessus
		o.observe('click', function(event){
			new Effect.Fade(o, {delay: 0, duration: speed, queue : {position:'front', scope: 'msgscope'},beforeStart:function(){ if(activecache){ new Effect.Fade(cache, {delay: 0, duration: speed*3});}}});
		});
		
		// on place le div par rapport à l'ancre
		if ($(this.id_ancre)) {
			var ancre = $(this.id_ancre);		
			
			var pos = Position.positionedOffset(ancre);
			var top = pos[1];
			var left = pos[0];
			var width = ancre.getWidth();
			
			if (this.plusTop)
				o.style.top = (top + parseInt(this.plusTop)) + "px";
			else
				o.style.top = (top - 5) + "px";
			
			if (this.plusLeft)
				o.style.left = (left + parseInt(this.plusLeft)) + "px";
			else
				o.style.left = left + "px";
			
			if (this.width)
				o.style.width = (width - 34 + parseInt(this.width)) + "px";
			else
				o.style.width = (width - 34) + "px";
		} else {

			// on place au centre de la page
			if (Prototype.Browser.IE) {
				var screenH = document.documentElement.clientHeight;
				var screenW = document.documentElement.clientWidth;
			} else {
				var screenH = window.innerHeight;
				var screenW = window.innerWidth;
			}
			var posTop = (screenH / 2) - (o.getHeight() / 2) + document.documentElement.scrollTop;
			var posLeft = (screenW / 2) - (o.getWidth() / 2) + document.documentElement.scrollLeft;
			o.style.top = posTop + "px";
			o.style.left = posLeft + "px";
			
		} // fin du if
		
		// on affiche le message créé avec scriptaculous (fadeout au bout de 4sec)
		new Effect.Appear(o, {duration: speed, queue : {position:'front', scope: 'msgscope'} });
		new Effect.Fade(o, {delay: this.duration, duration: speed, queue : {position:'end', scope: 'msgscope'},
			beforeStart:function(){
				if (activecache) {
					new Effect.Fade(cache, {delay: duration, duration: speed*3});
				}
			}
		});
		
		
	} // fin de open
	
}; // fin de Display.Message


/**
 * Affichage d'un message d'attente
 * Exemple : new Display.Wait({msg: "Veuillez patienter", cssClass: "adm-wait", cache: true});
 */
Display.Wait = Class.create();
Display.Wait.prototype = {

	/**
	 * constructeur de la classe
	 */
	initialize: function(options) {

		// definition des parametres
		this.msg		= 'Veuillez patienter ...'; // message HTML
		this.id_div		= 'form-wait';
		this.id_cache	= 'cache-wait';
		this.cache		= false;
		this.classCache = 'cache';
		this.id_ancre	= ''; // id de l'element ancre pour le positionnement
		this.plusTop	= 0;
		this.plusLeft	= 0;
		this.width		= 0;
		this.speed		= 0.4;
		this.cssClass	= 'form-wait';
		this.ajaxImg	= 'images/ajax-loader.gif';
		this.ajaxImgH	= 15;
		this.ajaxImgW	= 15;
		this.onFinish	= Prototype.emptyFunction;
		this.options	= {};

		Object.extend(this.options, options || {});
		
		// on affecte les propriétés des options
		for (var o1 in this) {
			for (var o2 in this.options) {
				if (o1==o2) {
					this[o1] = this.options[o2];
				}
			}
		}

		this.open();

	}, // fin du constructeur

	/**
	 * Affichage du message
	 */
	open: function () {
		
		// déclaration des variables
		speed = this.speed;
		activecache = this.cache;
			
		// on regarde si le div d'alerte existe, si oui on l'efface
		if ($(this.id_div)) {
			$(this.id_div).remove(); 
		}
		
		// on regarde si le div de cache existe, si oui on l'efface
		if ($(this.id_cache)) {
			$(this.id_cache).remove();
		}
		
		// création et affichage du cache
		var c = document.createElement("div");
		document.body.appendChild(c); 
		c.className = this.classCache;
		
		if (activecache) {
			// on applique les attributs au div créé
			c.id = this.id_cache;
			c.style.display = "block";
		}
		
		// on créé le div en DOM et on le place dans le body
		var o = document.createElement("div");
		document.body.appendChild(o);
		
		// on applique les attributs au div créé
		o.id = this.id_div;		
		o = $(this.id_div);
		
		o.setStyle({
			display: 'block',
			opacity: 0.999999,
			position: 'absolute'
		});
		o.update('<img src="' + this.ajaxImg + '" height="' + this.ajaxImgH + '" width="' + this.ajaxImgW + '" align="absbottom" /> ' + this.msg);
		
		// choix de la classe en fonction du type d'alerte
		o.className = this.cssClass;
		
		// on place le div par rapport à l'ancre
		if ($(this.id_ancre)) {
			var ancre = $(this.id_ancre);		
			
			var pos = Position.positionedOffset(ancre);
			var top = pos[1];
			var left = pos[0];
			var width = ancre.getWidth();
			
			if (this.plusTop)
				o.style.top = (top + parseInt(this.plusTop)) + "px";
			else
				o.style.top = (top - 5) + "px";
			
			if (this.plusLeft)
				o.style.left = (left + parseInt(this.plusLeft)) + "px";
			else
				o.style.left = left + "px";
			
			if (this.width)
				o.style.width = (width - 34 + parseInt(this.width)) + "px";
			else
				o.style.width = (width - 34) + "px";
		} else {

			// on place au centre de la page
			if (Prototype.Browser.IE) {
				var screenH = document.documentElement.clientHeight;
				var screenW = document.documentElement.clientWidth;
			} else {
				var screenH = window.innerHeight;
				var screenW = window.innerWidth;
			}
			var posTop = (screenH / 2) - (o.getHeight() / 2) + document.documentElement.scrollTop;
			var posLeft = (screenW / 2) - (o.getWidth() / 2) + document.documentElement.scrollLeft;
			o.style.top = posTop + "px";
			o.style.left = posLeft + "px";
			
		} // fin du if
		
		// on affiche le message créé avec scriptaculous
		//new Effect.Opacity(o, {duration:speed, from:0.0, to:1.0, queue: {position: 'front', scope: 'waitscope'}});

	}, // fin de open

	/**
	 * Effacage du message
	 */
	close: function (options) {

		Object.extend(this.options, options || {});
		
		// on affecte les propriétés des options
		for (var o1 in this) {
			for (var o2 in this.options) {
				if (o1==o2) {
					this[o1] = this.options[o2];
				}
			}
		}

		var obj = this;
		
		var o = $(this.id_div);
		var c = $(this.id_cache);
		
		new Effect.Opacity(o, {duration: this.speed, from:1.0, to:0.0, queue: {position: 'end', scope: 'waitscope'},
		//new Effect.Fade(o, {duration: speed, queue : {position:'end', scope: 'waitscope'}, 
			afterFinish: function() {
				if (obj.cache) {
					c.setStyle({display: 'none'});
				}
				if (obj.options.onFinish) {
					obj.options.onFinish();
				}
				o.setStyle({display: 'none'});
			}
		});
	
	} // fin de close

}; // fin de Display.Wait


/**
 * Formulaire en superposition
 */
Display.DivForm = Class.create();
Display.DivForm.prototype = {

	/**
	 * constructeur de la classe
	 */
	initialize: function(options) {

		// Définition des paramètres
		this.cacheId	= 'cache-popup'; // id du cache
		this.classCache = 'black_overlay';
		this.formId		= 'container-popup'; // id du div contenant le form
		this.options	= {};

		Object.extend(this.options, options || {});
		
		// on affecte les propriétés des options
		for (var o1 in this) {
			for (var o2 in this.options) {
				if (o1==o2) {
					this[o1] = this.options[o2];
				}
			}
		}
		
		//this.open();
		
	}, // fin du constructeur
	
	open: function () {
		// on se place en haut de la page
		self.scrollTo(0,0);
		
		// on créé un cache
		if ($(this.cacheId)) {
			$(this.cacheId).remove();
		}
		var cache = document.createElement("div");
		cache.id = this.cacheId;
		document.body.appendChild(cache);
		cache.className = this.classCache;

		cache = $(this.cacheId);
		
		// on créé le div du formulaire
		if ($(this.formId)) {
			$(this.formId).remove();
		}
		var form = document.createElement("div");
		form.id = this.formId;
		document.body.appendChild(form);
		
		form = $(this.formId);
		
		form.style.display = "block";
		form.style.opacity = 0.5;

		var h = document.documentElement.scrollHeight;
		var w = document.documentElement.scrollWidth;
		// now IE 7 + Opera with "min window"
		if ( document.documentElement.clientHeight > h ) { h  = document.documentElement.clientHeight; }
		if ( document.documentElement.clientWidth > w ) { w  = document.documentElement.clientWidth; }
		// last for safari
		if ( document.body.scrollHeight > h ) { h = document.body.scrollHeight; }
		if ( document.body.scrollWidth > w ) { w = document.body.scrollWidth; }
	
		cache.style.height = h + "px";
		cache.style.display = 'block';
		
		cache.observe('click', function(event){
			obj.close();
		});
		
		// on cache les elements qui passent au dessus du div
		this.hideTags(1);

		var obj = this;
		
		//new Effect.Scale(form.id, 100, {duration:0.3 ,scaleContent:false, scaleFrom:70, scaleFromCenter:true, afterFinish: function() {
		new Effect.Opacity(form, {duration:0.5, fps:25, from:0.5, to:1.0, afterFinish: function() {
			if (obj.options.onFinish) {
				obj.options.onFinish();
			}
		}});
		
	}, // fin de open
	
	/**
	 * Fermeture du div superposé
	 */
	close: function () {

		var cache = $(this.cacheId);
		var form = $(this.formId);
		
		form.update("");
		
		//new Effect.Shrink(formId, {duration: 0.7});
		new Effect.Opacity(form, {duration:0.5, fps:25, from:1, to:0.5, afterFinish: function() {
			form.style.display = "none";
			cache.style.display = 'none';			
		}});
	
		// on remet les elements effacés 
		this.hideTags(0);
		
	}, // fin de close
	
	/**
	 * Cachage ou affichage d'elements pour l'affichage d'une div en superposition
	 */
	hideTags: function (t) {
		var tags = new Array("applet", "iframe", "select", "object");
	
		for (var k = tags.length; k > 0; ) {
			var ar = document.getElementsByTagName(tags[--k]);
			var cc = null;
	
			for (var i = ar.length; i > 0;) {
				cc = ar[--i];
	
				if (t==0) {
					cc.style.visibility = "visible";
				} else {
					cc.style.visibility = "hidden";
				}
			} // fin du for
		} // fin du for
	}
}; // fin de DivForm

/**
 * Affichage d'une popup
 */
Display.Popup = Class.create();
Display.Popup.prototype = {

	/**
	 * constructeur de la classe
	 */
	initialize: function(url, options) {
		
		// Définition des paramètres
		this.url		= url;
		this.name		= 'popup'; 
		this.win		= null;
		this.pos		= 'center'; // postion centrée ou random
		this.width		= 500;
		this.height		= 500;
		this.scroll		= 'yes';
		this.resize		= 'yes';
		this.options	= {};
		
		Object.extend(this.options, options || {});
		
		// on affecte les propriétés des options
		for (var o1 in this) {
			for (var o2 in this.options) {
				if (o1==o2) {
					this[o1] = this.options[o2];
				}
			}
		}

		this.open();

	}, // fin du constructeur

	/**
	 * Affichage de la popup
	 */
	open: function () {
				
		if (this.pos=="random") {
			LeftPosition=(screen.width)?Math.floor(Math.random()*(screen.width-this.width)):100;TopPosition=(screen.height)?Math.floor(Math.random()*((screen.height-this.height)-75)):100;
		}
		if (this.pos=="center") {
			LeftPosition=(screen.width)?(screen.width-this.width)/2:100;TopPosition=(screen.height)?(screen.height-this.height)/2:100;
		} else if ((this.pos!="center" && this.pos!="random") || this.pos==null){
			LeftPosition=0;
			TopPosition=20;
		}
		settings = 'width='+this.width;
		settings+= ',height='+this.height;
		settings+= ',top='+TopPosition;
		settings+= ',left='+LeftPosition;
		settings+= ',scrollbars='+this.scroll;
		settings+= ',location=no';
		settings+= ',directories=no';
		settings+= ',status=no';
		settings+= ',menubar=no';
		settings+= ',toolbar=no';
		settings+= ',resizable='+this.resizable;
		
		this.win = window.open(this.url, this.name, settings);
		this.win.focus(this.name);
		
	} // fin de open
	
}; // fin de Display.Popup

/**
 * Scroller de contenu (automatique + pagination)
 * Exemple : new Display.Scroller('scroller-container', { itemClassName: 'scroller-item', bulletClassName: 'scroller-page', colWidth: 974, pagination: true, transition: 'fade', paginationOverMode: 'image', paginationOverSuffix: '-on' } );
 */
Display.Scroller = Class.create();
Display.Scroller.prototype = {

	/**
	 * constructeur de la classe
	 */
	initialize: function(idScroller, options) {
		
		// Définition des paramètres
		this.currentPage			= 0;
		this.prevPage				= 0;
		this.nbPage					= 0;
		this.nbCol					= 0; 
		this.nbColPage				= 1; // nb de colonne par page
		this.colWidth				= 100;
		this.isBlocked				= false;
		this.idScroller				= idScroller;
		this.itemClassName			= "box-item";
		this.bulletClassName		= "box-bullet";
		this.duration				= 1;
		this.timer 					= true;
		this.timerDuration			= 5;
		this.pe						= null;
		this.pagination				= true;
		this.paginationOverMode		= 'opacity'; // opacity | image
		this.paginationOverSuffix	= '-on'; // suffixe de l'image en cas de paginationOverMode "image"
		this.transitionMode			= 'move'; // move | fade
		this.transition				= Effect.Transitions.sinoidal;
		this.mouseWheelEnabled		= true;
		this.options				= {};
		
		Object.extend(this.options, options || {});
		
		// on affecte les propriétés des options
		for (var o1 in this) {
			for (var o2 in this.options) {
				if (o1==o2) {
					this[o1] = this.options[o2];
				}
			}
		}

		if (!$(idScroller))
			alert(idScroller + " introuvable !");
		else
			this.start();

	}, // fin du constructeur

	/**
	 * Initialisation du scroller
	 */
	start: function ()
	{
		var obj = this;
		
		$(this.idScroller).observe("mouseover", this.scrollerOver.bindAsEventListener(this));
		$(this.idScroller).observe("mouseout", this.scrollerOut.bindAsEventListener(this));
		
		if ($(obj.idScroller).style.position != "absolute")
			$(obj.idScroller).style.position = "absolute";
		
		// on compte le nb d'élément du scroller
		$$("." + this.itemClassName).each(function(el) {
			el.id = obj.itemClassName + obj.nbCol;
			obj.nbCol ++;
		});
		if (this.pagination) {
			var cpt = 0;
			$$("." + this.bulletClassName).each(function(el) {
				el.id = obj.bulletClassName + cpt;
				el.observe("click", obj.clickPageBullet.bind(obj));
				cpt ++;
			});
		}
		if (this.nbCol % this.nbColPage == 0)  {
			this.nbPage = Math.floor(this.nbCol / this.nbColPage);
		} else {
			//this.nbPage = Math.floor(this.nbCol / this.nbColPage);
			this.nbPage = (Math.floor(this.nbCol / this.nbColPage) + 1);
		}
		
		switch (this.transitionMode) {
			case "move":
				$(this.idScroller).style.width = "10000px";
			break;
			case "fade":			
				$(this.idScroller).style.position = "absolute";
				var cpt = 0;
				$$("." + this.itemClassName).each(function(el) {
					el.style.position = "absolute";
					el.style.zIndex = obj.nbPage - cpt;
					cpt ++;
				});
			break;
		}	
		
		if (this.mouseWheelEnabled) {
			// mozilla
			Event.observe(this.idScroller, 'DOMMouseScroll', this.mouseWheel.bindAsEventListener(this));	
			// IE/Opera
			Event.observe(this.idScroller, 'mousewheel', this.mouseWheel.bindAsEventListener(this));	
		}
		
		this.managePagination();
		
		if (this.timer)
			this.pe = new PeriodicalExecuter(this.nextPage.bind(this), this.timerDuration);
		
	}, // fin de start
	
	/**
	 * Initialisation du scroller
	 */
	managePagination: function ()
	{
		var obj = this;

		if (this.pagination) {
			// bullets
			$$("." + this.bulletClassName).each(function(el) {
				switch (obj.paginationOverMode) {
					case "opacity":
						el.setOpacity(0.5);
					break;
					case "image":
						var regExp = new RegExp(obj.paginationOverSuffix);
						el.src = el.src.replace(regExp,"");
					break;
				}
				el.style.cursor = "pointer";
			});
			// current
			switch (this.paginationOverMode) {
				case "opacity":
					$(this.bulletClassName + this.currentPage).setOpacity(1);
				break;
				case "image":
					var src = $(this.bulletClassName + this.currentPage).src;
					var ext = src.substring(src.lastIndexOf('.'));
					var prefix = src.substring(0, src.length - ext.length);
					$(this.bulletClassName + this.currentPage).src = prefix + this.paginationOverSuffix + ext;
				break;
			}
			$(this.bulletClassName + this.currentPage).style.cursor = "auto";
		}
		
	}, // fin de managePagination
	
	mouseWheel: function(event)
	{
		if (!this.isBlocked) {
			var delta = 0;
			if (!event) /* For IE. */
				event = window.event;
			if (event.wheelDelta) { /* IE/Opera. */
				delta = event.wheelDelta/120;
				/** In Opera 9, delta differs in sign as compared to IE. */
				if (window.opera)
					delta = -delta;
			} else if (event.detail) { /** Mozilla case. */
				/** In Mozilla, sign of delta is different than in IE.
				* Also, delta is multiple of 3.
				*/
				delta = -event.detail/3;
			}
			if (delta) {
				if (delta > 0)
					this.nextPage();
				else
					this.prevPage();
					
				if (this.timer && this.pe != null ) {
					this.pe.stop(); this.pe = null;
					this.pe = new PeriodicalExecuter(this.nextPage.bind(this), this.timerDuration);	
				}
			}
	
			if (event.preventDefault)
				event.preventDefault();
			
			event.returnValue = false;
		}
	}, // fin de mouseWheel
	
	/**
	 * Click sur une page
	 */
	clickPageBullet: function(event)
	{
		if (!this.isBlocked) {
			var el = event.findElement();
			var page = parseFloat(el.id.replace(this.bulletClassName, ""));
			this.prevPage = this.currentPage;
			this.currentPage = page;
			this.changePage(page - this.prevPage);
			el.blur();
			this.managePagination();
			
			if (this.timer && this.pe != null) {
				this.pe.stop(); this.pe = null;
				this.pe = new PeriodicalExecuter(this.nextPage.bind(this), this.timerDuration);	
			}
		}
	},  // fin de clickPageBullet
	
	/**
	 * Changement de page
	 */
	changePage: function(cpt)
	{
		if (!this.isBlocked) {
			var delta = - this.nbColPage * this.colWidth;
			this.isBlocked = true;
			var obj = this;
			switch (this.transitionMode) {
				case "move":
					new Effect.Move(this.idScroller, { duration: this.duration , x: cpt * delta, transition: this.transition, afterFinish: function(el) { obj.isBlocked = false; }} );
				break;
				case "fade":
					var cpt = 0;
					var prevItem = null;
					var currentItem = null;
					$$("." + this.itemClassName).each(function(el) {
						if (obj.prevPage == cpt) {
							prevItem = el;
						} else if (obj.currentPage == cpt) {
							currentItem = el;
							el.show();
						} else {
							el.hide();
						}
						cpt ++;
					});
					prevItem.style.zIndex = 2;
					currentItem.style.zIndex = 1;
					new Effect.Fade(prevItem, { duration: obj.duration / 2, transition: obj.transition,  afterFinish: function() {
						obj.isBlocked = false;
					}} );

				break;
			}			
		}
	},  // fin de changePage
	
	/**
	 * Page suivante
	 */
	nextPage: function()
	{
		this.prevPage = this.currentPage;
		this.currentPage += 1;
		if (this.currentPage > this.nbPage - 1) {
			this.currentPage = 0;
		} else if (this.currentPage < 0) {
			this.currentPage = this.nbPage - 1;
		}
		this.changePage(this.currentPage - this.prevPage);
		this.managePagination();
		
	},  // fin de nextPage
	
	/**
	 * Page précédente
	 */
	prevPage: function()
	{
		this.prevPage = this.currentPage;
		this.currentPage -= 1;
		if (this.currentPage > this.nbPage - 1) {
			this.currentPage = 0;
		} else if (this.currentPage < 0) {
			this.currentPage = this.nbPage - 1;
		}
		this.changePage(this.currentPage - this.prevPage);
		this.managePagination();
		
	},  // fin de prevPage
	
	/**
	 * Mouse Over scroller
	 */
	scrollerOver: function()
	{
		if (this.timer && !this.isBlocked && this.pe != null) {
			this.pe.stop(); this.pe = null;
		}
	},  // fin de scrollerOver
	
	/**
	 * Mouse Over scroller
	 */
	scrollerOut: function()
	{
		if (this.timer && !this.isBlocked && this.pe == null)
			this.pe = new PeriodicalExecuter(this.nextPage.bind(this), this.timerDuration);
	} // fin de scrollerOut
	
}; // fin de Display.Scroller



/**
 * Affichage d'une liste d'autocomplete sur un champ texte
 * Exemple : new Display.AutoComplete("search", {cssClass: "adm-alerte"});
 */
Display.AutoComplete = Class.create();
Display.AutoComplete.prototype = {

	/**
	 * constructeur de la classe
	 */
	initialize: function(id, options) {
		
		// Définition des parametres
		this.id_container 	= id + '_container';
		this.id_id		 	= id + '_id';
		this.id_value		= id + '_value';
		this.id_loading		= id + '_loading';
		this.cssClass 		= 'autocomplete';
		this.url			= '_ajax/autoComplete.php';
		this.params 		= ''; // &param1=1&param2=2 ...
		this.minChars 		= 2;
		this.pe 			= null;
		this.index 			= -1;
		this.current 		= null;
		this.duration		= 0.25; // duree d'affichage (en sec)
		this.delaySearch	= 0.2; // temps maximum entre deux recherche
		this.peDelaySearch 	= null;
		this.appearContainer= null;
		this.onSearch		= Prototype.emptyFunction;
		this.onSelect		= Prototype.emptyFunction;
		this.options		= {};
		
		Object.extend(this.options, options || {});
		
		// on affecte les propriétés des options
		for (var o1 in this) {
			for (var o2 in this.options) {
				if (o1==o2) {
					this[o1] = this.options[o2];
				}
			}
		}

		this.elt = $(id);
		this.container = $(this.id_container);

		this.elt.observe('keyup', this.keyEvent.bind(this));
		this.elt.observe('focus', this.focusEvent.bind(this));
		this.elt.observe('blur',  this.blurEvent.bind(this));
		
		// on bloque la soumission du formulaire s'il y en a un	
		if (this.elt.up('form')) {
			var obj = this;			
			this.elt.up('form').observe('submit', function(event) {
				if (obj.container.visible()) {
					Event.stop(event);
				}
			});
		}

	}, // fin du constructeur

	/**
	 * 
	 */
	focusEvent: function(event)
	{
		this.search();
	},
	blurEvent: function(event)
	{
		if (this.current) {
			this.select(this.current.readAttribute("ac_id"), this.current.readAttribute("ac_value"));
			this.close();
		}
		
		this.pe = new PeriodicalExecuter(this.peEvent.bind(this), 0.15);
	},
	peEvent: function(pe)
	{
		this.close();
		this.pe = pe;
		this.pe.stop();
	},
	keyEvent: function(event)
	{
		switch (event.keyCode) {
			case Event.KEY_DOWN:
				this.upDown(1);
			break;
			case Event.KEY_UP:
				this.upDown(-1);
			break;
			case Event.KEY_RETURN:
				if (this.current) {
					this.select(this.current.readAttribute("ac_id"), this.current.readAttribute("ac_value"));
					this.close();
				}
			break;
			default:
				if (this.delaySearch != 0) {
					// on lance le delay entre 2 keydown
					if (this.peDelaySearch != null) {
						this.peDelaySearch.stop();
					}
					this.peDelaySearch = new PeriodicalExecuter(this.peDelaySearchEvent.bind(this), this.delaySearch);
				} else {
					this.search();
				}
		}
	},
	peDelaySearchEvent: function(pe)
	{
		this.search();
		this.peDelaySearch.stop();
		this.peDelaySearch = null;
	},

	upDown: function(cpt)
	{
		this.index += cpt;
		var cResult = this.container.select("a");
		if (this.index > cResult.size() -1 ) {
			this.index --;
		} else if (this.index < 0) {
			this.index = 0;
		}
		if (this.current) {
			this.current.removeClassName("current");
		}
		this.current = cResult.toArray()[this.index];
		this.current.addClassName("current");

		//this.select(this.current.readAttribute("ac_id"), this.current.readAttribute("ac_value"));
	},
	search: function()
	{
		if (this.options.onSearch) {
			this.params = this.options.onSearch();
		}
		
		if (this.pe) { this.pe.stop(); this.pe = null; }
		if ($(this.id_id)) { $(this.id_id).value = ""; }
		
		var s = this.elt.value;
		var obj = this;
		if (s.length >= this.minChars) {
			var url = this.url +  '&' + this.elt.id + '=' + encodeURIComponent(s) + this.params;
			//alert(url);
			if ($(this.id_loading)) { new Effect.Appear(this.id_loading, {duration: this.duration}); }
			new Ajax.Request(url, {
				method: 'get',
				asynchronous: false,
				onSuccess: function(transport) {
					obj.container.show();
					obj.container.update(transport.responseText);
					if ($(obj.id_loading)) { new Effect.Fade(obj.id_loading, {duration: obj.duration}); }
					
					// on compte le nb de résultats
					var cResult = obj.container.select("a");
					if (cResult.size() > 0) {
						var first = cResult.toArray()[0];
						if (cResult.size() == 1) {
							obj.index = 0;
							obj.upDown(0);
						}
						cResult.each( function(o) {
							o.observe('click',  obj.clickItem.bindAsEventListener(obj, o));
						});
					}
					
					// nb de lignes
					/*var cLine = this.container.select("div");
					var h = cLine.toArray()[0].getHeight();
					this.container.style.height = (cLine.size() * h) + "px";*/
					
					if (obj.appearContainer) { obj.appearContainer.cancel(); }					
					obj.appearContainer = new Effect.Opacity(obj.container, {from:0, to:1, duration: obj.duration, afterFinish: function() { obj.appearContainer = null; } });
					//this.container.show();
				}
			});			
			
		} else {
			this.close();
		}
	},
	clickItem: function(event)
	{
		if (this.pe) { this.pe.stop(); this.pe = null; }
		var data = $A(arguments);
		data.shift();
		var a = data[0];
		this.select(a.readAttribute('ac_id'), a.readAttribute('ac_value'));
		this.close();
	},
	select: function(id, value)
	{
		if (this.pe) { this.pe.stop(); this.pe = null; }
		if ($(this.id_id)) { $(this.id_id).value = id; }
		this.elt.value = value;
		if (this.options.onSelect) {
			this.options.onSelect();
		}
	},
	close: function()
	{
		new Effect.Fade(this.container, {duration: this.duration});//container.hide();
		this.index = -1;	
		this.current = null;
	}
	
}; // fin de Display.AutoComplete

