function liste_autocomplete(obj,ca){

	

	/* ---- Variables publiques ---- */
	this.timeOut =-1; //  Timeout in ms (-1: autocomplete never time out)
	this.lim = 5;    // Number of elements autocomplete can show (-1: no limit)
	this.firstText = false; // should the auto complete be limited to the beginning of keyword?
	this.mouse = true; // Enable Mouse Support
	this.delimiter = new Array(';',',');  // Delimiter for multiple autocomplete. Set it to empty array for single autocomplete
	this.startcheck = 1; // Show widget only after this number of characters is typed in.
	/* ---- Public Variables ---- */

	/* --- Styles --- */
	this.bgColor = 'white';
	this.textColor = 'black';
	this.hColor = '#C0C0C0';
	this.fFamily = 'verdana, arial, sans-serif';
	this.fSize = '10px';
	this.hStyle = 'text-decoration:underline;font-weight:bold';
	/* --- Styles --- */

	/* ---- Private Variables ---- */
	var delimwords = new Array();
	var cdelimword = 0;
	var delimchar = new Array();
	var display = false;
	var pos = 0;
	var total = 0;
	var touche=0;
	var curr = null;
	var rangeu = 0;
	var ranged = 0;
	var bool = new Array();
	var pre = 0;
	var toid;
	var tomake = false;
	var getpre = "";
	var mouse_on_list = 1;
	var kwcount = 0;
	var caretmove = false;
	this.keywords = new Array();
	/* ---- Private Variables---- */
	
	this.keywords = ca;
	var self = this;

	curr = obj;
		
	addEvent(curr,"focus",setup);
	function setup(){
		addEvent(document,"keydown",checkkey);
		addEvent(curr,"blur",clear);
		addEvent(document,"keypress",keypress);
	}

	function clear(evt){
		if (!evt) evt = event;
		removeEvent(document,"keydown",checkkey);
		removeEvent(curr,"blur",clear);
		removeEvent(document,"keypress",keypress);
		removedisp();
	}
	function parse(n){
	//permet de matcher les correspondances entre la ville et la saisie
		if (self.delimiter.length > 0){
			var t = delimwords[cdelimword].trim().addslashes();
			var plen = delimwords[cdelimword].trim().length;
			//var t = delimwords[cdelimword].addslashes();
			//var plen = delimwords[cdelimword].length;
		}else{
			var t = curr.value.addslashes();
			var plen = curr.value.length;
		}
		var tobuild = '';
		var i;
		
		if (self.firstText){
			var re = new RegExp("^" + t, "i");
		}else{
			//création des expressions régulières pour les caractère accentués
			var relettree     = new RegExp('[éèêë]','gi');
			var relettrea     = new RegExp('[àäâ]','gi');
			var relettreu     = new RegExp('[ùûü]','gi');
			var relettrec     = new RegExp('[ç]','gi');
				var monexpress = /(\s)\s+/gi;
			var re = new RegExp(t, "i");
		}
		t=t.replace(monexpress,' ');
		re.compile(t,"i");
		
		var relettrest     = new RegExp('st','gi');

		var re2     = new RegExp('saint','gi');
	
		var ss_accent= n;
		
		//si pas de E accentué dans la saisie on remplace tous les E accentués par e dans ville
		if (relettree.test(t)==false)		
		{	
			if (relettree.test(ss_accent))
			{
				ss_accent= ss_accent.replace(relettree,"e");}
		}
		if (relettrea.test(t)==false)		
		{
			if (relettrea.test(ss_accent))
			{
				ss_accent= ss_accent.replace(relettrea,"a");
			}
		}
		if (relettreu.test(t)==false)		
		{
			if (relettreu.test(ss_accent))
			{
				ss_accent= ss_accent.replace(relettreu,"a");
			}
		}
		if (relettrec.test(t)==false)		
		{
			if (relettrec.test(ss_accent))
			{ss_accent= ss_accent.replace(relettrec,"a");
			}
		}
		var p;
		if (relettrest.test(t)){
			p = ss_accent.search(re);
			var p2= ss_accent.search(re2);
			
			if (p==-1){
			
				t=t.replace(relettrest,"saint");
				
				re.compile(t,"gi");
				p= ss_accent.search(re);
				
				plen=t.length;
				}
		}
		else
			p = ss_accent.search(re);
				
		for (i=0;i<p;i++){
			tobuild += n.substr(i,1);
		}
		tobuild += "<font style='"+(self.hStyle)+"'>"
		for (i=p;i<plen+p;i++){
			tobuild += n.substr(i,1);
		}
		tobuild += "</font>";
			for (i=plen+p;i<n.length;i++){
			tobuild += n.substr(i,1);
		}
		return tobuild;
	}
	function generate(){
	//	genere la liste
		var t = delimwords[cdelimword].trim().addslashes();
		//var t = delimwords[cdelimword].addslashes();
		var re ="";
		if (document.getElementById('tat_table'))
		{ 
			display = false;
			document.body.removeChild(document.getElementById('tat_table')); 
		} 
	
		for (i=0;i<self.keywords.length;i++)
		{
			re = new RegExp(self.keywords[i], "i");
			//pour empecher l'ecriture dans la textbox quand un element de la liste a été inséré
		 	if (total==0 && re.test(t)==true && t.length>self.keywords[i].length && self.keywords[i].length!=0 )
			{	obj.value=self.keywords[i];		
			}
		}
		if (kwcount == 0)
		{
			display = false;
			return;
		}
		

		a = document.createElement('table');
		a.cellSpacing='0px';
		a.cellPadding='0px';
		a.width='20%';
		//a.border='1';
		a.style.position='absolute';
		a.style.borderStyle='solid';
		a.style.borderWidth='1px';
		
		a.style.top = eval(curTop(curr) + curr.offsetHeight) + "px";
		a.style.left = curLeft(curr) + "px";
		a.style.backgroundColor=self.bgColor;
		a.id = 'tat_table';
	document.body.appendChild(a);

		var i;
		var first = true;
		var j = 1;
		if (self.mouse){
			a.onmouseout = table_unfocus;
			a.onmouseover = table_focus;
		}

		var counter = 0;
		//alert(touche);
		for (i=0;i<self.keywords.length;i++)
		{
			if (bool[i])
			{
				counter++;


				r = a.insertRow(-1);
				if (first && !tomake)
				{
					//r.style.bgColor = self.hColor;
					r.style.backgroundColor = self.hColor;
					first = false;
					pos = counter;
				}
				else if(pre == i)
				{
					r.style.backgroundColor = self.hColor;
					first = false;
					pos = counter;
				}
				else
				{
					r.style.backgroundColor = self.bgColor;
				}
			
				//s'il ne reste plus qu'une proposition et que backspace n'est pas pressé
				if(total==1 && touche!=8 && touche!="[object]" && touche!="[object HTMLTableElement]" && touche!=17 && touche!=16 && touche!=36 && touche!=35 && touche!=37 && touche!=39)
				{
					display=true;
					caretmove = 1;
					penter();
			
					break;				
				}
				//permet de faire fonctionner maj+origine, maj+fin, maj+droite, maj+gauche
				else if ( touche==16 || touche==17 || touche==36 || touche==35 || touche==37 || touche==39){
					break;
}

				r.id = 'tat_tr'+(j);
				c = r.insertCell(-1);
				c.style.color = self.textColor;
				c.style.fontFamily = self.fFamily;
				c.style.fontSize = self.fSize;
				
				c.innerHTML = parse(self.keywords[i]);
				c.id = 'tat_td'+(j);
				c.setAttribute('pos',j);
				if (self.mouse){
					c.style.cursor = 'pointer';
					c.onclick=mouseclick;
					c.onmouseover = table_highlight;
				}
				j++;
			}
			if (j - 1 == self.lim && j < total)
			{
				r = a.insertRow(-1);
				r.style.backgroundColor = self.bgColor;
				c = r.insertCell(-1);
				c.style.color = self.textColor;
				c.style.fontFamily = 'arial narrow';
				c.style.fontSize = '12px';
				c.style.fontWeight = 'bold';
				c.align='center';
				var img = document.createElement("img");
  				 var src = document.createAttribute("src");
  				 src.nodeValue = "pages/images/fleche-bas.gif";
   				img.setAttributeNode(src);
				 c.appendChild(img);
				//replaceHTML(c,'<b>/</b>');
				if (self.mouse)
				{
					c.style.cursor = 'pointer';
					c.onclick = mouse_down;
				}
				break;
			}
		}
		
		rangeu = 1;
		ranged = j-1;
		display = true;
		if (pos <= 0) pos = 1;	
			
	}
	
	function remake()
	{
	//reconstruit la liste en cas de up and down
		document.body.removeChild(document.getElementById('tat_table'));
		a = document.createElement('table');
		a.cellSpacing='0px';
		a.cellPadding='0px';
		a.width='20%';
		a.style.position='absolute';
		a.style.borderStyle='solid';
		a.style.borderWidth='1px';
		a.style.top = eval(curTop(curr) + curr.offsetHeight) + "px";
		a.style.left = curLeft(curr) + "px";
		a.style.backgroundColor=self.bgColor;
		a.id = 'tat_table';
		if (self.mouse){
			a.onmouseout= table_unfocus;
			a.onmouseover=table_focus;
		}
		document.body.appendChild(a);
		var i;
		var first = true;
		var j = 1;
		if (rangeu > 1){
			r = a.insertRow(-1);
			r.style.backgroundColor = self.bgColor;
			r.style.height='5px';
			c = r.insertCell(-1);
			c.style.color = self.textColor;
			c.style.fontFamily = 'arial narrow';
			c.style.fontSize = self.fSize;
			c.align='center';
			
				var img = document.createElement("img");
  				 var src = document.createAttribute("src");
  				 src.nodeValue = "pages/images/fleche-haut.gif";
   				img.setAttributeNode(src);
			 c.appendChild(img);
			//replaceHTML(c,'/\\');
			if (self.mouse){
				c.style.cursor = 'pointer';
				c.onclick = mouse_up;
			}
		}
		
		for (i=0;i<self.keywords.length;i++){
			if (bool[i]){
				if (j >= rangeu && j <= ranged){
					r = a.insertRow(-1);
					r.style.backgroundColor = self.bgColor;
					r.style.height='5px';
					r.id = 'tat_tr'+(j);
					c = r.insertCell(-1);
					c.style.color = self.textColor;
					c.style.fontFamily = self.fFamily;
					c.style.fontSize = self.fSize;
					c.innerHTML = parse(self.keywords[i]);
					c.id = 'tat_td'+(j);
					c.setAttribute('pos',j);
					if (self.mouse){
						c.style.cursor = 'pointer';
						c.onclick=mouseclick;
						c.onmouseover = table_highlight;
					}
					j++;
				}else{
					j++;
				}
			}
			if (j > ranged) break;
		}
		if (j-1 < total){
			r = a.insertRow(-1);
			r.style.backgroundColor = self.bgColor;
			r.style.height='5px';
			c = r.insertCell(-1);
			c.style.color = self.textColor;
			c.style.fontFamily = 'arial narrow';
			c.style.fontSize = self.fSize;
			c.align='center';
			
				var img = document.createElement("img");
  				 var src = document.createAttribute("src");
  				 src.nodeValue = "pages/images/fleche-bas.gif";
   				img.setAttributeNode(src);
			 c.appendChild(img);
		//	replaceHTML(c,'\\/');
			if (self.mouse){
				c.style.cursor = 'pointer';
				c.onclick = mouse_down;
			}
		}
	}
	function goup(){
		if (!display) return;
		if (pos == 1) return;
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.bgColor;
		pos--;
		if (pos < rangeu) moveup();
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.hColor;
		if (toid) clearTimeout(toid);
		if (self.timeOut > 0) toid = setTimeout(function(){mouse_on_list=0;removedisp();},self.timeOut);
	}
	function godown(){
		if (!display) return;
		if (pos == total) return;
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.bgColor;
		pos++;
		if (pos > ranged) movedown();
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.hColor;
		if (toid) clearTimeout(toid);
		if (self.timeOut > 0) toid = setTimeout(function(){mouse_on_list=0;removedisp();},self.timeOut);
	}
	function movedown(){
		rangeu++;
		ranged++;
		remake();
	}
	function moveup(){
		rangeu--;
		ranged--;
		remake();
	}

	/* Mouse */
	function mouse_down(){
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.bgColor;
		pos++;
		movedown();
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.hColor;
		curr.focus();
		mouse_on_list = 0;
		if (toid) clearTimeout(toid);
		if (self.timeOut > 0) toid = setTimeout(function(){mouse_on_list=0;removedisp();},self.timeOut);
	}
	function mouse_up(evt){
		if (!evt) evt = event;
		if (evt.stopPropagation){
			evt.stopPropagation();
		}else{
			evt.cancelBubble = true;
		}
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.bgColor;
		pos--;
		moveup();
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.hColor;
		curr.focus();
		mouse_on_list = 0;
		if (toid) clearTimeout(toid);
		if (self.timeOut > 0) toid = setTimeout(function(){mouse_on_list=0;removedisp();},self.timeOut);
	}
	function mouseclick(evt){
		if (!evt) evt = event;
		if (!display) return;
		mouse_on_list = 0;
		pos = this.getAttribute('pos');
		penter();
	}
	function table_focus(){
		mouse_on_list = 1;
	}
	function table_unfocus(){
		mouse_on_list = 0;
		if (toid) clearTimeout(toid);
		if (self.timeOut > 0) toid = setTimeout(function(){mouse_on_list = 0;removedisp();},self.timeOut);
	}
	function table_highlight(){
		mouse_on_list = 1;
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.bgColor;
		pos = this.getAttribute('pos');
		while (pos < rangeu) moveup();
		while (pos > ranged) movedown();
		document.getElementById('tat_tr'+pos).style.backgroundColor = self.hColor;
		if (toid) clearTimeout(toid);
		if (self.timeOut > 0) toid = setTimeout(function(){mouse_on_list = 0;removedisp();},self.timeOut);
	}
	/* ---- */

	function insertword(a){
		if (self.delimiter.length > 0){
			str = '';
			l=0;
			for (i=0;i<delimwords.length;i++){
				if (cdelimword == i){
					prespace = postspace = '';
					gotbreak = false;
					for (j=0;j<delimwords[i].length;++j){
						if (delimwords[i].charAt(j) != ' '){
							gotbreak = true;
							break;
						}
						prespace += ' ';
					}
					for (j=delimwords[i].length-1;j>=0;--j){
						if (delimwords[i].charAt(j) != ' ') break;
						postspace += ' ';
					}
					str += prespace;
					str += a;
					l = str.length;
					if (gotbreak) str += postspace;
				}else{
					str += delimwords[i];
				}
				if (i != delimwords.length - 1){
					str += delimchar[i];
				}
			}
			curr.value = str;
			setCaret(curr,l);
		}else{
			curr.value = a;
		}
		mouse_on_list = 0;
		removedisp();
	}
	function penter(){
	
		if (!display) return;
		display = false;
		var word = '';
		var c = 0;

		for (var i=0;i<=self.keywords.length;i++){
			if (bool[i]) c++;
			if (c == pos){
				word = self.keywords[i];
				break;
			}
		}
		insertword(word);
		l = getCaretStart(curr);
	}
	function removedisp(){
		if (mouse_on_list==0){
			display = 0;
			if (document.getElementById('tat_table')){ document.body.removeChild(document.getElementById('tat_table')); }
			if (toid) clearTimeout(toid);
		}
	}
	function keypress(e){
			if (caretmove) stopEvent(e);
		return !caretmove;
	}
	function checkkey(evt){
		if (!evt) evt = event;
		a = evt.keyCode;
		caret_pos_start = getCaretStart(curr);
		caretmove = 0;

		switch (a){
			case 38:
				goup();
				caretmove = 1;
				return false;
				break;
			case 38:
				goup();
				caretmove = 1;
				return false;
				break;
			case 9: 
  				mouse_on_list = 0;
  				removedisp();
  				return true;
  				break;
  			case 27: // ADDED to disable autocomplete list on TAB
  				mouse_on_list = 0;
  				removedisp();
  				return true;
  				break;
			case 40:
				godown();
				caretmove = 1;
				return false;
				break;
			case 13: //touche Entrée
				if (display){
					caretmove = 1;
					penter();
					return false;
				}else{
					return true;
				}
				break;
			default:
				setTimeout(function(){tocomplete(a)},50);
				break;
		}
	}

	function tocomplete(kc)
	{
	
		if (kc == 38 || kc == 40 || kc == 13) 
		 return;
		var i;

		touche=kc;
		if (display)
		{ 
			var word = 0;
			var c = 0;
			for (var i=0;i<=self.keywords.length;i++)
			{
			
				if (bool[i]) c++;
				if (c == pos)
				{			
					word = i;
					
					break;
				}
			}
			pre = word;
		}
		else
		{ 	pre = -1};
	
		// si valeur dans la textebox vide on enleve le div
			if (curr.value == '')
			{
				mouse_on_list = 0;
				removedisp();
				return;
			}

			if (self.delimiter.length > 0)
			{
				caret_pos_start = getCaretStart(curr);
				caret_pos_end = getCaretEnd(curr);
			
				delim_split = '';
				for (i=0;i<self.delimiter.length;i++)
				{
					delim_split += self.delimiter[i];
				}
				delim_split = delim_split.addslashes();
				delim_split_rx = new RegExp("(["+delim_split+"])");
				c = 0;
				delimwords = new Array();
				delimwords[0] = '';
				for (i=0,j=curr.value.length;i<curr.value.length;i++,j--)
				{
					if (curr.value.substr(i,j).search(delim_split_rx) == 0)
					{
						ma = curr.value.substr(i,j).match(delim_split_rx);
					
						delimchar[c] = ma[1];
						c++;
						delimwords[c] = '';
					}
					else
					{
						delimwords[c] += curr.value.charAt(i);
				
					}
				}

				var l = 0;
				cdelimword = -1;
				for (i=0;i<delimwords.length;i++)
				{
					if (caret_pos_end >= l && caret_pos_end <= l + delimwords[i].length)
					{
						cdelimword = i;
					}
					l+=delimwords[i].length + 1;
				}
				var ot = delimwords[cdelimword].trim(); 
				var t = delimwords[cdelimword].addslashes().trim();
			
			}
			else
			{
				var ot = curr.value;
				var t = curr.value.addslashes();
			}
		
			if (ot.length == 0)
			{
				mouse_on_list = 0;
				removedisp();
			}
			if (ot.length < self.startcheck) 
				return this;
		
			if (self.firstText)
			{
				var relettree     = new RegExp('^[éèêë]','gi');
				var relettrea     = new RegExp('^[àäâ]','gi');
				var relettreu     = new RegExp('^[ùûü]','gi');
				var relettrec     = new RegExp('^[ç]','gi');
				var re = new RegExp("^" + t, "i");
			
			}
			else
			{
				var relettree     = new RegExp('[éèêë]','gi');
				var relettrea     = new RegExp('[àäâ]','gi');
				var relettreu     = new RegExp('[ùûü]','gi');
				var relettrec     = new RegExp('[ç]','gi');
				var relettrest    = new RegExp('st','gi');
				var relettreste   = new RegExp('ste','gi');
				var monexpress = /(\s)\s+/gi;
	
				var re = new RegExp(t, "i");
			}
			var expressst    = new RegExp('saint','gi');
			var expressste    = new RegExp('sainte','gi');
			var express_tiret    = new RegExp('[-]','gi');
		
	
			t=t.replace(monexpress,' ');
			re.compile(t,"i");
		
		

			total = 0;
			tomake = false;
			kwcount = 0;
			var e_ok=relettree.test(t);
			var a_ok=relettrea.test(t);
			var u_ok=relettreu.test(t);
			var c_ok=relettrec.test(t);
			var st_ok=relettrest.test(t);
			var ste_ok=relettreste.test(t);
			var st_tiret=express_tiret.test(t);
		
	
		
			for (i=0;i<self.keywords.length;i++)
			{
				bool[i] = false;
				
				
				var ville=self.keywords[i];
				var saint_ville=expressst.test(ville);
				var sainte_ville=expressste.test(ville);
				
				if (st_tiret==true && saint_ville==true && st_ok==true)
				{	t=t.replace(relettrest,"saint");
					re.compile(t,"i");
				}
				if (st_tiret==true && sainte_ville==true && ste_ok==true)
				{	t=t.replace(relettreste,"sainte");
					re.compile(t,"i");
				}
		
				
				if (e_ok==false)
				{ 
					ville = ville.replace(relettree,"e");
				}
				if (a_ok==false)
				{ 
					ville = ville.replace(relettrea,"a");
				}
				if (u_ok==false)
				{ 
					ville = ville.replace(relettreu,"u");
				}
				if (c_ok==false)
				{ 
					ville = ville.replace(relettrec,"c");
				}
			
			
				
	
			if (st_ok==true || ste_ok==true)
			{
		
				if ( re.test(ville)|| saint_ville==true && (t=="St" || t=="st") )
				{
					if (ste_ok==false)
					{
						total++;
						bool[i] = true;
						kwcount++;
					
						if (pre == i) 
							tomake = true;
					}
				}
				if (ste_ok==true)
				{
					if ( re.test(ville)|| sainte_ville==true && (t=="ste" || t=="Ste"))
				 	{
	
						total++;
						bool[i] = true;
						kwcount++;
				
						if (pre == i) 
							tomake = true;
					}
				}		
		
			}
			else 
			{
				if (re.test(ville))
				{
		
					total++;
					bool[i] = true;
					kwcount++;
					
					if (pre == i) 
						tomake = true;
				}				
			}
		}

		if (toid) 
			clearTimeout(toid);
		if (self.timeOut > 0)
			 toid = setTimeout(	function()
			 					{	mouse_on_list = 0;
			 						removedisp();
			 					},self.timeOut
			 				);
		generate();		
	}

	return this;
}

//Adaptation du Script réalisé par zichun
//http://www.codeproject.com/jscript/jsactb.asp
//Sous licence Creative Common License http://creativecommons.org/licenses/by/2.0/" 
