	// Images
	var arrowImage = './site/images/selectBox/select_arrow.gif';	// Regular arrow
	var arrowImageOver = './site/images/selectBox/select_arrow_over.gif';	// Mouse over
	var arrowImageDown = './site/images/selectBox/select_arrow_down.gif';	// Mouse down
	// Références globales		
	var zIndex = 0; // compteur pour les z-index
	var currentlyOpenedOptionBox = false; // référence sur le div actuellement ouvert
	var editableSelect_activeArrow = false;	// référence sur la flèche du select actuellement actif (image flèche "active")
		
	/****************************************************************************************************************************************/
	function selectBox_init(id_input, disabled, width)
	// crée un élément select à partir d'un input et d'une liste de valeur, disabled indique si la saisie est désactivée pour l'input (false par défaut)
	{
		if(disabled!=true) disabled = false;
		if(!width) width=200; // largeur par défaut
		// input
		var dest = document.getElementById(id_input);
		dest.is_disabled  = disabled;
		dest.is_visible   = false; // indique si le div d'option est montré
		dest.className	  ='selectBoxInput';
		dest.activeOption = ''; 
		dest.style.width  = width + 'px';
		dest.onmousedown  = selectBox_showOptions; // ouverture de la liste
		dest.onkeydown	  = selectBox_specialChar;	 // controle des caractères spéciaux
		dest.onkeyup 	  = selectBox_highlightAndHideFromValue; // surlignement et masquage automatique
		// div contenant l'input, la flèche et le div d'option
		var div = document.createElement('DIV');
		div.id				 = 'selectBox_' + dest.id;		
		div.style.styleFloat = 'left';
		div.style.width		 = width + 2 + 2 + 15 + 1 + 2 + 'px'; // largeur de l'input + marges horizontales de l'input + marge input/image largeur de l'image + décalage à droite de l'image + bordures du div
		div.style.position	 = 'relative';
		div.className		 = 'selectBox';
		div.style.zIndex	 = 10000 - zIndex;
		zIndex++;
		var parent = dest.parentNode;
		div.appendChild(dest);	
		parent.appendChild(div);
		// input hidden pour la valeur de retour (quand la valeur affichée ne correspond pas à celle que l'on veut retourner, comme un nom et un id par ex)
		var input_hidden = document.createElement('INPUT');
		input_hidden.id    = dest.id + '_hidden';
		input_hidden.name  = dest.id + '_hidden';
		input_hidden.type  = 'hidden';
		input_hidden.value = (dest.getAttribute('value_hidden')) ? dest.getAttribute('value_hidden') : '';
		div.appendChild(input_hidden);	
		// image de la flèche
		var img = document.createElement('IMG');
		img.src		  = arrowImage;
		img.className = 'selectBoxArrow';
		img.id		  = 'arrowSelectBox_' + dest.id;
		img.input_id  = dest.id; // id de l'input associé
		img.style.cursor = (navigator.userAgent.indexOf('MSIE')>=0) ? 'hand' : 'pointer';
		img.onmouseover	= selectBox_switchImage; // changement au survol
		img.onmouseout	= selectBox_switchImage;  // idem
		img.onclick		= selectBox_switchOptions;		// ouverture de la liste
		div.appendChild(img);
		// div d'option
		var optionDiv = document.createElement('DIV');
		optionDiv.id		  = 'selectBoxOptions_' + dest.id;
		optionDiv.input_id	  = dest.id;
		optionDiv.className	  ='selectBoxOptionContainer';
		optionDiv.style.width = div.style.width;
		div.appendChild(optionDiv);
		// remplissage du div d'option
		if(dest.getAttribute('selectBoxOptions'))
		{
			var tab_options = dest.getAttribute('selectBoxOptions').split(';;');
			var optionsTotalHeight = 0;
			var optionArray = new Array();
			// ajustement de la taille de la liste déroulante
			for(var no=0, cpt=0;no<tab_options.length;no++)
			{
				if(tab_options[no].length>0) // s'il y a une valeur valide
				{
					var option_tmp = tab_options[no].split('::'); // on sépare le libellé de l'option [0] et la valeur de retour [1]
					if(option_tmp.length==1||option_tmp[1].length==0) option_tmp[1] = option_tmp[0]; // la valeur n'est pas initialisée, on prend le libellé comme valeur de retour
					// option
					var anOption = document.createElement('DIV');
					anOption.id			  = 'selectBoxOptions_' + dest.id + '_' +cpt; // id d'une option
					anOption.input_id	  = dest.id; // id de l'input associé
					anOption.style.width  = 'auto'; // -2 pour les marges, -5 pour le padding-left
					anOption.title		  = option_tmp[0];
					anOption.innerHTML	  = option_tmp[0];
					anOption.className    = 'selectBoxAnOption';
					anOption.option_lib	  = option_tmp[0]; // libellé de l'option
					anOption.option_value = option_tmp[1]; // valeur de l'option
					anOption.style.cursor = (navigator.userAgent.indexOf('MSIE')>=0) ? 'hand' : 'pointer';
					anOption.onclick 	  = selectBox_selectOptionValue;
					anOption.onmouseover  = selectBox_highlightOption;
					// on rattache l'option au div d'option
					optionDiv.appendChild(anOption);
					optionsTotalHeight = (anOption.offsetHeight>0) ? optionsTotalHeight + anOption.offsetHeight : optionsTotalHeight + anOption.clientHeight;
					optionArray.push(anOption);
					cpt++; // compteur des id
				}
			} 
			// hauteur de la liste
			if(optionArray.length<11&&optionsTotalHeight>0) optionDiv.style.height = optionsTotalHeight+Math.round(1.5*optionArray.length)+'px'; // + 1 px par option à cause des marges
			else if(optionArray.length<11) optionDiv.style.height = 'auto';
			if(!optionDiv.style.height||optionDiv.style.height.length==0) // hauteur par défaut
			{
				if(optionArray.length>30) optionDiv.style.height='200px';
				else optionDiv.style.height='150px';
			}
			optionDiv.defaultHeigth = optionDiv.style.height; // on sauvegarde la hauteur initiale
			// on masque le conteneur
			optionDiv.style.display = 'none';
		}		
	}
	/****************************************************************************************************************************************/	
	function selectBox_switchOptions(id_input)
	// montre ou cache le div d'option associé à l'input courant en fonction de son style 'display'
	// fonctionne soit avec this (pour l'input et l'image) soit en passant l'id de l'input en paramètre (dans ce cas on traite comme pour une image)
	{
		// références
		var refToInput; // référence sur l'input
		if(document.getElementById(id_input)) refToInput = document.getElementById(id_input); // si l'id est passé en paramètre
		else
		{
			var id_input = false;
			if(this.input_id) refToInput = document.getElementById(this.input_id);	// si l'évènement a lieu sur l'image
			else refToInput = this; 					// si l'évènement a lieu sur l'input	
		}
		var switchOption = (id_input||this.input_id) ? true : false; // indique si on switch (true) ou si l'on show (false)
		var refToImage = document.getElementById('arrowSelectBox_' + refToInput.id); 		// image flèche
		var refToOptionDiv = document.getElementById('selectBoxOptions_' + refToInput.id);	// div d'options	
		
		// paramètrage de l'execution
		var tmp_display = '';
		var tmp_src = '';
		if(switchOption) // l'évènement est lancé par l'image flèche
		{
			if(refToInput.is_visible) // on masque le div d'option
			{
				tmp_display = 'none';
				tmp_src = (this.input_id) ? arrowImageOver : arrowImage; // pour ne pas fausser le rollover de l'image
			}
			else // on affiche le div d'option
			{
				var divs_option = refToOptionDiv.getElementsByTagName('DIV');
				for(var no=0;no<divs_option.length;no++) { divs_option[no].style.display='block'; }
				tmp_display = 'block';
				tmp_src = arrowImageDown;
				refToInput.focus();
			}
			refToInput.is_visible = !refToInput.is_visible;
		}
		
		if(tmp_display!=tmp_src) // si les paramètres ont été initialisés (tous les cas sauf pour le focus)
		{
			// gestion de l'image flèche "active"
			if(editableSelect_activeArrow && editableSelect_activeArrow!=refToImage){ editableSelect_activeArrow.src = arrowImage; }
			editableSelect_activeArrow = refToImage;		
			refToImage.src = tmp_src;	
			// gestion de l'affichage du div
			if(currentlyOpenedOptionBox && currentlyOpenedOptionBox!=refToOptionDiv)
			{	
				currentlyOpenedOptionBox.style.display='none';	
				document.getElementById(currentlyOpenedOptionBox.input_id).is_visible = false;	
			}
			currentlyOpenedOptionBox = refToOptionDiv;			
			refToOptionDiv.style.display=tmp_display;
		}
	}
	/****************************************************************************************************************************************/	
	function selectBox_showOptions()
	// montre le div d'option associé à l'input quand l'input est cliqué
	{ if(!this.is_visible) selectBox_switchOptions(this.id); }
	/****************************************************************************************************************************************/
	function selectBox_switchImage()
	// change l'image "flèche" du select, switch entre l'image normal et l'image "over"
	{
		var src_tmp = arrowImage.replace('../',''); // on échappe les caractères de localisation relative
		src_tmp = src_tmp.replace('./','');			// car src est en reférence absolu (donc indeOf() ne reconnait pas)
		if(this.src.indexOf(arrowImageDown.replace('./',''))==-1&&this.src.indexOf(arrowImageDown.replace('../',''))==-1) { (this.src.indexOf(src_tmp)>=0) ? this.src = arrowImageOver : this.src = arrowImage; } // si la flèche est active (image down) on ne fait rien		
	}
	/****************************************************************************************************************************************/	
	function selectBox_selectOptionValue(id_input)
	// place la value de l'option choisie dans l'input associé à liste
	{
		var refToInput; // référence sur l'input
		if(document.getElementById(id_input)) refToInput = document.getElementById(id_input); // si l'id est passé en paramètre
		else refToInput = document.getElementById(this.input_id);	// si l'évènement a lieu sur l'option
		var refToInputHidden = document.getElementById(refToInput.id+'_hidden'); // référence sur l'input caché (valeur réelle de l'option
		refToInput.value 	   = refToInput.activeOption.option_lib;
		refToInputHidden.value = refToInput.activeOption.option_value;
		selectBox_switchOptions(refToInput.id);
		refToInput.blur();
	}
	/****************************************************************************************************************************************/
	function selectBox_highlightOption(id_divToHighlight)
	// gestion du surlignage
	// la fonction peut soit etre lancé par l'élément div option lui-même (this) soit à distance en passant l'objet en paramètre
	{	
		var divToHighlight = (document.getElementById(id_divToHighlight)) ? document.getElementById(id_divToHighlight) : this;
		var refToInput = document.getElementById(divToHighlight.input_id);
		var refToOptionDiv = document.getElementById('selectBoxOptions_' + refToInput.id);	// div d'options	
		// gestion de la couleur de fond de l'élément courant
		if(refToInput.activeOption!=divToHighlight) refToInput.activeOption.className='selectBoxAnOption'; // élément précédement actif
		divToHighlight.className='selectBoxAnOptionOver';
		refToInput.activeOption = divToHighlight;
		if(refToInput.is_visible) refToInput.focus();
	}
	/****************************************************************************************************************************************/
	function selectBox_disable(car)
	// gère la désactivation du champs, autorise certaines saisies
	{
		// si la touche pressée ne correpond pas à une fonction spécial on lance le script 		
		if(car==8 || car==9 || car==13 || car==16 || car==38 || car==40 || car==127) return true; // (touche : retour arrière (supprimer), tab, entrée, majuscule, haut, bas, suppr)
		else return false;
	}
	/****************************************************************************************************************************************/
	function selectBox_specialChar(e)
	// vérifie s'il s'agit d'un caractère spécial déclenchant une fonction propre à la selectBox
	// flèche haut / bas : navigation dans la liste
	// flèche droite : complète le mot saisi avec le premier mot qui correspond (laisse le select visible)
	// touche entrée : complète le mot saisi avec le premier mot qui correspond (ferme le select)
	{
		if(window.event) var e=window.event; // on récupère l'évènement
		var car = selectBox_getCarSaisi(e); 
		
		document.getElementById(this.id+'_hidden').value = ''; // lors d'une saisie on vide la valeur sélectionné (qui n'est plus valide)
		var div_select  = document.getElementById('selectBoxOptions_'+this.id);
		var divs_option = div_select.getElementsByTagName('DIV');
		if(car==13) { if(this.activeOption!='') selectBox_selectOptionValue(this.id); return false; } // entrée : place la valeur de l'option active dans l'input
		else if((car==38 || car==40)&&divs_option.length>0) // haut / bas : change l'option active (surlignée)
		{
			var ancre = (car==38) ? 'up' : 'down';
			var ind; // indice de l'option
			if(this.activeOption=='') ind=(car==38)?0:divs_option.length-1; // valeur par défaut (extrémités de la liste)
			else
			{
				var id_split = this.activeOption.id.split('_');
				ind=stringToInt(id_split[id_split.length-1]);	// indice actuellement sélectionné				
			}
						
			if(car==38)
			{
				// on cherche l'option précédente à afficher : pour commencer on prend le div précédente
				if(ind>0) ind--; // option précédente, ind = indice de l'option
				else ind=divs_option.length-1; // haut atteint on retourne en bas
				for(var i=0; i<divs_option.length && divs_option[ind].style.display!='block'; i++, ind--) // on vérifie que le div choisi soit afficher soit on en cherche un autre
				{ if(ind==0) ind=divs_option.length; }	// haut atteint on retourne en bas
				if(ind==divs_option.length-1) ancre='down'; // si haut atteint et retour en bas on focus l'ancre du bas pour que le texte soit bien visible
			}
			else if(car==40)
			{
				// on cherche l'option suivant à afficher : pour commencer on prend le div suivant
				if(ind<divs_option.length-1) ind++; // option suivante, ind = indice de l'option
				else ind=0; // bas atteint on retourne en haut
				for(var i=0; i<divs_option.length && divs_option[ind].style.display!='block'; i++, ind++) // on vérifie que le div choisi soit afficher soit on en cherche un autre
				{ if(ind==divs_option.length-1) ind=-1; }	// bas atteint on retourne en haut
				if(ind==0) ancre='up'; // si haut atteint et retour en bas on focus l'ancre du bas pour que le texte soit bien visible				
			}
			// on s'arrete lorsqu'on trouve un div non affiché ou lorsqu'on est retombé sur l'option actuellement active
			selectBox_highlightOption(divs_option[ind].id);
			// on focus sur le div et l'option pour ajuster l'ascenseur
			divs_option[ind].focus();
			//document.getElementById(divs_option[ind].id+ancre).focus();
			this.focus(); // on retourne sur l'input pour que les touches spéciales soit toujours actives
		}
		else if(!this.is_disabled || selectBox_disable(car)) return true;
		else return false;
	}
	/****************************************************************************************************************************************/
	function selectBox_highlightAndHideFromValue(e)
	// surlignement automatique avec masquage
	{
		if(window.event) var e=window.event; // on récupère l'évènement
		var car = selectBox_getCarSaisi(e);
		if(!selectBox_disable(car)||car==8||car==127) // si la touche pressée ne correpond pas à une fonction spécial on lance le script (sauf retour arrière et suppr)
		{
			var div_select = document.getElementById('selectBoxOptions_'+this.id);
			var divs_option = div_select.getElementsByTagName('DIV');
			var nbOptions = 0; // nombre d'options affichées
			var strToCheck = (this.is_disabled) ? String.fromCharCode(car) : this.value;
			if(this.is_disabled) this.value=''; // si l'input est disabled on n'enregistre pas la saisie (seulement une selection dans la liste peut remplir l'input)
			for(var no=0;no<divs_option.length;no++)
			{
				var matched = divs_option[no].option_lib.toLowerCase().match('^'+strToCheck.toLowerCase());
				var isValid = ( matched || matched == '' ) ? true : false;		
				if(isValid)
				{
					divs_option[no].style.display='block';
					if(nbOptions == 0) selectBox_highlightOption(divs_option[no].id); // effet de surlignement sur le premier élément trouvé
					nbOptions++;
				}
				else divs_option[no].style.display='none'; // on masque les options non voulue
			}
			// résultats
			if(nbOptions==0&&this.value.length==0) // si aucune option n'a été trouvée et que l'input est vide
			{ 
				div_select.style.height=div_select.defaultHeight; // on rétablit la hauteur initiale du div
				for(var no=0;no<divs_option.length;no++) divs_option[no].style.display='block'; // on affiche toutes les options
			}
			else if(nbOptions==0&&!this.is_disabled&&this.is_visible) selectBox_switchOptions(this.id); // si la saisie est possible mais qu'aucun résultat n'est disponible, on masque la liste
			else if(nbOptions>0) // il existe des résultats
			{
				if(nbOptions<11) div_select.style.height='auto';// on ajuste la hauteur
				else if(nbOptions>30) div_select.style.height='200px';
				else div_select.style.height='150px';
				if(!this.is_visible) selectBox_switchOptions(this.id); // on affiche la liste si celle-ci est masquée 
			}
			for(var no=0;no<divs_option.length;no++) divs_option[no].style.width='auto'; // débordement : on ajuste la largeur des options pour afficher le scroll verticale sans afficher le scroll horizontal
			return true;
		}
		else return false;
	}
	/****************************************************************************************************************************************/
	function selectBox_getCarSaisi(evenement)
	// détermine la méthode utiliser par le navigateur pour gérer l'événement onKeyPress
	// et renvoie le code décimal de la touche qui a été frappée.
	{
		for (prop in evenement)							// on vérifie chaque propriété de l'evenement
		{if(prop == 'which') return(evenement.which);}  // si le navigateur utilise which, on retourne sa valeur (compatible IE)
		return(evenement.keyCode);						// sinon on retourne keyCode (compatible Netscape)
	}
	/****************************************************************************************************************************************/
	// Autres
	/****************************************************************************************************************************************/
	function stringToInt(str)
	// converti une chaine en entier, si un caractère n'est pas un chiffre il est remplacé par 0
	{
		var int=0;
		for(var i=0; i<str.length; i++)
		{
			if(i>0) int=int*10; // on rajoute un zéro à gauche
			switch(str.charAt(i))
			{
				case '0' : int+=0; break;
				case '1' : int+=1; break;
				case '2' : int+=2; break;
				case '3' : int+=3; break;
				case '4' : int+=4; break;
				case '5' : int+=5; break;
				case '6' : int+=6; break;
				case '7' : int+=7; break;
				case '8' : int+=8; break;
				case '9' : int+=9; break;
				default  : int+=0; break; // 0 remplace les caractères littéraux
			}
		}
		return int;
	}
