

// Fonction renvoyant un tableau de toutes les suggestions commencant par la chaîne de caractères "start"
findSuggestions = function()
{
	var liste = new Array(); // Liste de suggestions
	var start = this.currentInputFieldValue.toLowerCase();
	if (start == "")
		return liste;
	var len = start.length;
	for (var i=0 ; i<mv_recipients.length ; i++)
		if (mv_recipients[i].substr(0, len) == start)
		{
			liste.push(mv_recipients[i]); // Rajoute l'élément à la liste de suggestions
			if (liste.length >= this.MAX_SUGGESTIONS)
				break;
		}
	return liste;
}

// Rajoute une fonction d'autocomplétion au champ "field", proposant
// "max" suggestions au maximum, données par la fonction "findSuggestionsFunction"
autocompletion = function(field, max, findSuggestionsFunction)
{
	// Garde une trace de l'objet
	if (!document.autocompletion)
		document.autocompletion = new Array();
	document.autocompletion.push(field);
	field.autocompletionId = document.autocompletion.length-1;
	// Récupération des paramètres
	field.MAX_SUGGESTIONS = max;
	field.findSuggestions = findSuggestionsFunction;

	// Création et placement de la liste de suggestions
	field.suggestionsDiv = document.getElementById('autocompletion');
	field.setSuggestionsDivSize = setSuggestionsDivSize;
	field.setSuggestionsDivSize();

	// Définitions des attributs
	field.eventKeyCode = null;
	field.currentInputFieldValue = field.value;
	field.oldInputFieldValue = field.value;
	field.suggestionsCache = new Array();
	field.suggestionsCache[""] = "";
	field.selectedSuggestion = -1;
	field.lastKeyCode = -1;

	// Définitions des évènements
	field.onkeydown = autocompletionKeyDownHandler;
	field.onkeyup = autocompletionKeyUpHandler;
	field.onblur = autocompletionBlurHandler;

	// Définitions des méthodes
	field.showSuggestions = showSuggestions;
	field.highlightNewValue = highlightNewValue;
	field.rangeSize = rangeSize;
	field.beforeRangeSize = beforeRangeSize;

	// Boucle pour proposer en permanence de nouvelles suggestions
	field.autocompletionLoop = function()
	{
		if (this.currentInputFieldValue != this.oldInputFieldValue)
		{
			var suggestions = this.suggestionsCache[this.currentInputFieldValue];
			if (suggestions) // La réponse est encore dans le cache
				if (suggestions.length > 0)
					this.showSuggestions(suggestions);
				else
					this.suggestionsDiv.style.visibility = "hidden";
			else
			{
				var liste = this.findSuggestions();
				this.suggestionsCache[this.currentInputFieldValue.toLowerCase()] = liste;
				if (liste.length > 0)
					this.showSuggestions(liste);
				else
					this.suggestionsDiv.style.visibility = "hidden";
			}
		}
		this.oldInputFieldValue = this.currentInputFieldValue;
		setTimeout("document.autocompletion["+this.autocompletionId+"].autocompletionLoop()", 200); // La fonction se redéclenchera dans 200 ms
	}
	setTimeout("document.autocompletion["+field.autocompletionId+"].autocompletionLoop()", 200); // Ne pas utiliser setInterval, qui est asynchrone
}

// Actualise la liste de suggestions
function showSuggestions(liste)
{
	var content = '';
	if (this.lastKeyCode != 8)
		this.selectedSuggestion = 0;
	else
		this.selectedSuggestion = -1;
	for (var f=0 ; f<liste.length ; f++)
		content += '<div' + ((f==this.selectedSuggestion)?' class="selected"':'') + '>' + liste[f] + '</div>';
	this.suggestionsDiv.innerHTML = content;
	for (var i=0 ; i<liste.length ; i++)
	{
		this.suggestionsDiv.childNodes[i].autocompletionField = this;
		this.suggestionsDiv.childNodes[i].index = i;
		this.suggestionsDiv.childNodes[i].onmousedown = autocompletionSuggestionMouseDownHandler;
		this.suggestionsDiv.childNodes[i].onmouseover = autocompletionSuggestionMouseOverHandler;
		this.suggestionsDiv.childNodes[i].onmouseout = autocompletionSuggestionMouseOutHandler;
	}
	this.suggestionsDiv.style.visibility = "visible";

	if ((this.selectedSuggestion != -1) && (liste[0].toLowerCase().indexOf(this.value.toLowerCase()) == 0))
	{
		var pos = this.beforeRangeSize();
		this.value = liste[0];
		if (this.createTextRange)
		{
			var t = this.createTextRange();
			t.moveStart("character", pos);
			t.select();
		}
		else if (this.setSelectionRange)
			this.setSelectionRange(pos, this.value.length);
	}
}

// Handler pour le keydown du champ texte
var autocompletionKeyDownHandler = function(event)
{
	// Accès evenement compatible IE/Firefox
	if (!event && window.event)
		event = window.event;
	// On enregistre la touche ayant déclenché l'évènement
	if (event)
		this.lastKeyCode = event.keyCode;
}

// Handler pour le keyup du champ texte
var autocompletionKeyUpHandler = function(event)
{
	// Accès evenement compatible IE/Firefox
	if (!event && window.event)
		event = window.event;
	var keyCode = event.keyCode;
	switch (keyCode)
	{
		case 38: // "haut"
		if (this.value != "")
			this.highlightNewValue(this.selectedSuggestion - 1);
		break;

		case 40: // "bas"
		if (this.value != "")
			this.highlightNewValue(this.selectedSuggestion + 1);
		break;

		case 8: // "backspace"
		this.currentInputFieldValue = this.value;
		var suggestionsList = this.suggestionsDiv.childNodes;
		for (var i=0 ; i<suggestionsList.length ; i++)
			suggestionsList[i].className = '';
		this.selectedSuggestion = -1;
		break;

		default:
		this.currentInputFieldValue = this.value.substr(0, this.beforeRangeSize());
		break;
	}
}

// Handler pour le blur du champ texte
var autocompletionBlurHandler = function()
{
	this.suggestionsDiv.style.visibility = "hidden";
}

// Handler pour le mousedown de chaque div de suggestion
var autocompletionSuggestionMouseDownHandler = function()
{
	this.autocompletionField.value = this.innerHTML;
}

// Handler pour le mouseover de chaque div de suggestion
var autocompletionSuggestionMouseOverHandler = function()
{
	if ((this.autocompletionField.selectedSuggestion != -1) && (this.index != this.autocompletionField.selectedSuggestion))
		this.autocompletionField.suggestionsDiv.childNodes[this.autocompletionField.selectedSuggestion].className = '';
	this.className = 'selected';
	this.autocompletionField.selectedSuggestion = this.index;
}

// Handler pour le mouseout de chaque div de suggestion
var autocompletionSuggestionMouseOutHandler = function()
{
	this.className = '';
}

// Sélectionne une nouvelle suggestion dans la liste
function highlightNewValue(index)
{
	var suggestionsList = this.suggestionsDiv.childNodes;
	var nbSuggestions = suggestionsList.length;
	if (!suggestionsList || (nbSuggestions <= 0) || ((nbSuggestions == 1) && (this.suggestionsDiv.innerHTML.indexOf('<') == -1)))
		return;
	if (index >= nbSuggestions)
		index = nbSuggestions - 1;
	if ((this.selectedSuggestion != -1) && (index != this.selectedSuggestion))
		suggestionsList[this.selectedSuggestion].className = '';
	if (index < 0)
	{
		this.value = this.oldInputFieldValue;
		this.currentInputFieldValue = this.oldInputFieldValue;
		this.selectedSuggestion = -1;
		return;
	}
	this.selectedSuggestion = index;
	suggestionsList[index].className = 'selected';
	this.currentInputFieldValue = this.oldInputFieldValue;
	this.value = suggestionsList[index].innerHTML;
	if (this.createTextRange)
	{
		var t = this.createTextRange();
		t.moveStart("character", this.currentInputFieldValue.length);
		t.select();
	}
	else if (this.setSelectionRange)
		this.setSelectionRange(this.currentInputFieldValue.length, this.value.length);
}

// Taille de la sélection dans le champ input
function rangeSize()
{
	var size = 0;
	if (this.createTextRange)
		size = document.selection.createRange().duplicate().text.length;
	else if (this.setSelectionRange)
		size = this.selectionEnd - this.selectionStart;
	return size;
}

// Taille du champ input non sélectionné
function beforeRangeSize()
{
	return this.value.length - this.rangeSize();
}

// Défini la position et la taille de la liste de suggestions
function setSuggestionsDivSize()
{
	var absoluteOffsetLeft = 0, absoluteOffsetTop = 0;
	var obj = this;
	while (obj)
	{
		absoluteOffsetLeft += obj.offsetLeft;
		absoluteOffsetTop += obj.offsetTop;
		obj = obj.offsetParent;
	}
	this.suggestionsDiv.style.left = absoluteOffsetLeft + "px";
	this.suggestionsDiv.style.top = (absoluteOffsetTop + this.offsetHeight - 1) + "px";
	this.suggestionsDiv.style.width = this.offsetWidth-2 + "px";
}
