Création d'un plugin jQuery

Si vous êtes là, c'est que vous avez surement déjà entendu parler de jQuery. jQuery est un framework javascript mettant à notre disposition une foule de fonctions permettant d'utiliser javascript beaucoup plus facilement. L'objet de ce tutoriel est la création d'un plugin pour ce framework. On peut penser que c'est une tâche difficile mais ce n'est pas le cas. Vous verrez dans ce tutoriel comment créer un plugin basique pour jQuery.


Les plugins jQuery ont tous en commun une structure. Cette structure, une fois mise en place vous permettra de créer n'mporte quel plugin. Cette structure, la voici :

(function($) {

    // Objet contenant les options par défaut
    $.sxnDemoPlugin = {

        defaults: {

        }

    };

    // On ajoute notre plugin à jQuery
    $.fn.extend({

        // Fonction principale de notre plugin
        sxnDemoPlugin:function(config) {

            // On fusionne les options par defaut avec les options de l'utilisateur
            var config = $.extend({}, $.sxnDemoPlugin.defaults, config);

            /*** Code du plugin ***/            

            // On retourne this afin de pouvoir appeler d'autres fonctions en chaîne après notre plugin
            // Exemple : $('#some_id').show().sxnDemoPlugin().css('color', 'red');
            return this;

        }

    });

)(jQuery);

Le code de notre plugin est encadré par une fonction anonyme prenant en paramètre le symbole $. Ce symbole représente jQuery. Nous ajoutons ensuite un objet à la collection d'objets de jQuery. Donnez le nom de votre plugin à cet objet. Ce n'est pas obligatoire mais c'est plus simple ainsi. Cet objet en contient un deuxième appelé defaults. Là encore, vous pouvez lui donner le nom que vous souhaitez mais comme cet objet contiendra les options par défaut de notre plugin, s'il en possède, defaults est tout à fait aproprié.

Nous appelons ensuite la méthode $.fn.extend() de jQuery qui nous permet d'intégrer notre plugin aux autres fonctions déjà existentes de jQuery. Cette fonction contiendra ensuite au moins une fonction, la fonction principale de notre plugin. Vous donnerez à cette fonction le nom de votre plugin puisque c'est cette fonction que l'utilisateur de votre plugin appellera. Libre à vous de faire d'autres fonctions si besoin en est. Vous pouvez également faire des fonctions que votre fonction principale appellera. Votre fonction principale prend en paramètre la variable config qui représente un objet contenant les options que l'utilisateur à précisé. Cet objet peut être vide si votre plugin ne comprend aucune option.

Nous définissons ensuite la variable config qui fait appel à la fonction $.extend() (a ne pas confondre avec $.fn.extend()). Cette fonction sert à fusionner plusieurs objets entre eux pour en former un seul, elle prend 3 paramètres.

Le premier paramètre est l'objet qui contiendra toutes les propriétés des objets fusionnés.

Le second paramètre est l'objet avec les propriétés par défauts, c'est à dire que si l'autre objet que l'on va fusionner avec celui-ci contient les mêmes propriétés, celles du premier objet seront remplacées par celles du second. Dans notre cas, on passe au second paramètre notre objet $.sxnDemoplugin.defaults qui contient la liste de nos options par défaut.

Le troisième paramètre contient l'objet qu'on va fusionner avec le premier. Ici, cet objet contient les options que l'utilisateur du plugin à défini et qui viendront écraser les propriétés par défaut de notre plugin contenu dans $.sxnDemoPlugin.defaults. Ici, on passe la variable config en paramètre.

Enfin, nous pouvons écrire le code de la fonction principale de notre plugin. Une fois le code de la fonction écrit, on retourne l'objet jQuery afin que d'autres fonctions puissent être appelées en chaîne après notre plugin.

Et voilà, c'est tout pour la structure d'un plugin jQuery. On va maintenant pouvoir passer à la création d'un vrai plugin.

Passons à la conception de notre plugin. Celui ci proposera d'afficher un texte ou une image au survorl d'un lien ou de n'importe quel autre élément avec le souris. Pour garder notre plugin basique, celui-ci affichera soit du texte soit une image.

Survol avec la souris

Pour ce faire, créer un fichier HTML, index.html par exemple. Dans ce fichier, écrivez du texte ou ce que vous souhaitez. Voici le contenu de mon fichier.

<quote>
  En informatique, un <a href="#" rel="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." class="target">plugin</a> ou plug-in (aussi nommé module d'extension, greffon ou plugiciel au Québec) est un logiciel qui complète un logiciel hôte pour lui apporter de nouvelles fonctionnalités.

  Le terme plugin provient de la métaphore de la <a href="#" rel="sxnImage__assets/img/prise.jpg" class="target2">prise électrique</a> standardisée et désigne une extension prévue des fonctionnalités, en comparaison des ajouts non prévus initialement apportés à l'aide de correctifs (patchs).

    La plupart du temps, ces programmes sont caractérisés de la façon suivante :
  <ul style="margin-left:20px;">
    <li>ils ne peuvent fonctionner seuls car ils sont uniquement destinés à apporter une fonctionnalité à un ou plusieurs logiciels.</li>
    <li>ils sont mis au point par des personnes n'ayant pas nécessairement de relation avec les auteurs du logiciel principal.</li>
  </ul>
</quote>

Vous pouvez voir 2 liens dans mon paragraphe : plugin et prise électrique.

La différence entre l'affichage d'une image et d'un texte est dans l'attribut rel. Cet attribut contient, par défaut, le texte ou l'image que l'on souhaite afficher au survol de l'élément. Pour un texte, écrivez simplement votre texte dans l'attribut et pour une image, écrivez sxnImage:addresse/de/limage.jpg.

De cette façon, notre plugin pourra faire la différence entre une image et un texte.

Passons maintenant à la conception du dit plugin. Ce dernier s'appellera sxnDemoPlugin. Créez donc le fichier jquery.sxndemoplugin.js et insérez y la structure de base d'un plugin que nous avons vu dans le chapitre précédent.

Intéressons nous aux options par défaut dans un premier temps. Comme ce plugin est basique, nous n'aurons besoin que d'une seule option spécifiant l'attribut sur lequel on va récupérer les données à afficher.

$.sxnDemoPlugin = {

    defaults: {
        attr: 'rel'
    }

};

Notre plugin ira donc par défaut récupérer les données dans l'attribut rel de la cible du plugin. Comme c'est une option, l'utilisateur du plugin pourra décider d'aller récupérer ces données dans l'attribut href ou id de l'élément cible s'il le souhaite.

Nous allons pouvoir commencer à écrire le code de notre plugin. A la place de /*** Code du plugin ***/, écrivez ceci :

var $this = $(this);

$(this) désigne l'élément sur lequel travaille la fonction dans lequel on l'utilise. Ici, j'affecte cette valeur à $this afin de mieux différencier l'élément principal sur lequel s'applique notre fonction principale. Vous verrez que ça a un intérêt dans le suite.

Comme il est fortement probable que l'utilisateur définisse plusieurs cibles au plugin, nous allons traiter chacune de ces cibles grâce à la fonction each() de jQuery. Le fait d'avoir passé le jQuery via $ au tout début de notre fichier nous donne accès à toutes les fonctions déjà existentes de jQuery.

$this.each(function() {
    // On passe en revue chacun des éléments cible
});

On souhaite que chaque élément cible fasse apparaître une boîte avec des données lors de son survol. Ils nous faut donc une fonction capable de détecter le survol de la souris sur l'élément cible. Il y a bien entendu mouseover() mais je préfère utiliser hover() car cette fonction peut prendre deux paramètre : une fonction à appeller lorsque la souris est sur l'élément cible et une fonction à appeller lorsque la souris quitte l'élément cible.

On a donc ceci :

$this.each(function() {

    $(this).hover(

        function(e) {
            // La souris est sur l'élément
        },
        function() {
            // La souris n'est plus sur l'élément
        }

    );

});

Ici, j'utilise de nouveau $(this) qui fait référence à l'élément sur lequel s'applique la fonction hover(). En résumé, voici les 3 "this" que notre plugin contient.

  • $this : la cible sur laquelle s'applique notre plugin
  • $(this) : la cible sur laquelle s'applique la fonction dans laquelle $(this) est utilisé
  • this : l'objet jQuery

La fonction appellée lorsque la souris est sur la cible prend un paramètre que j'ai appelé e. Ce paramètre réprésent un objet contenant des informations sur l'évènement déclenché. Il contient entre autre 2 informations dont nous aurons besoin : e.pageX (coordonnée horizontale en pixels de l'endroit où se trouvait le pointeur de la souris) et e.pageY (coordonnée verticale en pixels de l'endroit où se trouvait le pointeur de la souris).

On va maintenant récupérer les données que contient l'attribut de la cible.

$this.each(function() {

    $(this).hover(

        function(e) {
            var data = $(this).attr(config.attr);
        },
        function() {
            // La souris n'est plus sur l'élément
        }

    );

});

L'attribut contenant nos données est dans l'objet contenant les options de notre plugin. Si les options par défaut ont été conservées, l'attribut est alors rel. La variable data contiendra donc les données. Nous allons maintenant analyser ces données pour savoir s'il s'agit d'un texte ou d'une image.

$(this).hover(

    function(e) {
        var data = $(this).attr(config.attr);

        if (data.indexOf('sxnImage__') != -1) {
            var datas = data.split('__');
            var img = datas[1];
            var box = '<div id="sxnBox"><img src="' + img + '" alt="Chargement..." /></div>';
        }
        else {
            var box = '<div id="sxnBox">' + data + '</div>';
        }
    },
    function() {
        // La souris n'est plus sur l'élément
    }

);

On utilise la fonction indexOf() qui va vérifier si data contient sxnImage_. Cette fonction retourne -1 si la chaîne de caractères passée en paramètre n'est pas trouvée. Si on doit afficher une image, il faut retirer sxnImage: de nos données pour ne conserver que l'adresse de l'image. On utilise la fonction split() à cet effet. Cette dernière va couper la chaîne de caractères à chaque fois qu'elle rencontrera les caractères _. Elle retourne un tableau contenant sxnImage et l'adresse de notre image. On recupère juste l'adresse et on la place dans la variable box qui contient le code HTML de notre boîte.

Si on ne veut afficher que du texte, c'est plus simple car on a juste à l'insérer dans le code HTML.

function(e) {
    var data = $(this).attr(config.attr);

    if (data.indexOf('sxnImage__') != -1) {
        var datas = data.split('__');
        var img = datas[1];
        var box = '<div id="sxnBox"><img src="' + img + '" alt="Chargement..." /></div>';
    }
    else {
        var box = '<div id="sxnBox">' + data + '</div>';
    }

    $('body').append(box);
    $('#sxnBox').css('left', e.pageX + 20).css('top', e.pageY - 10);

},
function() {
    // La souris n'est plus sur l'élément
}

Il nous reste juste à afficher la boîte en l'insérant dans le DOM. On lui applique ensuite deux propriétés CSS : left et top afin que notre boîte se positionne 10 pixels au-dessus de la souris et 20 pixels à droite de la souris.

Maintenant, nous devons supprimer la boîte lorsque l'utilisateur n'a plus sa souris sur la cible car sinon, la page va vite devenir un beau bordel.

function(e) {
    var data = $(this).attr(config.attr);

    if (data.indexOf('sxnImage__') != -1) {
        var datas = data.split('__');
        var img = datas[1];
        var box = '<div id="sxnBox"><img src="' + img + '" alt="Chargement..." /></div>';
    }
    else {
        var box = '<div id="sxnBox">' + data + '</div>';
    }

    $('body').append(box);
    $('#sxnBox').css('left', e.pageX + 20).css('top', e.pageY - 10);

},
function() {
    $('#sxnBox').remove();
}

Dans l'état actuel, le plugin est fonctionnel, lorsque la souris passe sur une des cibles la boîte s'affiche mais quelque chose va surement vous choquer. La boîte ne suit pas les déplacements de la souris et c'est assez désagréable. Nous allons donc tout de suite remédier à ce problème.

$this.each(function() {

    $(this).hover(
        function(e) {

            // On recupère le texte contenu dans l'attribut defini dans les options
            var data = $(this).attr(config.attr);

            if (data.indexOf('sxnImage__') != -1) {
                var datas = data.split('__');
                var img = datas[1];
                var box = '<div id="sxnBox"><img src="' + img + '" alt="Chargement..." /></div>';
            }
            else {
                var box = '<div id="sxnBox">' + data + '</div>';
            }

            $('body').append(box);
            $('#sxnBox').css('left', e.pageX + 20).css('top', e.pageY - 20);


        },
        function() {

            $('#sxnBox').remove();

        }
    );

    $(this).mousemove(function(e) {

        $('#sxnBox').css('left', e.pageX + 20).css('top', e.pageY - 20);

    });

});

La fonction mousemove() est appellée à chaque fois que la souris bouge, nous pouvons donc mettre à jour la position de la boîte en fonction des mouvements de la souris.

Voici le code complet du plugin.

(function($) {

    // Objet contenant les options par défaut
    $.sxnDemoPlugin = {

        defaults: {
            attr : 'rel'
        }

    };

    // On ajoute notre plugin à jQuery
    $.fn.extend({

        // Fonction principale de notre plugin
        sxnDemoPlugin:function(config) {

            // On fusionne les options par defaut avec les options de l'utilisateur
            var config = $.extend({}, $.sxnDemoPlugin.defaults, config);
            // $(this) fait référence à l'objet sur lequel on applique notre plugin
            var $this = $(this);

            $this.each(function() {

                $(this).hover(
                    function(e) {

                        // On recupère le texte contenu dans l'attribut defini dans les options
                        var data = $(this).attr(config.attr);

                        if (data.indexOf('sxnImage__') != -1) {
                            var datas = data.split('__');
                            var img = datas[1];
                            var box = '<div id="sxnBox"><img src="' + img + '" alt="Chargement..." /></div>';
                        }
                        else {
                            var box = '<div id="sxnBox">' + data + '</div>';
                        }

                        $('body').append(box);
                        $('#sxnBox').css('left', e.pageX + 20).css('top', e.pageY - 20);


                    },
                    function() {

                        $('#sxnBox').remove();

                    }
                );

                $(this).mousemove(function(e) {

                    $('#sxnBox').css('left', e.pageX + 20).css('top', e.pageY - 20);

                });

            });


            // On retourne this afin de pouvoir appler d'autres fonctions en chaine après notre plugin
            // Exemple : $('#some_id').show().sxnDemoPlugin().hide();
            return this;

        }

    });

})(jQuery);

Maintenant que notre plugin est écrit, nous pouvons l'intégrer à notre page et l'utiliser. Ajoutez le code suivant avant la balise de votre page HTML.

<script type="text/javascript" src="chemin/vers/jquery.js"></script>
<script type="text/javascript" src="chemin/vers/jquery.sxndemoplugin.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        // Les cibles du plugin sont tous les éléments ayant la class target
        // Comme on a pas précisé d'options, les données seront cherchées dans l'attribut rel
        $('.target').sxnDemoPlugin();

        // Les éléments ayant la classe target2 contiendront leurs données dans l'attribut id
        $('.target2').sxnDemoPlugin({
            attr: 'id'
        });
    });
</script>
<style type="text/css" media="screen">
    #sxnBox {
        position: absolute;
        padding: 3px;
        max-width: 300px;
        border: 4px solid #afafaf;
        background: #e8e8e8;
        -moz-border-radius: 5px;
        -webkit-border-radius: 5px;
    }
    #sxnBox img {
        width: 300px;
    }
</style>

On appelle donc notre plugin sur les éléments ayant les classes target et target2. Ensuite, on ajoute un peu de CSS pour notre boîte et c'est terminé.\r\nJ'espère que ce tuto vous sera utile et bon développement !


Abonnez vous au flux RSS des tutoriels pour rester informé.
Sinon, n'hésitez pas à laisser un commentaire ou à partage ce tutoriel sur les réseaux sociaux, ça me fait toujours plaisir et m'encourage à continuer mon oeuvre pour un monde meilleur.

Ajouter un commentaire