function multiselect(aSel) {
	this.selectbox = aSel;	// listebox
	this.nb = aSel.length;	// nb de liste (profondeur)
	this.liste = [];		// arboresence
	this.defaut = new Array(this.nb);	// valeur par defaut
	this.memo_profondeur = { niveau: 0, idp: 0 };	// profondeur

	// mémorise et retourne dans quelle profondeur de l'arbo on se trouve
	this.profondeur = function(idp) {
		var bTrouve = false;
		if(idp > 0) {
			if (this.memo_profondeur.idp != idp) {
				this.memo_profondeur.niveau = this.est_au_niveau(idp, 0);
				this.memo_profondeur.idp = idp;
			}
		}
		else {
			this.memo_profondeur.idp = 0;
			this.memo_profondeur.niveau = 0;
		}

		return this.memo_profondeur.niveau;
	};

	// compte à quel niveau se trouvre un noeud (récusive)
	this.est_au_niveau = function(idp, iNiveau) {
		var bParent = false;
		if (idp > 0) {
			for (var i=0; i<this.liste.length; i++) {
				if (this.liste[i].id == idp) {
					iNiveau++;
					idp = this.liste[i].idp;
					bParent = true;
					break;
				}
			}
		}
		return bParent ? this.est_au_niveau(idp, iNiveau) : iNiveau;
	};

	this.valeur_par_defaut = function(iListe, valDefaut) {
		this.defaut[iListe - 1] = valDefaut;
	};

	// retourne la valeur id de la selection d'une liste
	this.est_selectionne = function(liste) {
		// TODO : revoir tout l'algo sur un array liste[n][n] au lieu d'un tableau listant tous les niveau
		// basé sur la valeur, donc si 2 valeurs identiques sur un même niveau (même de branches différentes) = bug
		//var iSelection = this.selectbox[liste].selectedIndex;
		var sValue = this.selectbox[liste].value;
		
		var id = 0, cpt = 1;
		for(var i=0;i<this.liste.length;i++) {
			oliste = this.liste[i];			
			if (oliste.profondeur == liste && sValue == oliste.valeur ) {				
					id = oliste.id;
				cpt++;
			}
		}		
		return id;
	}

	// ajoute un noeud à l'arbo
	this.add = function(id, idp, texte, valeur) {
		valeur = valeur != "" ? valeur : texte;
		var prof = this.profondeur(idp);
		this.liste[this.liste.length] = {
			profondeur: prof,
			id: id,
			idp: idp,
			texte: texte,
			valeur: valeur,
			defaut: (this.defaut[prof] == valeur)
		};
	};

	// initialise
	this.init = function() {
		var oliste, cpt = 1;

		// remplit la première liste uniquement
		for(var i=0;i<this.liste.length;i++) {
			oliste = this.liste[i];
			if (oliste.profondeur == 0) {
				this.selectbox[0].options[cpt++] = new Option(oliste.texte, oliste.valeur); //, oliste.defaut, oliste.defaut);
				if (oliste.defaut) this.selectbox[0].selectedIndex = cpt-1; // @#$ IE6
			}
		}

		// événements sur les listes
		for (var i = 0;i < this.nb; i++) {		
			this.selectbox[i].instance = this;
			this.selectbox[i].liste = i + 1;			
			this.selectbox[i].onchange = function() {
				this.instance.change(this.liste);
			}
		}
	};

	// garde la premi�re valeur (choississez, tous...)
	// cpt = 1
	this.raz = function(oSel) {
		var aSave = [oSel.options[0].text, oSel.options[0].value];
		oSel.options.length = 0;
		oSel.options[0] = new Option(aSave[0], aSave[1], true, true);
	};
	
	// change les listes en cascades
	this.change = function(liste) {
		var oliste, cpt, iSelection;
		for (var i = liste;i < this.nb; i++) {		
			cpt = 1;
			iSelection = this.est_selectionne(i - 1);	
			this.raz(this.selectbox[i]);
			
			for(var j=0;j<this.liste.length;j++) {
				oliste = this.liste[j];	

				if (oliste.profondeur == i && oliste.idp == iSelection) {
					this.selectbox[i].options[cpt++] = new Option(oliste.texte, oliste.valeur); //, oliste.defaut, oliste.defaut);
					if (oliste.defaut) this.selectbox[i].selectedIndex = cpt-1; // @#$ IE6
				}
			}
		}
	};
	
	this.selectionner= function(iListe, sVal) {
		var oLst = this.selectbox[iListe -1];		
		for(var i=0;i<oLst.options.length;i++) {		
			if (oLst.options[i].value == sVal) {
				oLst.selectedIndex = i;		
				this.change(iListe);
				break;
			}
		}
	};
}
