/*******************************************************************************
 * 
 * CSS de base de la liste affichable.
 * 
 ******************************************************************************/

insertCSS(
		'.AutoCompleteDivListeStyle',
		'border: #bfbfbf 1px solid; z-index: 5515; padding: 0; visibility: hidden; position: absolute; background-color: white; font-size: 13px; font-family: arial,sans-serif; word-wrap:break-word; height:100px; overflow:scroll;text-align:left;');
insertCSS(
		'.AutoCompleteDiv',
		'display: block; padding-left: 3; padding-right: 3; overflow: hidden; background-color: white; height: auto; margin: 2px 0;');
insertCSS(
		'.AutoCompleteDivAct',
		'background-color: #7D7D7D; color: #2A4D6C ! important; cursor: pointer; height: auto; margin: 2px 0;');

/*******************************************************************************
 * 
 * Fonctions Générales
 * 
 ******************************************************************************/

// echappe les caractère spéciaux de la chaine de craractéres passée en
// paramétre.
function escapeURI(uri) {
	if (encodeURIComponent) {
		return encodeURIComponent(uri);
	}
	if (escape) {
		return escape(uri)
	}
}

// insère une règle CSS avec son nom dans la premiére feuille de style CSS du
// document.
function insertCSS(cssName, cssRule) {
	if (document.styleSheets) {
		var ss = document.styleSheets[0];
		if (ss.addRule) { // méthode IE
			ss.addRule(cssName, cssRule)
		} else if (ss.insertRule) { // méthode DOM
			ss.insertRule(cssName + " { " + cssRule + " }", ss.cssRules.length)
		}
	}
}

// mettre un syle à un élement DOM
function setStyleForElement(element, className) {
	element.className = className;
}

/*******************************************************************************
 * 
 * Déclaration de variables
 * 
 ******************************************************************************/
var _DEFAULT_COMPLETE_DIV_WIDTH = 200;
// l'objet input field qui est rempli par l'utilisateur
var _inputFieldLabel = null;
// l'objet input field qui va contenir l'identifiant de la structure choisie par
// l'utilisateur
var _inputFieldId = null;
// varaible qui sert à préciser si on veut que la valeur du champ soit auto
// complétée ou non.
var _autocompletValue = false;
// l'objet xmlHttpRequest utilisé pour contacter le serveur
var _xmlHttp = null;
// value actuelle du champ texte
var _currentInputFieldLabelValue = "";
// value précédente du champ texte
var _oldInputFieldLabelValue = "";
//
var _oldInputFieldIdValue = null;
// fonction lancée quand l'identifiant change par rapport à la précédente
// valeur.
var _idChangeFunction = null;
// l'adresse à interroger pour trouver les suggestions
var _servletURL = null;
// le code du dernier appuie sur une touche
var _lastKeyCode = null;
// l'événement d'appuie sur uen touche
var _eventKeycode = null;
// liste des objet mis dans la div "completeDiv"
var _suggestionList = null;
// la taille de la liste de suggestion
var _suggestionListLength = 0;

var _completeDivDivList = null;

var _highlightedSuggestionIndex = -1;

var _highlightedSuggestionDiv = null;

var _cursorUpDownPressed = null;
// Handler de resize de la fenetre
var _onResizeHandler = function(event) {
	// recalcule la taille des suggestions
	setCompleteDivSize();
}
// Handler de blur sur le champ texte
var onBlurHandler = function(event) {
	if (!_cursorUpDownPressed && !completeDivFocused) {
		// si le blur n'est pas causé par la touche haut/bas
		hideCompleteDiv();
		// Si la dernière touche préssé est tab, on passe au bouton de
		// validation
		if (_lastKeyCode == 9) {
			_lastKeyCode = -1
		}
	}
	_cursorUpDownPressed = false
};
// declenchee quand on clique sur une div contenant une possibilite
var divOnMouseDown = function() {
	_inputFieldLabel.value = getSuggestionLabel(this);
	putIdWhenEvent();
	hideCompleteDiv();
	
};
// declenchee quand on passe sur une div de possibilite. La div précédente est
// passee en style normal
var divOnMouseOver = function() {
	if (_highlightedSuggestionDiv) {
		setStyleForElement(_highlightedSuggestionDiv, "AutoCompleteDiv");
	}
	setStyleForElement(this, "AutoCompleteDivAct")
};
// declenchee quand la sourie quitte une div de possiblite. La div repasse a
// l'etat normal
var divOnMouseOut = function() {
	setStyleForElement(this, "AutoCompleteDiv");
};
// Handler pour le keydown du document
var onKeyDownHandler = function(event) {
	// accès evenement compatible IE/Firefox
	if (!event && window.event) {
		event = window.event;
	}
	// on enregistre la touche ayant déclenché l'evenement
	if (event) {
		_lastKeyCode = event.keyCode;
	}
};
// Handler pour le keyup du champ texte
var onKeyUpHandler = function(event) {
	// accès evenement compatible IE/Firefox
	if (!event && window.event) {
		event = window.event;
	}
	_eventKeycode = event.keyCode;
	// Dans les cas touches touche haute(38) ou touche basse (40)
	if (_eventKeycode == 40 || _eventKeycode == 38) {
		// on autorise le blur du champ (traitement dans onblur)
		blurThenGetFocus();
	}
	// taille de la selection
	var selectionSize = rangeSize(_inputFieldLabel);
	// taille du texte avant la selection (selection = suggestion
	// d'autocomplétion)
	var beforeSelectionSize = beforeRangeSize(_inputFieldLabel);
	// contenu du champ texte
	var currentLabelValue = _inputFieldLabel.value;
	if (_eventKeycode != 0) {
		//if (selectionSize > 0 && beforeSelectionSize != -1) {
			// on recupere uniquement le champ texte tapé par l'utilisateur
		//	currentLabelValue = currentLabelValue.substring(0, beforeSelectionSize);
		//}
		// 13 = touche entrée
		if (_eventKeycode == 13 || _eventKeycode == 3) {
			// on mets en place l'ensemble du champ texte en repoussant la
			// selection
			if (_inputFieldLabel.createTextRange) {
				var fieldLabelTextRange = _inputFieldLabel.createTextRange();
				fieldLabelTextRange.moveStart("character",
						_inputFieldLabel.value.length);
				_inputFieldLabel.select()
			} else if (_inputFieldLabel.setSelectionRange) {
				_inputFieldLabel.setSelectionRange(
						_inputFieldLabel.value.length,
						_inputFieldLabel.value.length)
			}
		} else {
			// si on a pas pu agrandir le champ non selectionné, on le mets en
			// place violemment.
			if (_inputFieldLabel.value != currentLabelValue) {
				_inputFieldLabel.value = currentLabelValue
			}
		}
	}
	// si la touche n'est ni haut, ni bas, on stocke la value utilisateur du
	// champ
	if (_eventKeycode != 40 && _eventKeycode != 38) {
		// le champ courant n est pas change si key Up ou key Down
		_currentInputFieldLabelValue = currentLabelValue;
	}
	if (handleCursorUpDownEnter(_eventKeycode) && _eventKeycode != 0) {
		// si on a préssé une touche autre que haut/bas/enter
		pressAction();
	}
};
// afficher la divComplete quand elle n'est pas vide et qu'on a le focus
var _onFocusHandler = function() {
	if (!completeDivFocused && _inputFieldLabel && _inputFieldLabel.value != "") {
		// s'il n'y a pas eu de changement dans les entrées utilisateur et que
		// la liste des suggestion n'est pas vide on réaffiche sans faire une
		// requete serveur
		if (_currentInputFieldLabelValue == _inputFieldLabel.value
				&& _suggestionListLength > 0) {
			_oldInputFieldLabelValue = _currentInputFieldLabelValue;
			_currentInputFieldLabelValue = _inputFieldLabel.value;
			showCompleteDiv();
		} else if (_inputFieldLabel.value.length > 0) {
			callSuggestions();
		}
	}
}
// inhibe l'appui sur la touche entrée validant le formulaire.
var _oldOnKeyPressHandler = null;
var _onKeyEnterHandler = function(event) {
	if (event.keyCode == 13 || event.keyCode == 3) {
		return false
	}
};

// Objet qui contient les retour du serveur aprés l'envoie d'une requete
function RequestValue(id, label) {
	this.id = id;
	this.label = label;
}

/*******************************************************************************
 * 
 * fonctions d'initialisation
 * 
 ******************************************************************************/

// initialisation des valeurs et de l'affichage
// fieldId -> identifiant du champ dans lequel l'utilisateur va taper au clavier
// fieldContainerId -> identifiant du champ dans lequel l'identifiant de la
// structure choisie va être déposé.
// autocompletValue -> indique si on veut que le texte soit auto completer dans
// le champ ou non.
function initAutoComplete(fieldId, fieldContainerId, autocompletValue) {
	_inputFieldLabel = document.getElementById(fieldId);
	_inputFieldId = document.getElementById(fieldContainerId);
	_autocompletValue = autocompletValue;
	// on créé la div qui va servir à afficher les réponses
	createAutocompletionDiv();
	document.onkeydown = onKeyDownHandler;
	_inputFieldLabel.onkeyup = onKeyUpHandler;
	addEvent( _inputFieldLabel, 'focus', _onFocusHandler);
	addEvent( _inputFieldLabel, 'blur', onBlurHandler);
	_oldOnKeyPressHandler = _inputFieldLabel.onkeypress;
	// faire en sorte que le navigateur ne propose pas de valeur pour ce champ
	// (liste de valeur)
	if (!autocompletValue) {
		_inputFieldLabel.setAttribute("autocomplete", "off");
	}
	window.onresize = _onResizeHandler;
	setTimeout("mainLoop()", 400);
}

// ajoute la servlet URL tout en ajoutant le parametre à compléter en fin de
// d'URL.
// servletURL -> URL de la servlet à intéroger pour résupérer les values
// servant à complétrer la saisie de l'utilisateur
function initServletURL(servletURL) {
	// modification de la servlet URL pour ajouter le '?' s'il n'existe pas
	// suivi du paramétre permettant la discussion avec la servlet.
	if (servletURL.indexOf('?') == -1) {
		_servletURL = servletURL + '?CONTAINED_TEXT=';
	} else {
		if (servletURL.lastIndexOf('&') != servletURL.length) {
			_servletURL = servletURL + '&CONTAINED_TEXT=';
		} else {
			_servletURL = servletURL + 'CONTAINED_TEXT=';
		}
	}
	_currentInputFieldLabelValue = _inputFieldLabel.value;
	_oldInputFieldLabelValue = _currentInputFieldLabelValue;
	if (_currentInputFieldLabelValue == "") {
		_oldInputFieldIdValue = null;
	} else {
		_oldInputFieldIdValue = _inputFieldId.value;
	}
	_suggestionList = null;
	_suggestionListLength = 0;
}

// Préciser la fonction à lancer lorsque l'identifiant mis dans le container
// d'ID est changé.
function initIdChangeAction(functionToLunch) {
	_idChangeFunction = functionToLunch;
}

/*******************************************************************************
 * 
 * fonctions de traitement
 * 
 ******************************************************************************/
// tourne en permanence pour suggerer suite à un changement du champ texte
function mainLoop() {
	var lowerCaseOldLabel = _oldInputFieldLabelValue.toLowerCase();
	var lowerCaseCurrentLabel = _currentInputFieldLabelValue.toLowerCase();
	// si les valeur sont similaire on ne recharge pas le contenu
	if (lowerCaseOldLabel != lowerCaseCurrentLabel) {
		// limiter le nombre de requetes AJAX quand on ajoute des lettres à un
		// element qui n'existe pas dans la liste des suggestion (le fait
		// d'ajouter des lettres rendra toujours une réponse vide)
		if (lowerCaseCurrentLabel.indexOf(lowerCaseOldLabel, 0) >= 0
				&& _suggestionListLength == 0 && _suggestionList != null) {
			_oldInputFieldLabelValue = _currentInputFieldLabelValue;
			_currentInputFieldLabelValue = _inputFieldLabel.value;
		} else if (_inputFieldLabel.value.length > 0) {
			callSuggestions(); // appel distant
			_inputFieldLabel.focus();
		}
	}
	setTimeout("mainLoop()", 400); // la fonction se redéclenchera dans 200 ms
	return true;
}

// envoyer une requete HTML au serveur pour récupérer les suggestions.
function callSuggestions() {
	var text = _inputFieldLabel.value;
	_oldInputFieldLabelValue = _currentInputFieldLabelValue;
	_currentInputFieldLabelValue = text;
	if (_xmlHttp && _xmlHttp.readyState != 0) {
		_xmlHttp.abort();
	}
	_xmlHttp = getXMLHTTP();
	if (_xmlHttp) {
		// appel à l'url distante
		_xmlHttp.open("GET", _servletURL + escapeURI(text), true);
		_xmlHttp.onreadystatechange = function() {
			if (_xmlHttp.readyState == 4 && _xmlHttp.responseXML) {
				_suggestionList = manageXmlSuggestions(_xmlHttp.responseXML);
				_suggestionListLength = _suggestionList.length;
				displaySuggestions();
				// mettre l'identifiant dans le containerId lorsqu'on à reçu la
				// liste de valeurs (L'ID est mis à jour quand on trouve une
				// valeur similaire à ce qui à été tapé dans la liste de
				// suggestions).
				putIdWhenEvent();
			}
		};
		// envoi de la requete
		_xmlHttp.send(null);
	}
}

// Transforme la réponse XML en un tableau de valeur de type requestValue
function manageXmlSuggestions(xmlDoc) {
	var requestValues = xmlDoc.getElementsByTagName('rqV');
	var requestValueList = new Array();
	for ( var i = 0; i < requestValues.length; ++i) {
		// si le label et l'id sont definis on les ajoutes.
		if (requestValues[i].attributes.getNamedItem("id")
				&& requestValues[i].firstChild) {
			rqValueId = requestValues[i].attributes.getNamedItem("id").value;
			rqValueLabel = requestValues[i].firstChild.data;
			rqValueLabel = rqValueLabel.substring(0,1).toUpperCase() + rqValueLabel.substring(1).toLowerCase()
			requestValueList.push(new RequestValue(rqValueId, rqValueLabel));
		}
	}
	return requestValueList;
}

// Fonction qui permet de déposer l'identifiant dans le container prévu à cet
// effet. Cette fonction ne dépose que l'identifiant que si celui-ci est
// différent du précédent (et par la même occasion lance la fonction
// spécifique).
// De plus si le label n'est représenté par aucun identifiant alors le container
// devient vide (ce qui est appelé changement de clé correspond à un changement
// de valeur mais aussi un changement de label lorsque la clé est vide).
function putIdWhenEvent() {
	var i = 0;
	while (i < _suggestionListLength
			&& _suggestionList[i].label.toLowerCase() != _inputFieldLabel.value
					.toLowerCase()) {
		i++;
	}
	// si on a trouvé une suggestion on calcule le nouvel ID
	var newInputFieldIdValue = "";
	if (i < _suggestionListLength) {
		newInputFieldIdValue = _suggestionList[i].id;
	}
	// on vérifie q'il y a du changement
	if (_oldInputFieldIdValue == null
			|| newInputFieldIdValue != _oldInputFieldIdValue) {
		bIdChange = _oldInputFieldIdValue == null
				|| newInputFieldIdValue != _oldInputFieldIdValue;
		_inputFieldId.value = newInputFieldIdValue;
		_oldInputFieldIdValue = newInputFieldIdValue;
		if (_idChangeFunction && bIdChange) {
			_idChangeFunction();
		}
	}
}

// Transforme le label pour mettre en gras les parties correspondantes au texte
// saisi. Pour mettre en gras le texte on utilise les balise <strong> et
// </strong>.
// Retourne un STRING
function transformLabelToBold(label) {
	var returnLabel = "";
	var subString = label;
	var currentValue = _currentInputFieldLabelValue;
	if (currentValue && currentValue != "") {
		var index = subString.toUpperCase().indexOf(currentValue.toUpperCase());
		var currentValueSize = currentValue.length;
		while (index > -1) {
			returnLabel += subString.substring(0, index) + "<STRONG>"
					+ subString.substring(index, index + currentValueSize)
					+ "</STRONG>";
			subString = subString.substring(index + currentValueSize,
					subString.length);
			index = subString.toUpperCase().indexOf(currentValue.toUpperCase());
		}
		returnLabel += subString;
		return returnLabel;
	} else {
		return label;
	}
}

// Enleve du label les balises permettant d'afficher en gras : <strong> et
// </strong>.
// Retourne un STRING
function transformLabelWithoutBold(label) {
	var returnLabel = "";
	var startStrong = "<STRONG>";
	var endStrong = "</STRONG>";
	var subString = label;
	var startStrongIndex = subString.toUpperCase().indexOf(startStrong);
	var endStrongIndex = subString.toUpperCase().indexOf(endStrong);
	while (startStrongIndex > -1 && endStrongIndex > startStrongIndex) {
		returnLabel += subString.substring(0, startStrongIndex);
		returnLabel += subString.substring(startStrongIndex
				+ startStrong.length, endStrongIndex);
		subString = subString.substring(endStrongIndex + endStrong.length,
				subString.length);
		startStrongIndex = subString.toUpperCase().indexOf(startStrong);
		endStrongIndex = subString.toUpperCase().indexOf(endStrong);
	}
	returnLabel += subString;
	return returnLabel;
}
/*******************************************************************************
 * 
 * fonctions liées au positionnement
 * 
 ******************************************************************************/
// calcule le décalage à gauche
function calculateOffsetLeft(element) {
	return calculateOffset(element, "offsetLeft")
}

// calcule le décalage vertical
function calculateOffsetTop(element) {
	return calculateOffset(element, "offsetTop")
}

// calcul une position par rapport au body de la page origine de la page. Cela
// permet de placer les éléments n'importe où quand leur parent est "body".
function calculateOffset(element, offsetPosition) {
	// position en pixel
	var positionInPx = 0;
	// boucle qui permet de parcourir tous les péres pour trouver leur position
	// ajout des positions.
	while (element) {
		// retrouve la position de l'élement par rapport à son parent.
		positionInPx += element[offsetPosition];
		// on place le parent pour récupérer son offset
		element = element.offsetParent
	}
	
	if(offsetPosition == "offsetTop") positionInPx -= 120;
	return positionInPx;
}

// calcule la largeur du champ
function calculateWidth() {
	if (_inputFieldLabel.offsetWidth < 2) {
		return _DEFAULT_COMPLETE_DIV_WIDTH;
	} else {
		return _inputFieldLabel.offsetWidth - 2 * 1;
	}
}

function setCompleteDivSize() {
	if (_completeDiv) {
		_completeDiv.style.left = calculateOffsetLeft(_inputFieldLabel) + "px";
		_completeDiv.style.top = calculateOffsetTop(_inputFieldLabel)
				+ _inputFieldLabel.offsetHeight - 1 + "px";
		_completeDiv.style.width = calculateWidth() + "px"
	}
}

/*******************************************************************************
 * 
 * Création et remplissage
 * 
 ******************************************************************************/

var completeDivFocused = false;
function createAutocompletionDiv() {
	_completeDiv = document.createElement("DIV");
	_completeDiv.id = "completeDiv";
	setCompleteDivSize();
	document.body.appendChild(_completeDiv);
	setStyleForElement(_completeDiv, "AutoCompleteDivListeStyle");
	_completeDiv.onmouseover = function(){
		completeDivFocused = true; 
		
	}
	_completeDiv.onmouseout = function(){
		completeDivFocused = false;
		
	}
	_completeDiv.onmousedown = function(){
		setTimeout("_inputFieldLabel.focus();", 5);
	}
}

// Permet de construire l'ensemble des DIV qui composent la DIV de suggestion.
// Cette fonction permet donc de construire, aprés avoir vider la DIV de
// suggestion, toutes les suggestions une par une. Une suggestion est composée
// de 2 SPAN : le label et l'ID.
function displaySuggestions() {
	// suppression des enfants de la DIV
	while (_completeDiv.childNodes.length > 0) {
		_completeDiv.removeChild(_completeDiv.childNodes[0]);
	}
	// mise en place des suggestions
	for ( var f = 0; f < _suggestionListLength; ++f) {
		// creation de la DIV
		var newDiv = document.createElement("DIV");
		// ajout des evenements claviers.
		newDiv.onmousedown = divOnMouseDown;
		newDiv.onmouseover = divOnMouseOver;
		newDiv.onmouseout = divOnMouseOut;
		// ajout du style
		setStyleForElement(newDiv, "AutoCompleteDiv");
		// création de la SPAN label
		var newSpanLabel = document.createElement("SPAN");
		newSpanLabel.name = "label";
		// le texte de la suggestion
		newSpanLabel.innerHTML = transformLabelToBold(_suggestionList[f].label);
		// création de la SPAN ID
		var newSpanID = document.createElement("SPAN");
		newSpanID.name = "idValue";
		newSpanID.style.display = "none";
		newSpanID.innerHTML = _suggestionList[f].id;

		newDiv.appendChild(newSpanLabel);
		newDiv.appendChild(newSpanID);

		_completeDiv.appendChild(newDiv)
	}
	pressAction();
	if (_suggestionListLength > 0) {
		_completeDiv.height = 16 * _suggestionListLength + 4;
	} else {
		hideCompleteDiv();
	}
}

// Change la suggestion selectionnée. Cette méthode traite les touches haut, bas
// et enter
function handleCursorUpDownEnter(eventCode) {
	if (eventCode == 40) {
		highlightNewValue(_highlightedSuggestionIndex + 1);
		return false
	} else if (eventCode == 38) {
		highlightNewValue(_highlightedSuggestionIndex - 1);
		return false
	} else if (eventCode == 13 || eventCode == 3) {
		_inputFieldLabel.value = getSuggestionLabel(_highlightedSuggestionDiv);
		putIdWhenEvent();
		hideCompleteDiv();
		return false
	}
	return true
}

// gère une touche pressée autre que haut/bas/enter
function pressAction() {
	_highlightedSuggestionIndex = -1;
	var suggestionList = _completeDiv.getElementsByTagName("div");
	var suggestionSize = suggestionList.length;
	// on stocke les values précédentes
	// possiblités de complétion
	_completeDivDivList = suggestionList;
	if (_currentInputFieldLabelValue == "" || suggestionSize == 0) {
		hideCompleteDiv()
	} else {
		showCompleteDiv()
	}
	var trouve = false;
	// si on a du texte sur lequel travailler
	if (_currentInputFieldLabelValue.length > 0) {
		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 < suggestionSize; indice++) {
			if (getSuggestionLabel(suggestionList.item(indice)).toUpperCase()
					.indexOf(_currentInputFieldLabelValue.toUpperCase()) == 0) {
				trouve = true;
				break
			}
		}
	}
	// on désélectionne toutes les suggestions
	for ( var i = 0; i < suggestionSize; i++) {
		setStyleForElement(suggestionList.item(i), "AutoCompleteDiv");
	}
	// si l'entrée utilisateur (n) est le début d'une suggestion (n-1) on
	// sélectionne cette suggestion avant de continuer
	if (trouve) {
		_highlightedSuggestionIndex = indice;
		_highlightedSuggestionDiv = suggestionList
				.item(_highlightedSuggestionIndex);
	} else {
		_highlightedSuggestionIndex = -1;
		_highlightedSuggestionDiv = null
	}
	var supprSelection = false;
	switch (_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:
		// on supprime la suggestion du texte utilisateur
		supprSelection = true;
		break;
	default:
		break
	}
	// si on a une suggestion (n-1) sélectionnée
	if (!supprSelection && _highlightedSuggestionDiv) {
		setStyleForElement(_highlightedSuggestionDiv, "AutoCompleteDivAct");
		var z;
		if (trouve) {
			z = getSuggestionLabel(_highlightedSuggestionDiv).substr(0);
		} else {
			z = _currentInputFieldLabelValue;
		}
		if (z != _inputFieldLabel.value) {
			if (_inputFieldLabel.value != _currentInputFieldLabelValue) {
				return;
			}
			if (_autocompletValue) {
				// si on peut créer des range dans le document
				if (_inputFieldLabel.createTextRange
						|| _inputFieldLabel.setSelectionRange) {
					_inputFieldLabel.value = z;
				}
				// on sélectionne la fin de la suggestion
				if (_inputFieldLabel.createTextRange) {
					var t = _inputFieldLabel.createTextRange();
					t.moveStart("character",
							_currentInputFieldLabelValue.length);
					t.select()
				} else if (_inputFieldLabel.setSelectionRange) {
					_inputFieldLabel.setSelectionRange(
							_currentInputFieldLabelValue.length,
							_inputFieldLabel.value.length)
				}
			}
		}
	} else {
		// sinon, plus aucune suggestion de sélectionnée
		_highlightedSuggestionIndex = -1;
	}
}

// permet le blur du champ texte après que la touche haut/bas ai été pressé.
// le focus est récupéré après traitement (via le timeout).
function blurThenGetFocus() {
	_cursorUpDownPressed = true;
	_inputFieldLabel.blur();
	setTimeout("_inputFieldLabel.focus();", 5);
	return
}

// taille de la selection dans le champ input
function rangeSize(n) {
	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
}

// taille du champ input non selectionne
function beforeRangeSize(n) {
	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
}

// Retourne la valeur de la suggestion (texte) contenue dans une div de
// suggestion
function getSuggestionLabel(oneDiv) {
	if (!oneDiv) {
		return null;
	}
	// innerHTML : car il y a des balises de type <STRONG> dans le label
	return transformLabelWithoutBold(trimCR(oneDiv.getElementsByTagName("SPAN")[0].innerHTML));
}

// supprime les caractères retour chariot et line feed d'une chaine de
// caractères
function trimCR(chaine) {
	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
}

// cache la DIV + remet le comportement initial de du input (la touche entrée
// valide le formulaire) + remet à 0 la suggestion selectionnée
function hideCompleteDiv() {
	_highlightedSuggestionIndex = 0;
	_completeDiv.style.visibility = "hidden";
	_inputFieldLabel.onkeypress = _oldOnKeyPressHandler;
}

// fait apparaitre la DIV + fait en sorte que le comportement du INPUT face en
// sorte que l'appui sur ENTREE ne valide pas le formulaire
function showCompleteDiv() {
	_inputFieldLabel.onkeypress = _onKeyEnterHandler;
	_completeDiv.style.visibility = "visible";
	setCompleteDivSize()
}

// Change la suggestion en surbrillance
// index => index de l'élément à selectionner.
function highlightNewValue(index) {
	if (!_completeDivDivList || _suggestionListLength <= 0) {
		return;
	}
	showCompleteDiv();
	if (index >= _suggestionListLength) {
		index = _suggestionListLength - 1
	}
	if (_highlightedSuggestionIndex != -1
			&& index != _highlightedSuggestionIndex) {
		setStyleForElement(_highlightedSuggestionDiv, "AutoCompleteDiv");
		_highlightedSuggestionIndex = -1
	}
	if (index < 0) {
		_highlightedSuggestionIndex = -1;
		_inputFieldLabel.focus();
		return
	}
	_highlightedSuggestionIndex = index;
	_highlightedSuggestionDiv = _completeDivDivList.item(index);
	setStyleForElement(_highlightedSuggestionDiv, "AutoCompleteDivAct");
	// _inputFieldLabel.value = getSuggestionLabel(_highlightedSuggestionDiv);
}
