Pour avoir plusieurs éléments <select> liés et les afficher au fur et à mesure, on peut :
- soit recharger la page en cours pour la ré-afficher avec la liste suivante
- soit jouer sur les propriétés css display ou visibility pour afficher/masquer les select qui sont alors tous présents dans la page
- soit les générer au fur et à mesure en javascript
La fonction suivante se propose de générer les différents select au fur et à mesure en javascript et de supprimer les éléments créés si l'on modifie les choix faits dans les listes précédentes.
La base d'utilisation de cette fonction est un tableau à dimensions multiples en javascript regroupant toutes les listes qui pourront exister dans la page. A chaque fois une nouvelle liste précédée de l'élément qui l'appellera :
list_choix = {
"amstramgram" : ["am", "stram", "gram"],
"pifpafpoum" : ["pif", "paf", "poum"],
"tictac" : ["tic", "tac"],
"pif" : ["chien", "gadget"],
"gram" : ["kilo", "tonne", "livre"],
"paf" : ["aie", "ouille"],
"tac" : ["ding", "dong"]
}
La première liste sera déclarée directement dans le code html et toutes les listes seront regroupées dans un même élément pour y accéder plus facilement, ici un <fieldset> :
<fieldset>
<select name="choix1" id="choix1" onchange="ajout(this)">
<option value="amstramgram">amstramgram</option>
<option value="pifpafpoum">pifpafpoum</option>
<option value="tictac">tictac</option>
</select>
</fieldset>
Une première fonction créée qui se basait exclusivement sur des fonctions DOM ne fonctionne malheureusement pas sous Internet Explorer qui gère de façon assez étrange et aléatoire la fonction setAtttribute(), cette fonction sera d'ailleurs certainement le sujet d'un prochain article.
Voici tout de même cette fonction qui est compatible mozilla, netscape, opéra mais pas internet explorer :
function ajout(selection){
nb_select = selection.parentNode.getElementsByTagName("select").length;
if ( selection == selection.parentNode.getElementsByTagName("select")[nb_select-1] ) {
element_select = selection;
selection = selection.options[selection.selectedIndex].value;
if ( list_choix[selection] ) {
new_liste = document.createElement("select");
element_select.parentNode.appendChild(new_liste);
new_liste.setAttribute("id", "choix"+nb_select);
new_liste.setAttribute("name", "choix"+nb_select);
new_liste.setAttribute("onchange", "ajout(this)");
for (var i=0; i<list_choix[selection].length; i++) {
new_option = document.createElement("option");
new_liste.appendChild(new_option);
new_option.setAttribute("value", list_choix[selection][i]);
new_option.text = list_choix[selection][i];
}
}
}
else {
selection.parentNode.removeChild(selection.nextSibling);
ajout(selection)
}
}
page d'exemple
Pour pouvoir être compatible internet explorer, il a donc fallut supprimer tous les setAttribute() et cibler directement avec new_element.id="toto" plutôt que new_element.setAttribute("id","toto")
Pour ajouter le onchange() par contre, il faut passer par outerHTML afin de récrire complètement la balise, new_element.onchange=fonction ne permettant pas le passage de paramètres.
La fonction compatible internet explorer, mozilla, opéra, netscape donne alors ceci :
function ajout(selection){
nb_select = selection.parentNode.getElementsByTagName("select").length;
if ( selection == selection.parentNode.getElementsByTagName("select")[nb_select-1] ) {
element_select = selection;
selection = selection.options[selection.selectedIndex].value;
if ( list_choix[selection] ) {
new_liste = document.createElement("select");
truc = element_select.parentNode.appendChild(new_liste);
if ( document.all) {
new_liste.outerHTML = "<select id="choix"+nb_select+"" name="choix"+nb_select+"" onchange="ajout(this)"></select>";
}
else {
new_liste.setAttribute("id", "choix"+nb_select);
new_liste.setAttribute("name", "choix"+nb_select);
new_liste.setAttribute("onchange", "ajout(this)");
}
for (var i=0; i<list_choix[selection].length; i++) {
new_option = document.createElement("option");
document.getElementById("choix"+nb_select).appendChild(new_option);
new_option.value = list_choix[selection][i];
new_option.text = list_choix[selection][i];
}
}
}
else {
selection.parentNode.removeChild(selection.nextSibling);
ajout(selection)
}
}
page d'exemple
EDIT : modification et amélirations de la fonction sur ce billet
Bienvue, mais personnellement, a cause IE comme tu l'a souligné, j'évite l'utilisation de setAttribute() et je "créer" mes attributs directement sous forme de variables attachées en JavaScipt :
new_liste.id = "choix"+nb_select;
new_liste.name = "choix"+nb_select;
new_liste.onchange = function () { ajout(this) }
Cette méthode n'est pas respectueuse de l'utilisation du DOM, mais elle à le mérite de fonctionner avec tous les navigateurs que j'ai testés jusqu'à présent.
arf oui, j'y pense jamais à faire comme ca
mais c'est mieux
Commentaires momentanément fermés. Merci de votre compréhension.