function autocompletionLocalisation(id_champs)
{
	//console.log(id_champs);
	//console.log("Accès autocompletionLocalisation");
	this.idChamps = id_champs.toUpperCase();
	this.oldInputFieldValue = '';//valeur précédente du champ texte
	this.currentInputFieldValue = '';//valeur actuelle du champ texte
	this.resultCache = new Object();//mécanisme de cache des requetes
	this.xmlHttp = null;//L'objet xmlHttpRequest utilisé pour contacter le serveur
	this.eventKeycode = null;
	this.completeDivRows = 0;
	this.completeDivDivList = null;
	this.highlightedSuggestionIndex = -1;
	this.highlightedSuggestionLi = null;
	this.cursorUpDownPressed = null;
	this.inputField = document.getElementById(id_champs);
	//console.log("id_champs : ", id_champs);
	//console.log("input Fied : ", document.getElementById(id_champs));
	if(this.inputField == null)
	{
		console.error("Element possédant l'id \"" + id_champs + "\" introuvable !");
		return;
	}
	//console.log("Champs à compléter", this.inputField);
	this.inputField.setAttribute('autocomplete','off');
	//console.log("Désactivation de " + id_champs);
	this.formulaire = this.inputField.parentNode;
	if(window.location.hostname.search(/pro-a-part/) != -1 || window.location.hostname.search(/proapart-demo/) != -1 || window.location.hostname.search(/194\.146\.225\.17/) != -1 || window.location.hostname.search(/proapart/) != -1)
	{
		this.adresseRecherche = "http://" + window.location.hostname + "/";
	}
	if(window.location.hostname.search(/localhost/) != -1)
	{
		this.adresseRecherche = "http://" + window.location.hostname + "/refonte_refonte/www/";
	}
	this.adresseRecherche += "recherche/recherche_location.php";
  this.adresseRecherche = "/recherche/recherche_location.php"
	while(this.formulaire.nodeName != 'FORM')
	{
		this.formulaire = this.formulaire.parentNode;
	}
	//alert(this.formulaire.onsubmit);
	if(!window.scann_onsubmit)
	{//On a pas encore scanné ni ajouté le contrôle
		window.scann_onsubmit = true;//On ajoute ce contrôle qu'une seule fois par page
		var function_submit = String(this.formulaire.onsubmit);
		if(function_submit != '')
		{//Le form a déjà un contrôle sur le onsubmit
			var debut_controle = function_submit.indexOf('{') + 1;
			var fin_controle = function_submit.lastIndexOf('}');
			var ancien_onsubmit = function_submit.substr(debut_controle + 1,fin_controle - debut_controle - 2);
		}
		this.formulaire.onsubmit = function()
		{//Firefox ne gère pas le event.returnValue = false sur le keypress, on est obligé d'interdire l'envoi du formulaire en vérfiant la variable
			var maintenant = new Date();
			if(
				window.selectionvisible == true
				&& window.selectionvisible != null
				&& (maintenant.getTime() - window.dateValidationSelection.getTime()) < 15
			)
			{//Si la liste de sélection est affichée, la touche entrée n'envoie pas le formulaire.
				//alert(maintenant.getTime() - window.dateValidationSelection.getTime());
				return false;
			}
			eval(ancien_onsubmit);
		}
	}
	this.creeAutocompletionDiv();
	this.currentInputFieldValue = this.inputField.value;
	this.oldInputFieldValue = this.currentInputFieldValue;
	this.cacheResults('',new Array());
	this.inputField.onkeypress = function(event)
	{
		if(!event && window.event)
		{//accès evenement compatible IE/Firefox
			event = window.event;
		}
		var classe_courante = 'localisation' + this.id.toUpperCase();
		var eventKeycode = event.keyCode;
		if(eventKeycode == 13 || eventKeycode == 3)
		{
			eval('var visible = ' + classe_courante + '.completeDiv.style.visibility;');
			if(visible == 'visible')
			{
				//this.inputField.value = this.getSuggestion(this.highlightedSuggestionLi);
				eval(classe_courante + '.inputField.value = ' + classe_courante + '.getSuggestion(' + classe_courante + '.highlightedSuggestionLi);');
				for(var i = 0; i < document.getElementsByTagName('input').length; i++)
				{//On passe au chmaps suivant
					eval('if(' + classe_courante + '.inputField == document.getElementsByTagName(\'input\')[i]){document.getElementsByTagName(\'input\')[i + 1].focus();}');
				}
				window.selectionvisible = true;
				window.dateValidationSelection = new Date();
				event.returnValue = false;//Ne marche pas avec Firefox...
			}
			else
			{
				window.selectionvisible = false;
			}
		}
		else
		{
			window.selectionvisible = false;
		}
	}
	this.inputField.onkeyup = function(event)
	{
		if(!event && window.event)
		{//accès evenement compatible IE/Firefox
			event = window.event;
		}
		var classe_courante = 'localisation' + this.id.toUpperCase();
		var eventKeycode = event.keyCode;
		//alert(eventKeycode);
		eval(classe_courante + '.eventKeycode = eventKeycode;');
		eval('var N = ' + classe_courante + '.rangeSize(this);');//taille de la selection
		eval('var v = ' + classe_courante + '.beforeRangeSize(this);');//taille du texte avant la selection (selection = suggestion d'autocomplétion)
		var V = this.value;//contenu du champ texte
		if(eventKeycode != 0 && eventKeycode != 9 && eventKeycode != 16)
		{//Sauf si on arrive dans la champs par tab (9 et 16)
			if(N > 0 && v != -1)
			{//on recupere uniquement le champ texte tapé par l'utilisateur
				V = V.substring(0,v);
			}
			if(eventKeycode == 13 || eventKeycode == 3)
			{//13 = touche entrée
				//eval('alert(' + classe_courante + '.highlightedSuggestionIndex);');
				var d = this;
				//on mets en place l'ensemble du champ texte en repoussant la selection
				if(this.createTextRange)
				{
					var t = this.createTextRange();
					t.moveStart('character',this.value.length);
					this.select();
				}
				else if(d.setSelectionRange)
				{
					this.setSelectionRange(this.value.length,this.value.length);
				}
			}
			else
			{
				if(this.value != V)
				{//si on a pas pu agrandir le champ non selectionné, on le mets en place violemment.
					this.value = V;
				}
			}
		}
		//si la touche n'est ni haut, ni bas, on stocke la valeur utilisateur du champ
		if(eventKeycode != 40 && eventKeycode != 38)
		{//le champ courant n'est pas change si key Up ou key Down
			currentInputFieldValue = V;
			eval(classe_courante + '.currentInputFieldValue = V;');
		}
		eval('var return_UpDownEnter = ' + classe_courante + '.handleCursorUpDownEnter(eventKeycode);');
		if(return_UpDownEnter && eventKeycode != 0)
		{//si on a préssé une touche autre que haut/bas/enter
			eval(classe_courante + '.PressAction();');
		}
	}
	this.inputField.onblur = function(event)
	{//Handler de blur sur le champ texte
		var classe_courante = 'localisation' + this.id.toUpperCase();
		eval('var return_up_down_pressed = ' + classe_courante + '.cursorUpDownPressed;');
		if(!return_up_down_pressed)
		{//si le blur n'est pas causé par la touche haut/bas
			eval(classe_courante + '.completeDiv.style.visibility = \'hidden\';');
		}
		eval(classe_courante + '.cursorUpDownPressed = false;');
	}
	setTimeout('localisation' + this.idChamps.toUpperCase() + '.mainLoop()',200);
}
autocompletionLocalisation.prototype.creeAutocompletionDiv = function()
{
	this.completeDiv = document.createElement('DIV');
	this.setCompleteDivSize();
	this.completeDiv.style.visibility = 'hidden';
	this.completeDiv.style.position = 'absolute';
	document.body.appendChild(this.completeDiv);
	this.setStylePourElement(this.completeDiv,'AutoCompleteDiv');
}
autocompletionLocalisation.prototype.setCompleteDivSize = function()
{
	if(this.completeDiv)
	{
		this.completeDiv.style.left = this.calculateOffsetLeft(this.inputField) + 'px';
		this.completeDiv.style.top = this.calculateOffsetTop(this.inputField) + this.inputField.offsetHeight + 'px';
		this.completeDiv.style.width = this.calculateWidth() + 'px'
	}
}
autocompletionLocalisation.prototype.calculateOffsetLeft = function(element)
{//calcule le décalage à gauche
	return this.calculateOffset(element,'offsetLeft') + 2;
}
autocompletionLocalisation.prototype.calculateOffsetTop = function(element)
{//calcule le décalage vertical
	return this.calculateOffset(element,'offsetTop');
}
autocompletionLocalisation.prototype.calculateWidth = function()
{//calcule la largeur du champ
	return this.inputField.offsetWidth - 2 * 1;
}
autocompletionLocalisation.prototype.calculateOffset = function(element,attr)
{
	var kb = 0;
	while(element)
	{
		kb += element[attr];
		element = element.offsetParent;
	}
	return kb;
}
autocompletionLocalisation.prototype.setStylePourElement = function(element,name)
{
	element.setAttribute('class',name);
	element.setAttribute('className',name);
}
autocompletionLocalisation.prototype.cacheResults = function(debut,suggestions)
{//Mecanisme de caching des réponses
	this.resultCache[debut] = suggestions;
}
autocompletionLocalisation.prototype.rangeSize = function(n)
{//Taille de la selection dans le champ input
	var N = -1;
	if(n.createTextRange)
	{
		var fa = document.selection.createRange().duplicate();
		N = fa.text.length;
	}
	else if(n.setSelectionRange)
	{
		N = n.selectionEnd - n.selectionStart;
	}
	return N;
}
autocompletionLocalisation.prototype.beforeRangeSize = function(n)
{//Taille du champ input non selectionne
	var v = 0;
	if(n.createTextRange)
	{
		var fa = document.selection.createRange().duplicate();
		fa.moveEnd('textedit',1);
		v = n.value.length-fa.text.length;
	}
	else if(n.setSelectionRange)
	{
		v = n.selectionStart;
	}
	else
	{
		v = -1;
	}
	return v;
}
autocompletionLocalisation.prototype.handleCursorUpDownEnter = function(eventCode)
{//Change la suggestion selectionné. Cette méthode traite les touches haut, bas et enter
	if(eventCode == 40)
	{
		this.highlightNewValue(this.highlightedSuggestionIndex + 1);
		return false;
	}
	else if(eventCode == 38)
	{
		this.highlightNewValue(this.highlightedSuggestionIndex - 1);
		return false
	}
	else if(eventCode == 13 || eventCode == 3)
	{
		return false;
	}
	return true;
}
autocompletionLocalisation.prototype.highlightNewValue = function(C)
{//Change la suggestion en surbrillance
	if(!this.completeDivDivList || this.completeDivRows <= 0)
	{
		return;
	}
	this.showCompleteDiv();
	if(C >= this.completeDivRows)
	{
		C = this.completeDivRows - 1;
	}
	if(this.highlightedSuggestionIndex != -1 && C != this.highlightedSuggestionIndex)
	{
		this.setStylePourElement(this.highlightedSuggestionLi,'AutoCompleteDiv');
		this.highlightedSuggestionIndex = -1
	}
	if(C < 0)
	{
		this.highlightedSuggestionIndex = -1;
		this.inputField.focus();
		return;
	}
	this.highlightedSuggestionIndex = C;
	this.highlightedSuggestionLi = this.completeDivDivList.item(C);
	this.setStylePourElement(this.highlightedSuggestionLi,'AutoCompleteLiAct');
	this.inputField.value = this.getSuggestion(this.highlightedSuggestionLi);
	if(this.inputField.createTextRange)
	{//on sélectionne la fin de la suggestion
		var t = this.inputField.createTextRange();
		t.moveStart('character',this.currentInputFieldValue.length);
		t.select();
	}
	else if(this.inputField.setSelectionRange)
	{
		this.inputField.setSelectionRange(this.currentInputFieldValue.length,this.inputField.value.length);
	}
}
autocompletionLocalisation.prototype.showCompleteDiv = function()
{//Rends les choix de completion visibles
	this.completeDiv.style.visibility = 'visible';
	this.setCompleteDivSize()
}
autocompletionLocalisation.prototype.getSuggestion = function(uneDiv)
{//Retourne la valeur de la possibilite (texte) contenu dans une li de possibilite
	if(!uneDiv)
	{
		return null;
	}
	return this.trimCR(uneDiv.firstChild.data);
}
autocompletionLocalisation.prototype.PressAction = function()
{//gère une touche pressée autre que haut/bas/enter
	this.highlightedSuggestionIndex = -1;
	var suggestionList = this.completeDiv.getElementsByTagName('li');
	var suggestionLongueur = suggestionList.length;
	//on stocke les valeurs précédentes
	this.completeDivRows = suggestionLongueur;//nombre de possibilités de complétion
	this.completeDivDivList = suggestionList;//possiblités de complétion
	if(this.currentInputFieldValue == '' || suggestionLongueur == 0)
	{//si le champ est vide, on cache les propositions de complétion
		this.completeDiv.style.visibility = 'hidden'
	}
	else
	{
		this.showCompleteDiv();
	}
	var trouve = false;
	if(this.currentInputFieldValue.length > 0)
	{//si on a du texte sur lequel travailler
		var indice;
		//T vaut true si on a dans la liste de suggestions un mot commencant comme l'entrée utilisateur
		for(indice = 0; indice < suggestionLongueur; indice++)
		{
			if(this.getSuggestion(suggestionList.item(indice)).toUpperCase().indexOf(this.currentInputFieldValue.toUpperCase()) == 0)
			{
				trouve = true;
				break
			}
		}
	}
	for(var i = 0; i < suggestionLongueur; i++)
	{//on désélectionne toutes les suggestions
		this.setStylePourElement(suggestionList.item(i),'AutoCompleteDiv');
	}
	if(trouve)
	{//si l'entrée utilisateur (n) est le début d'une suggestion (n-1) on sélectionne cette suggestion avant de continuer
		this.highlightedSuggestionIndex = indice;
		this.highlightedSuggestionLi = suggestionList.item(this.highlightedSuggestionIndex);
	}
	else
	{
		this.highlightedSuggestionIndex = -1;
		this.highlightedSuggestionLi = null
	}
	var supprSelection = false;
	switch(this.eventKeycode)
	{//cursor left, cursor right, page up, page down, others??
		case 8:
		case 33:
		case 34:
		case 35:
		case 35:
		case 36:
		case 37:
		case 39:
		case 45:
		case 46:
			supprSelection = true;//on supprime la suggestion du texte utilisateur
			break;
		default:
			break
	}
	if(!supprSelection && this.highlightedSuggestionLi)
	{//si on a une suggestion (n-1) sélectionnée
		this.setStylePourElement(this.highlightedSuggestionLi,'AutoCompleteLiAct');
		var z;
		if(trouve)
		{
			z = this.getSuggestion(this.highlightedSuggestionLi).substr(0);
		}
		else
		{
			z = this.currentInputFieldValue;
		}
		if(z != this.inputField.value)
		{
			if(this.inputField.value != this.currentInputFieldValue)
			{
				return;
			}
			if(this.inputField.createTextRange || this.inputField.setSelectionRange)
			{//si on peut créer des range dans le document
				this.inputField.value = z;
			}
			if(this.inputField.createTextRange)
			{//on sélectionne la fin de la suggestion
				var t = this.inputField.createTextRange();
				t.moveStart('character',this.currentInputFieldValue.length);
				t.select();
			}
			else if(this.inputField.setSelectionRange)
			{
				this.inputField.setSelectionRange(this.currentInputFieldValue.length,this.inputField.value.length);
			}
		}
	}
	else
	{//Sinon, plus aucune suggestion de sélectionnée
		this.highlightedSuggestionIndex = -1;
	}
}
autocompletionLocalisation.prototype.mainLoop = function()
{//Tourne en permanence pour suggerer suite à un changement du champ texte
	if(this.oldInputFieldValue != this.currentInputFieldValue)
	{
		//alert(this.oldInputFieldValue + ' et ' + this.currentInputFieldValue);
		var valeur = this.escapeURI(this.currentInputFieldValue);
		var suggestions = this.resultCache[this.currentInputFieldValue];
		if(suggestions)
		{//la réponse était encore dans le cache
			this.metsEnPlace(valeur,suggestions);
		}
		else
		{
			this.callSuggestions(valeur);//appel distant
		}
		this.inputField.focus();
	}
	this.oldInputFieldValue = this.currentInputFieldValue;
	setTimeout('localisation' + this.idChamps.toUpperCase() + '.mainLoop()',200);
	return true
}
autocompletionLocalisation.prototype.escapeURI = function(La)
{//echappe les caractère spéciaux
	if(encodeURIComponent)
	{
		return encodeURIComponent(La);
	}
	if(escape)
	{
		return escape(La);
	}
}
autocompletionLocalisation.prototype.metsEnPlace = function(valeur,liste)
{
	if(this.completeDiv.childNodes.length > 0)
	{
		supprimeElement(this.completeDiv.childNodes[0]);
	}
	var nouveauUl = document.createElement('UL');
	for(var f = 0; f < liste.length; f++)
	{//mise en place des suggestions
		var text_localisation = document.createTextNode(liste[f]);//Le texte de la suggestion
		var nouveauLi = document.createElement('LI');
		nouveauLi.id = this.idChamps + '-' + f;
		nouveauLi.onmousedown = function()
		{//declenchee quand on clique sur une div contenant une possibilite
			var classe_courante = 'localisation' + this.id.substr(0,3);
			eval(classe_courante + '.inputField.value = ' + classe_courante + '.getSuggestion(this);');
		};
		nouveauLi.onmouseover = function()
		{//declenchee quand on passe sur une div de possibilite. La div précédente est passee en style normal
			var classe_courante = 'localisation' + this.id.substr(0,3);
			eval('var highlightedSuggestionLi = ' + classe_courante + '.highlightedSuggestionLi;');
			if(highlightedSuggestionLi)
			{
				eval(classe_courante + '.setStylePourElement(' + classe_courante + '.highlightedSuggestionLi,\'AutoCompleteDiv\');');
			}
			eval(classe_courante + '.setStylePourElement(this,\'AutoCompleteLiAct\');');
		};
		nouveauLi.onmouseout = function()
		{//declenchee quand la sourie quitte une div de possiblite. La div repasse a l'etat normal
			var classe_courante = 'localisation' + this.id.substr(0,3);
			eval(classe_courante + '.setStylePourElement(this,\'AutoCompleteDiv\');');
		}
		this.setStylePourElement(nouveauLi,'AutoCompleteLi');
		nouveauLi.appendChild(text_localisation);
		nouveauUl.appendChild(nouveauLi);
	}
	this.completeDiv.appendChild(nouveauUl);
	this.PressAction();
	if(this.completeDivRows > 0)
	{
		this.completeDiv.height = 16 * this.completeDivRows + 4;
	}
	else
	{
		this.completeDiv.style.visibility = 'hidden'
	}
}
autocompletionLocalisation.prototype.callSuggestions = function(valeur)
{
	if(this.xmlHttp && this.xmlHttp.readyState != 0)
	{
		this.xmlHttp.abort();
	}
	this.xmlHttp = this.getXMLHTTP();
	if(this.xmlHttp)
	{//appel à l'url distante
		this.xmlHttp.open('GET',this.adresseRecherche + '?debut=' + valeur,true);
		var classe_courante = 'localisation' + this.idChamps.toUpperCase();
		eval('this.xmlHttp.onreadystatechange = function(){if(' + classe_courante + '.xmlHttp.readyState == 4 && ' + classe_courante + '.xmlHttp.responseXML){var liste = ' + classe_courante + '.traiteXmlSuggestions(' + classe_courante + '.xmlHttp.responseXML);' + classe_courante + '.cacheResults(valeur,liste);' + classe_courante + '.metsEnPlace(valeur,liste);}};');
		this.xmlHttp.send(null);//envoi de la requete
	}
}
autocompletionLocalisation.prototype.getXMLHTTP = function(id)
{//retourne un objet xmlHttpRequest. méthode compatible entre tous les navigateurs (IE/Firefox/Opera)
	var xhr = null;
	if(window.XMLHttpRequest)
	{//Firefox et autres
		xhr = new XMLHttpRequest();
	}
	else if(window.ActiveXObject)
	{//Internet Explorer
		try{
			xhr = new ActiveXObject('Msxml2.XMLHTTP');
		}
		catch(e)
		{
			try
			{
				xhr = new ActiveXObject('Microsoft.XMLHTTP');
			}
			catch(e1)
			{
				xhr = null;
			}
		}
	}
	return xhr;
}
autocompletionLocalisation.prototype.traiteXmlSuggestions = function(xmlDoc)
{//Transformation XML en tableau
	var options = xmlDoc.getElementsByTagName('option');
	var optionsListe = new Array();
	for(var i = 0; i < options.length; ++i)
	{
		optionsListe.push(options[i].firstChild.data);
	}
	return optionsListe;
}
autocompletionLocalisation.prototype.trimCR = function(chaine)
{//supprime les caractères retour chariot et line feed d'une chaine de caractères
	for(var f = 0, nChaine = '', zb = "\n\r"; f < chaine.length; f++)
	{
		if(zb.indexOf(chaine.charAt(f)) == -1)
		{
			nChaine += chaine.charAt(f);
		}
	}
	return nChaine
}
