Créer un plugin jQuery : une liste déroulante personnalisée

Pierre Schwartz

Cet article va présenter la création d'un plugin pour jQuery en réalisant un widget de liste déroulante personnalisée. Il est conseillé d'être déjà à l'aise avec l'utilisation de jQuery pour aborder cet article.

Rappel : Introduction à la bibliothèque JavaScript jQuery. ♪

- Titre : Créer un plugin jQuery : une liste déroulante personnalisée

- Auteur : Pierre Schwartz

- Parution : 31 mars 2009

- Licence : Copyright ® 2009 Pierre Schwartz. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Qu'est-ce qu'un plugin jQuery ?

- II. Création d'un plugin

- II-A. Lancement

- II-B. Paramètres

- III. Réalisation d'une liste déroulante personnalisée

- III-A. Code

- III-B. CSS

- IV. Résultat, conclusion

I - Qu'est-ce qu'un plugin jQuery ?

Un plugin jQuery est un ensemble de fonctions que l'on va rajouter à l'espace de noms de jQuery de manière à enrichir les possibilités du framework. De nombreux plugins existent déjà (la page des plugins jQuery), qu'il s'agisse de créer de nouveaux widgets, de rajouter des fonctions aux opérations de base de jQuery ou de créer de nouveaux comportements. Un plugin est avant tout une fonction qui sera appelable sur un objet jQuery, il sera composé d'une fonction publique et de plusieurs fonctions privées incluses dans la fonction publique.

Dans sa structure, jQuery est fait pour que tout le monde puisse y rajouter facilement des plugins. Un espace de noms est dédié aux plugins : $.fn. Chaque plugin que vous rajouterez est censé se trouver à cet endroit. En créant du contenu dans $.fn.exemple(paramètres), votre plugin sera appelable directement par jQuery.exemple(paramètres). Un plugin sera appliqué sur un objet jQuery, provenant par exemple d'une recherche dans le DOM de la page et possèdera des paramètres, indiqués par le développeur.

II - Création d'un plugin

II-A - Lancement

Pour créer un plugin il suffit en théorie de créer une fonction dans $.fn. On peut considérer cette fonction comme le constructeur de votre plugin, récupérant tous les paramètres et faisant le traitement propre au plugin, positionnant les évènements, etc.

(function($) {
// définition du plugin
$.fn.exemple = function() {
alert('hello world');
return $(this);
};
})(jQuery);

Ce plugin minimaliste affichera « hello world » chaque fois qu'il sera appelé.

<div>a</div><div>b</div><script type="text/javascript">$("div").exemple();</script>

Ce code lancera deux fois le plugin exemple, une fois sur chaque élément div.

On pensera à toujours renvoyer un objet jQuery de manière à conserver une interface fluide.

II-B - Paramètres

Les paramètres sont faits pour être passés sous forme JSON, cela offre entre autres la possibilité de définir des paramètres facultatifs. Le principe est de définir un jeu de paramètres par défaut. jQuery prendra ces paramètres lorsqu'ils ne seront pas définis dans l'entrée JSON.

(function($) {
$.fn.exemple = function(options) {
var defaults = {
title: "",
selectEvent: null
};

var opts = $.extend(defaults, options);

return $(this);
};
})(jQuery);

La fonction $.extend se charge de récupérer les paramètres par défaut si ces paramètres ne sont pas fournis à la fonction. En passant « options » à notre fonction de plugin, puis en récupérant les paramètres effectifs via $.extend, on obtient un second jeu de paramètres noté opts dans le code. C'est ce jeu de paramètres qu'il conviendra d'utiliser tout au long de notre plugin.

III - Réalisation d'une liste déroulante personnalisée

Je choisis de me baser sur une liste HTML composée de balises ul et li puis de la transformer en une liste déroulante composée d'une zone affichant l'option sélectionnée puis d'une zone dite déroulante proposant toutes les options de la liste.

Le plugin s'appellera directement sur les éléments ul : $(« ul »).customDropDown(); L'utilisateur pourra paramétrer le texte affiché à la création de la liste, quand aucune option n'est encore sélectionnée, ainsi qu'une fonction personnalisée à appeler à chaque sélection d'option. Ces deux paramètres sont notés title et selectEvent.

Nous ne savons pas sur combien d'objets jQuery le plugin sera appelé, il faudra donc penser en premier lieu à séparer tous les éléments <ul> pour créer une liste déroulante sur chacun.

Le principe de la transformation de la liste est le suivant :

- on crée une zone affichant l'option sélectionnée ;

- on crée une zone contenant tous les éléments <li> de la liste ;

- on positionne un évènement clic sur chaque élément sélectionnable de manière à le reporter dans la première zone ;

- on met en place un attribut value permettant de récupérer simplement l'option choisie.

Si vous placez une telle liste déroulante dans un formulaire, sa valeur ne sera pas envoyée lors de la soumission du formulaire. Pour cela vous allez devoir créer un élément <input type=« hidden »/> avec la valeur de l'élément sélectionné.

Le clic sur la première zone servira à dérouler et enrouler la liste selon qu'elle est déjà déroulée ou non. Nous aurons besoin de stocker un booléen représentant cet état. J'ai choisi de le stocker dans $.data. Notez qu'on aurait pu stocker cette information directement dans le DOM mais le stockage dans une structure de données découplée du DOM est plus propre.

III-A - Code

(function($) {
//Définition du plugin
$.fn.imgDropDown = function(options) {

// définition des paramètres par défaut
var defaults = {
title: "",
selectEvent: null
};
// mélange des paramètres fournis et des paramètres par défaut
var opts = $.extend(defaults, options);

// création d'une liste
function createList(f){
// créer la première zone, affichant l'option sélectionnée
var cell = $('<div class="dropdownCell">' + opts.title + '</div>');

// créer la seconde zone, affichant toutes les options
var dropdown = $('<div class="dropdownPanel"></div>');

$(this).find("li").each(function(){
dropdown.append($('<div class="dropdownOpt"></div>')
.click(onSelect)
.attr("value", $(this).attr("value"))
.append($(this).html())
.hover(function(){$(this).addClass("dropdownOptSelected");},
function(){$(this).removeClass("dropdownOptSelected");})
);
});

// on masque la zone déroulante
dropdown.hide();
$.data(cell, "visible", false);

// on remplace la balise ul par notre liste personnalisée
$(this).after(dropdown);
$(this).after(cell);
$(this).remove();

// on positionne l'évènement de déroulage de la liste
cell.click(function(){
// si la liste est déroulée
if ($.data(cell, "visible")){
dropdown.slideUp("fast");
$.data(cell, "visible", false);
}else{
dropdown.slideDown("fast");
$.data(cell, "visible", true);
}
});

// fonction appelée à chaque sélection d'un élément
function onSelect(){
cell.html($(this).html());
cell.attr("value", $(this).attr("value"));
dropdown.slideUp("fast");

$.data(cell, "visible", false);

// appel d'une fonction personnalisée
if (opts.selectEvent)
opts.selectEvent($(this));
}
}

// création d'une liste déroulante personnalisée pour tous les éléments de l'objet jQuery
$(this).each(createList);

// interface fluide
return $(this);
};
})(jQuery);

Voici un exemple d'appel :

<ul>
<li value="1"><img src="germany.png" alt="Allemagne" />Allemagne</li>
<li value="2"><img src="belgium.png" alt="Belgique" />Belgique</li>
<li value="3"><img src="spain.png" alt="Espagne" />Espagne</li>
<li value="4"><img src="france.png" alt="France" />France</li>
<li value="5"><img src="italy.png" alt="Italie" />Italie</li>
<li value="6"><img src="switzerland.png" alt="Suisse" />Suisse</li>
</ul>

<script type="text/javascript">
function f(){
alert('clic');
}

$("ul").customDropDown({title:"Pays", selectEvent:f});
</script>

L'attribut value des éléments <li> sera repris dans la zone personnalisée, il conviendra donc de penser à le renseigner.

III-B - CSS

Aucun style n'est défini dans le plugin, uniquement des classes CSS : dropdownCell, dropdownPanel, dropdownOpt et dropdownOptSelected. Voici un exemple de style qui ne rend pas trop mal :

/* la zone affichant l'option sélectionnée */
.dropdownCell{
border : 1px solid #bbb;
width: 150px;
height: 23px;
cursor: pointer;
font-family: arial;
font-size: 10pt;
max-height: 23px;
background: transparent url('arrow.gif') right top no-repeat;
}

.dropdownCell img{
margin : 0px 3px 0px 3px;
vertical-align: middle;
width: 24px;
}

.dropdownPanel{
border : 1px solid #bbb;
width: 150px;
position: absolute;
}

.dropdownOpt{
background-color: #fff;
cursor: pointer;
font-family: arial;
font-size: 10pt;
}

.dropdownOpt img{
margin : 0px 3px 0px 3px;
vertical-align: middle;
width: 24px;
}

.dropdownOptSelected{
background-color: #ccc;
}

IV - Résultat, conclusion

Voici une démonstration de ce que vous pouvez obtenir . N'hésitez pas à modifier le style si vos éléments de liste ne sont pas tous similaires.

Télécharger le code source de ce plugin

Merci à l'équipe de la rubrique JavaScript de developpez.com pour sa relecture et ses remarques toujours aussi pertinentes.