Liste déroulante <select> en lecture seule

Dans un formulaire HTML, il est possible de placer certains contrôles en lecture seule afin d'éviter qu'ils soient modifiés par l'usager. Par exemple, les boîtes de saisie textuelle (<input type="text"> et <textarea>) peuvent être mises en lecture seule grâce à l'attribut readonly. Ceci permet au contrôle de recevoir le focus et ne modifie pas son apparence, tout en empêchant la modification de son contenu.

Malheureusement, l'attribut readonly n'est pas disponible pour les listes déroulantes (<select>).

Je vous présente dans cet article une astuce pour simuler un readonly sur une liste déroulante.

▼Publicité

Avec une boîte de saisie textuelle, l'attribut readonly permet de placer le contrôle en lecture seule.

Ex :

HTML

<input type="text" id="codeproduit" name="codeproduit" value="CG354" readonly />

Pour une liste déroulante, puisque l'attribut readonly n'est pas disponible, il faut user d'astuce pour obtenir un résultat équivalent.

Il y a bien une possibilité avec l'attribut disabled. Cependant, avec disabled, il n'est plus possible de donner le focus au contrôle. De plus, on obtiendra une liste grisée dont l'apparence pourrait ne pas convenir à nos besoins. Et pire encore, lors du postback du formulaire, la valeur d'un contrôle disabled n'est pas retournée au serveur, ce qui complique la programmation.

Balise select avec attribut disabled

Les fonctions jQuery suivantes permettent de simuler un readonly sur une telle liste ou de la remettre dans son état original. Une fois la liste déroulante transformée en lecture seule, on aura l'impression qu'il s'agit d'un simple libellé. Le code JavaScript, PHP ou autre pourra encore travailler avec la liste déroulante mais l'usager ne saura même pas qu'il s'agissait à l'origine d'une balise <select>.

Voici donc l'apparence de la liste déroulante originale :

Liste déroulante éditable

Et voici cette même liste une fois transformée en lecture seule :

Liste déroulante en lecture seule

Pour opérer cette magie, il suffit d'un peut de jQuery et de CSS bien pensés !

jQuery

// on place le code dans une variable pour pouvoir l'assigner et le désassigner à un événement (doit avoir la même adresse mémoire)

var preventDefaultBehavior = function(e) {

   e.preventDefault();      

}

 

// Simule le readonly sur une liste déroulante en ajoutant une classe qui cache la flèche et le contour 

// et en enlevant la fonctionnalité de clic dessus

// Doit recevoir un événement en paramètre puisque sera appelé par un bind, ce qui ne permet pas de passer directement en paramètre les valeurs dont on a besoin.

// source : http://christianelagace.com

// Paramètres : événement dont le data contient :

//     - dropDownListId : ID de la balise <select> à modifier

// Retour : aucun

function rendreDDLReadOnly(e) {

    var dropDownListId = e.data.dropDownListId;

 

    // on ajoute une classe qui enlèvera l'encadré et la flèche de droite

    $("#" + dropDownListId).addClass('readonly');

 

    // on empêche la liste de s'ouvrir sur le clic (en fait, l'ouverture est programmée sur le mousedown)

    $("#" + dropDownListId).bind('mousedown', preventDefaultBehavior);

}

 

// Enlève la simulation readonly sur une liste déroulante 

// Doit recevoir un événement en paramètre puisque sera appelé par un bind, ce qui ne permet pas de passer directement en paramètre les valeurs dont on a besoin.

// source : http://christianelagace.com

// Paramètres : événement dont le data contient :

//     - dropDownListId : ID de la balise <select> à modifier

// Retour : aucun

function rendreDDLEditable(e) {

    var dropDownListId = e.data.dropDownListId;

 

    // on enlève la classe qui enlèvait l'encadré et la flèche de droite

    $("#" + dropDownListId).removeClass('readonly');

 

    // on remet le comportement par défaut sur le clic 

    $("#" + dropDownListId).unbind('mousedown', preventDefaultBehavior);

}

Et voici la classe CSS qui permet d'appliquer le style souhaité :

CSS

/* ********************************************************************* */

/* *** apparence d'un select quand on simule un readonly *************** */

/* ********************************************************************* */

select.readonly {

    -webkit-appearance: none;

    -moz-appearance: none;

    text-indent: 1px;

    border: none;

    color: #333333;

    position: relative;

    left: -2px;

}

Pour utiliser nos fonctions JavaScript :

HTML

<form>

    <p>

        <select id="voiture" name="voiture" size="1" >

            <option value="" >Veuillez choisir une voiture</option>

            <option value="2">Ford Escape</option>

            <option value="4">Honda Civic</option>

            <option value="1">Mazda 5</option>

            <option value="3">Mini Cooper</option>

            <option value="5">Toyota Matrix</option>

        </select>

    </p>

    <p><input type="button" id="boutonDDLReadOnly" value="Mettre en lecture seule" /></p>

    <p><input type="button" id="boutonDDLLEditable" value="Rendre éditable" /></p>

</form>

<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

<script>

    $(function() {

        // On aurait pu passer le onclick directement dans la balise HTML 

        // mais les bonnes pratiques veulent qu'on sépare le JavaScript du HTML

        // L'utilisation de bind() permet de passer du data en paramètre à un gestionnaire d'événement

        $('#boutonDDLReadOnly').bind('click', { dropDownListId: 'voiture' }, rendreDDLReadOnly);

        $('#boutonDDLLEditable').bind('click', { dropDownListId: 'voiture' }, rendreDDLEditable);

    });

</script>

Pour tester le tout sur jsFiddle : http://jsfiddle.net/christianelagace/b3mzfggm/

Merci de partager ! Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInPin on PinterestShare on StumbleUponEmail this to someone
Catégories