// Enzo@Arkonis
// 1.01 optimisation; bug sur les accents sur le retour d'un choix unique; bug sur shift tab sur champ vide
// 1.02 ajout de l'option completion_var['unique']
// 1.03 ajout des id (optionnel) sur la completion & de l'evenement & extension de plume.coordonnee

var completion_var = {
	hauteur : 20,
	taille	: 13,
	unique : false,
	simple : false,
	echappemment : false,
	ajax : false,
	serveur : false,
	evenement : false,
	valeur : ''
};

function completion(choix, fonction, options) {
	var menu, tmp, desactiver, valeur, max, liste, index, event, cible, sens, ligne, evenement;
	
	menu = document.getElementById('completion');
	
	if (typeof(choix) == 'boolean' && ! choix) {
		if (menu) {
			menu.parentNode.removeChild(menu);
			tmp = document.getElementsByTagName('body')[0];
			if (completion_var['echappemment']) {
				tmp.attribuer('onclick', completion_var['echappemment']);
				completion_var['echappemment'] = false;
			}
		}
		return;
	}
	
	if (typeof(choix) == 'string') {
		if (fonction == '') {
			completion(false);
			return;
		}
		
		while (menu.lastChild)
			menu.removeChild(menu.lastChild);
		liste = menu.bebe('ul');
		
		desactiver = /<!--+ *(.*) *-+->/;
		valeur = fonction.split(/\n/);
		max = valeur.length;
		if (max == 1 && completion_var['unique']) {
			ligne = valeur[0].split(/\t/);
			ligne = ligne.length > 1 ? ligne[1] : ligne[0];
			if (! desactiver.test(ligne)) {
				if (completion_var['simple'])
					return;
				choix = document.getElementById(menu.donnee('zone'));
				(cible = liste.bebe('li', { 'id' : "completion_" + ligne })).innerHTML = ligne;
				choix.value = cible.innerHTML;
				completion(false);
				return;
			}
		}
		completion_var['simple'] = false;
		
		index = menu.donnee('hauteur');
		menu.style.height = (max > index ? index : max) * menu.donnee('taille') + 3 + 'px';
		
		for (index = 0; index < max; ++ index) {
			tmp = valeur[index].split(/\t/);
			ligne = tmp[0];
			tmp = tmp[tmp.length > 1 ? 1 : 0];
			if (! desactiver.test(tmp))
				liste.bebe('li', { 'id' : "completion_" + ligne }).innerHTML = tmp;
			else if (tmp = desactiver.exec(tmp)[1])
				liste.bebe('li', { 'class' : 'disabled', 'id' : "completion_" + ligne }).innerHTML = tmp;
			else
				liste.bebe('li', { 'class' : 'disabled', 'id' : "completion_" + ligne }).bebe('hr');
		}
		
		menu.style.display = 'block';
		return;
	}
	
	event = choix || window.event;
	cible = event.target || event.srcElement;
	
	if (! menu) {
		menu = plume(cible.parentNode).bebe('div', { 'id' : 'completion', 'style' : 'left:' + cible.offsetLeft + 'px;top:' + (cible.offsetTop + cible.offsetHeight) + 'px;display:none;position:absolute',
			'onmouseover' : 'completion(event,1)', 'onmouseout' : 'completion(event,0)', 'onclick' : 'completion(event,2)' });
		tmp = plume(document.getElementsByTagName('body')[0]).attribuer('onclick', 'completion(false)');
		completion_var['echappemment'] = tmp != 'completion(false)' ? tmp : false;
	}
	
	evenement = false;
	switch (event.type) {
	case 'keydown':
		if (event.keyCode != 9 && event.keyCode != 13)	// 13: sinon pert le RC dans un submit
			return;
		// pas de break;
	case 'keyup':	// up pour l'effacement et le remplacement
		sens = 0;
		switch (event.keyCode) {
		case 40:	// DOM_VK_DOWN
			sens = 1;
			break;
		case 38:	// DOM_VK_UP
			sens = -1;
			break;
		case 9:		// DOM_VK_TAB
			if (event.type == 'keyup' || choix.shiftKey)
				return;
		case 13:	// DOM_VK_RETURN
		case 14:	// DOM_VK_ENTER
			if (menu.style.display != 'block' && fonction) {
				cible = menu.donnee('zone') ? document.getElementById(menu.donnee('zone')) : cible;
				if (typeof(fonction) == 'function')
					fonction(cible, completion_var.valeur);
				else
					eval(fonction + "(cible, completion_var.valeur)");
			}
			evenement = 'select';
			break;
		case 37:	// DOM_VK_LEFT
		case 39:	// DOM_VK_RIGHT
			return;
		case 27:	// DOM_VK_ESCAPE
			if (menu.style.display == 'block')
				completion(false);
			return;
		case 8:	// DOM_VK_BACK_SPACE
			if (menu.style.display != 'block')
				return;
			//pas de break;
		default:
			completion_var['simple'] = cible.value.length > 1 && ! menu.childNodes.length;	// pas de completition si aucun choix
			
			if (typeof(options) != 'object')
				options = {};
			menu.className = options['classe'] || 'completion';
			menu.donnee({ 'hauteur' : options['hauteur'] || completion_var.hauteur, 'zone' : cible.id, 'taille' : options['taille'] || completion_var.taille });
			
			if (typeof(completion_var['ajax']) != 'object')
				completion_var['ajax'] = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false;
			if (completion_var['ajax']) {
				if (completion_var['ajax'].readyState && completion_var['ajax'].readyState != 4)
					completion_var['ajax'].abort();
				completion_var['ajax'].open('GET', (completion_var.serveur || location.href.replace(/\?.*$/, '')) + "?completion_id=" + cible.id + '&completion_value=' + escape(cible.value), true);
				completion_var['ajax'].onreadystatechange = function() { if (completion_var['ajax'] && completion_var['ajax'].readyState == 4 && /^[^:\n]+:/.test(completion_var['ajax'].responseText)) { var separateur = completion_var['ajax'].responseText.indexOf(':', 0); completion(completion_var['ajax'].responseText.substr(0, separateur), completion_var['ajax'].responseText.substr(separateur + 1)) } }
				completion_var['ajax'].send(null);
			}
			return;
		}
		if (menu.style.display != 'block')
			return;
		liste = plume(menu.getElementsByTagName('li'));
		while (cible = liste.suivant())
			if (/\bselected\b/.test(cible.className))
				break;
		if (sens) {
			if (cible) {
				cible.className = '';
				if (sens < 0)
					liste.suivant(-2);
			} else
				liste.suivant(0);
			while (cible = liste.suivant(sens))
				if (! /\bdisabled\b/.test(cible.className)) {
					cible.className = 'selected';
					evenement = 'over';
					break;
				}
			if (evenement)
				ligne = cible;
			cible = false;
		} else
			ligne = cible;
		break;
	case 'click':
		if (cible.tagName == 'LI') {
			evenement = 'select';
			ligne = cible;
		} else
			cible = false;
		break;
	case 'mouseout':
		if (cible.tagName == 'LI') {
			cible.className = cible.className.replace(/\bselected\b/g, '');
			cible = cible.parentNode;
		}
		
		ligne = plume(cible.tagName == 'UL' ? cible.offsetParent : cible);
		tmp = ligne.coordonnee('relative');
		if (tmp[1] > event.clientX || event.clientX > tmp[3] || tmp[0] > event.clientY || event.clientY > tmp[2]) {
			evenement = 'out';
			ligne = cible;
		}
		cible = false;
		break;
	case 'mouseover':
		if (cible.tagName == 'LI') {
			cible.className = cible.className + ' selected';
			evenement = 'over';
			ligne = cible;
		}
		cible = false;
		break;
	default:
		return;
	}
	
	choix = menu.donnee('zone');
	
	if (evenement && completion_var.evenement) {
		if (ligne.tagName != 'LI')
			ligne = false;
		if (typeof(completion_var.evenement) == 'function')
			completion_var.evenement(evenement, ligne, choix);
		else
			eval(completion_var.evenement + "(evenement, ligne, choix)");
	}
	
	if (cible && cible.tagName == 'LI') {
		completion(false);
		if (/\bdisabled\b/.test(cible.className))
			return;
		choix = document.getElementById(choix);
		choix.value = cible.innerHTML.replace(/\&amp;/, '&');
		choix.focus();
		index = /^completion_(.*)$/.exec(cible.id)[1];
		completion_var.valeur = index;
		if (/*event.keyCode == 9 &&*/ fonction)
			if (typeof(fonction) == 'function')
				fonction(choix, index);
			else
				eval(fonction + "(choix, index)");
	}
	return;
}

function plume(element) {
    if (element && typeof(element) == 'string')
		element = document.getElementById(element);
	if (! element)
		return element;
	if (element.bebe) {
		element._suivant = 0;
		return element;
	}
	if (document.all && element.nodeName == '#text') return element;	// IE
	if (document.all && element.setAttribute) element.setAttribute('_donnee', {}); else element._donnee = {};
	element.donnee = function(cle, valeur) {
		if (typeof(cle) == 'object') {
			for (var index in cle)
				this._donnee[index] = cle[index];
			return;
		}
		var retour = this._donnee[cle];
		if (typeof(valeur) != 'undefined')
			this._donnee[cle] = valeur;
		return retour;
	}
	element.bebe = function(balise, attributs, queue) {
		var bebe = document.bebe(balise, attributs);
		if (queue)
			this.insertBefore(bebe, queue);
		else
			this.appendChild(bebe);
		return bebe;
	}
	element.coordonnee = function(option) {
		var sTop, sLeft, oTop, oLeft, h, w, element = this;
		sTop = sLeft = oTop = oLeft = 0;
		if (element) {
			w = element.offsetWidth;
			h = element.offsetHeight;
			do {
				oTop += element.offsetTop || 0;
				sTop += element.scrollTop || 0;
				oLeft += element.offsetLeft || 0;
				sLeft += element.scrollLeft || 0;
			} while (element = element.offsetParent);
		}
		if (typeof(option) == 'undefined')
			option = 'relative';
		switch (option) {
		case 'offset':
			return [oTop, oLeft, oTop + h, oLeft + w];
		case 'scroll':
			return [sTop, sLeft, sTop + h, sLeft + w];
		case 'offset,scroll':
			return [oTop, oLeft, oTop + h, oLeft + w, sTop, sLeft, sTop + h, sLeft + w];
		case 'scroll,offset':
			return [sTop, sLeft, sTop + h, sLeft + w, oTop, oLeft, oTop + h, oLeft + w];
		case 'relative':
			return [oTop -= sTop, oLeft -= sLeft, oTop + h, oLeft + w];
		}
		element = /^((o)ffset|(s)croll)(Left|Top)$/;
		if (! element.test(option))
			return 0;
		option = element.exec(option);
		option.shift();
		option.shift();
		eval('element = ' + option.join(''));
		return element;
	}
	element.attribuer = function(attribut, valeur) {
		var retour;
		if (! attribut)
			return;
		if (typeof(attribut) == 'string') {
			var cle = attribut;
			attribut = {};
			attribut[cle] = valeur;
		}
		if (document.all) {	// bug ie
			for (var cle in attribut) {
				valeur = attribut[cle];
				switch (cle) {
				case 'class':
					cle = 'className';
					break;
				case 'style':
					cle = 'cssText';
					break;
				}
				retour = this.getAttribute(cle);
				if (/^on/.test(cle))
					eval("this." + cle + "=function(event){" + valeur + "}");
				else
					this.setAttribute(cle, valeur);
			}
		} else {
			for (var cle in attribut) {
				retour = this.getAttribute(cle);
				valeur = attribut[cle];
				if (valeur == null)
					this.removeAttribute(cle);
				else
					this.setAttribute(cle, valeur);
			}
		}
		return retour;
	}
	if (document.all && element.setAttribute) element.setAttribute('_suivant', 0); else element._suivant = 0;
	element.suivant = function(positionner) {
		var retour, sens = 1;
		if (typeof(positionner) != 'undefined') {
			sens = parseInt(positionner, 10);
			if (! sens)
				this._suivant = 0;
		}
		if (this._suivant >= 0 && this._suivant < this.length) {
			retour = this[this._suivant];
			this._suivant += sens;
		}
		return retour;
	}
	return element;
}

document.bebe = function(balise, attributs) {
	var bebe;
	if (typeof(balise) == 'string') {
		if (typeof(attributs) == 'string') {
			bebe = document.createTextNode(attributs);
			attributs = false;
		} else
			bebe = document.createElement(balise);
	} else
		bebe = balise;
	plume(bebe);
	if (attributs && bebe.attribuer) bebe.attribuer(attributs);	// IE
	return bebe;
}

function frameId() {
	var x, id, cadre = arguments[0];
	for (x = 1; x < arguments.length; ++ x)
		if (id = arguments[x])
			cadre = document.all ? cadre.frames[id].document : cadre.getElementById(id).contentDocument;
	return cadre;
}

function hover_bug_ie(event) {
	if (! /Microsoft/i.test(navigator.appName))
		return;
	event = event || window.event;
	var balise = event.srcElement;
	if (! balise.tagName || (balise.tagName != 'SPAN' && balise.tagName != 'LI'))
		return;
	var classe = balise.className.replace(/ hover_bug_ie/, '');
	if (event.type == 'mouseover')
		classe += ' hover_bug_ie';
	balise.className = classe;
}

function ajax(methode, url, parametres, success, erreur) {
	if (typeof(ajax_xhr) == 'undefined')
		ajax_xhr = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false;
	if (! ajax_xhr)
		return false;
	var local_xhr = ! ajax_xhr.readyState ? ajax_xhr : window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false;
	if (methode == 'get') {
		url += '?' + parametres;
		parametre = null;
	}
	local_xhr.open('GET', url, success || erreur);
	local_xhr.onreadystatechange = function() {
		if (local_xhr && local_xhr.readyState == 4) {
			var fonction = local_xhr.status == 200 ? success : erreur;
			if (fonction)
				fonction(local_xhr.responseText);
		}
	}
	local_xhr.send(parametre);
	if (success || erreur)
		return true;
	local_xhr.readyState = 0;
	return local_xhr.responseText;
}

/*
if (typeof($) == 'undefined') {
	function $(id) {
		if (typeof(id) == 'string')
			return document.getElementById(id);
		return id;
	}
}/**/
