Select multiple avec checkboxes
17 février 2008 par zero-zombie

Voilà un script destiné à répondre à une problématique assez courante : comment faire une sélection multiple qui ne prenne pas beaucoup de place à l’écran et qui soit simple à utiliser ?
<select id="select_artistes" name="artistes"> <option checked="checked" value="pj">Harvey</option> <option value="jimi">Hendrix</option> <option checked="checked" value="maurice">Ravel</option> </select>
vous pourrez créer votre MSC en ajoutant juste en-dessous :
<script type="text/javascript"> ma_msc = MultipleSelectCheck("ma_msc"); ma_msc.create("artistes", "select_artistes", "MSCartistes", "obj_MSC_artistes"); </script>
Les quatre paramètres sont :
- Le nom de la select
- L’ID de la select
- Le nom de la MSC à créer
- L’ID de la MSC à créer
Vous obtiendrez ainsi une fausse liste multiple avec des checkboxes. En prime, la liste des éléments sélectionnés s’affiche sous cette liste.
Il est utile de nommer la MSC avec un nom différent de celiui de la select. Ainsi, on peut savoir si l’utilisateur fonctionnait en mode dégradé (sans javascript, select simple avec sélection unique) ou non.
Dans l’exemple précédent, si à l’envoi du formulaire le serveur reçoit MSCartistes, on peut avoir une sélection multiple. Dans le cas contraire, elle est forcément unique.
En parlant du serveur : que reçoit-il quand plusieurs sélections sont cochées ?
Eh bien la liste des valeurs sélectionnées, séparées par des virgules. Par exemple : 10,50,158
Comme on peut vouloir un autre séparateur, il est possible de le définir. De même, on peut choisir le séparateur de la liste des valeurs sélectionnées qui s’affiche à l’écran. Par défaut, c’est une virgule, mais on peut souhaiter avoir un <br />, par exemple.
Comme on peut éventuellement avoir besoin d’un switch qui coche/décoche toutes les options proposées. Ca tombe bien, il y en a un dans MSC, qui s’appelle GlobalSwitch.
Une méthode permet de l’ajouter en début de liste; elle prend en compte trois paramètres : le libellé du switch (ce qui s’affiche dans la liste), la valeur du switch (voir ci-dessous), et un booléen permettant de spécifier si toutes les cases doivent être cochées.
Dans le cas où toutes les options sont cochées, la première valeur des valeurs retournées est la valeur du switch (le deuxième paramètre).
<script type="text/javascript"> test2 = new MultipleSelectCheckbox("test2"); // séparateur pour les paramètres quienvoyés au serveur test2.URLSeparator = "-"; // séparateur pour l'affichage des éléments sélectionnés, sous la combo test2.visualSeparator = " <i>(and)</i> "; // ajoute une première option permettant de tout cocher/décocher test2.addGlobalSwitch("Tout sélectionner/désélectionner", "__global", true); test2.create("artistes", "select_artistes", "MSCartistes", "MSCselect_artistes"); </script>
Si on applique cette MSC à la select du premier exemple, et si on coche "Tout sélectionner"… on recevra coté serveur : __global,pj,jimi,maurice
A vous de voir ce que vous voulez en faire coté serveur : détecter la présence de votre valeur globale et la traiter comme cas particulier, considérer que seule la liste compte et ignorer cette valeur globale, ou bien tout conserver pour savoir ce qui était coché quand la valeur globale a été envoyée si la liste est vouée à évoluer.
Télécharger MSC v0.1


Merci pour cet excellent outil. Mis en production sur le back office d’un client, cela fonctionne parfaitement.
Une remarque cependant : lorsque tu veux récupérer les options déjà choisies pour cocher les bonnes cases par défaut, pourquoi détecter l’attribut “checked” et non pas “selected” ? “checked” est utilisé pour les input de type checkbox, mais pour les input de type select, c’est “selected” qui est employé.
Ne voulant pas modifier tous mes select, j’ai modifié votre script à la ligne 164 :
currentChecked = currentOption.getAttribute(’checked’) != null;
devient :
currentChecked = currentOption.getAttribute(’selected’) != null;
Parce que c’est sensé modifier une select simple et qu’il est illogique d’avoir plusieurs options avec l’attribut selected=”selected” dans ce cas.
A vérifier de toute façon avec tous les navigateurs… ça ne m’étonnerait pas que l’un ou l’autre ne conserve que le premier ou le dernier selected, ce qui faussera la récupération des données.
Au moins, checked c’est neutre dans le cas d’une select, et ça a du sens puisque c’est pour le rendu de checkboxes.
Dans le cas d’un select portant l’attribut “multiple”, ce sont aussi des “selected” qui caractérisent les options sélectionnées, les navigateurs acceptent donc bien plusieurs selected pour un même input de type select.
Oui… dans le cas d’un multiple.
C’est tout le problème de faire des composants génériques : on a toujours beaucoup de mal à satisfaire tous les cas possibles.
Je suis parti du cas où on veut offrir plusieurs choix si JS est activé, et un seul si JS est désactivé. Ca sert à améliorer l’”expérience utilisateur” quand on a un select simple, pas à offrir une visualisation différente d’un select multiple, en tout cas c’est dans cette optique que je l’ai conçu.
Mais si ça te va bien avec ta modif, c’est le principal
Du moment que ça te fait gagner du temps et t’évite de coder des choses pas vraiment passionnantes et te retaper tous ces p*tains de tests sous IE, Safari, Firefox et consorts, ça me fait plaisir
Rassure-toi cela n’enlève rien à la qualité de ton travail et au secours qu’il m’a apporté !
Jusque là je proposais justement soit un select multiple (contraignant à cause du Ctrl+clic) soit un ensemble de checkboxes (contraignant pour la place que cela prend sur la page), et quand j’ai lu la description de ton script, j’ai tout de suite pensé qu’il offrait justement un moyen idéal de concilier les avantages des deux méthodes sans les inconvénients cités, mais qu’en cas de dégradation (JS désactivé), il restait possible de sélectionner plusieurs choix, qu’on retombait donc sur un simple select multiple.
Encore merci pour l’effort et bonne continuation.
C’est bien sympa le select avec checkbox. Mais peut-on détruire et recréer dynamiquement l’objet MSC à partir du code js ?
Il y a un problème avec ie6.
Si il y a des menu déroulant sous la liste alors ces menus s’affichent au dessus de la liste.
Avez vous une solution ?
C’est un problème d’IE6 : tout sélect passe à travers les divs.
Ma solution, c’est de se fiche d’IE6 et de laisser ses bugs et lacunes apparaître pour motiver ses utilisateurs à changer de navigateur.
D’autres décident de prendre en charge ce navigateur et mettent en place des solutions techniques comme http://www.fabien-molinet.fr/index.php?option=com_content&task=view&id=22
En fait il y a deux écoles, si je me souviens bien : soit on cache les selects qui sont recouvertes par un div, soit on remplace les div par des iFrame, qui sont prioritaires sur les select.