34 votes

Fonctions publiques à l'intérieur d'un plugin jQuery

J'aime l'architecture des plugins jQuery, mais je trouve frustrant (probablement en raison d'un manque de compréhension de ma part) de vouloir conserver une référence à l'instance du plugin pour accéder à des propriétés ou à des méthodes plus tard dans mon code.

Edit : Je tiens à préciser que ce que j'essaie vraiment de faire, c'est de conserver une référence aux méthodes et propriétés utilisées dans le plugin, afin de pouvoir les utiliser ultérieurement.

Prenons le cas d'une icône de chargement AJAX. Dans un environnement OOP plus traditionnel, je pourrais le faire :

var myIcon = new AJAXIcon();
myIcon.start();
//some stuff
myIcon.stop();

Les méthodes et les propriétés de mon objet sont stockées dans une variable pour une utilisation ultérieure. Maintenant, si je veux avoir la même fonctionnalité dans un plugin jQuery, je l'appellerais depuis mon code principal un peu comme ceci :

$("#myId").ajaxIcon()

Par convention, mon plugin doit renvoyer l'objet jQuery original qui lui a été transmis pour permettre la chaînabilité, mais si je fais cela, je perds la possibilité d'accéder aux méthodes et aux propriétés de l'instance du plugin.

Maintenant, je sais que vous pouvez déclarer une fonction publique dans mon plugin, un peu comme suit

$.fn.ajaxIcon = function(options) {
    return this.each(function () {
        //do some stuff
    }
}

$.fn.ajaxIcon.stop = function() {
    //stop stuff
}

Cependant, sans rompre la convention qui consiste à renvoyer l'objet jQuery d'origine, je ne peux pas conserver une référence à l'instance spécifique du plugin auquel je veux me référer.

J'aimerais pouvoir faire quelque chose comme ça :

var myIcon = $("myId").ajaxIcon(); //myIcon = a reference to the ajaxIcon 
myIcon.start();
//some stuff
myIcon.stop();

Des idées ?

94voto

DEfusion Points 2793

Si vous faites quelque chose comme ce qui suit :

(function($){

$.fn.myPlugin = function(options) {
    // support multiple elements
    if (this.length > 1){
        this.each(function() { $(this).myPlugin(options) });
        return this;
    }

    // private variables
    var pOne = '';
    var pTwo = '';
    // ...

    // private methods
    var foo = function() {
        // do something ...
    }
    // ...

    // public methods        
    this.initialize = function() {
        // do something ...
        return this;
    };

    this.bar = function() {
        // do something ...
    };
    return this.initialize();
}
})(jQuery);

Vous pouvez alors accéder à n'importe laquelle de vos méthodes publiques :

var myPlugin = $('#id').myPlugin();

myPlugin.bar();

Ceci est tiré de ce qui suit article très utile (mai 2009) de trulyevil.com qui est lui-même une extension de cet article (Oct 2007) de learningjquery.com.

1 votes

C'est une excellente méthode, même au-delà de ce que vous expliquez ici... car je peux faire quelque chose comme var myPlugin = $('id').myPlugin().otherFunction().hide(), et myPlugin aura toujours les fonctions correctes, car elles sont ajoutées au nœud DOM qui est passé dans la fonction jQuery.

0 votes

Après quelques jours à essayer de comprendre, Dieu merci, c'est ici Y a-t-il eu des développements à ce sujet depuis 2009 ?

0 votes

Merci pour ces conseils utiles :)

3voto

Daniel Points 1404

Ok, j'ai trouvé comment faire ça :

Code du plugin :

$.ajaxIcon.init = function(element, options) {
    //your initialization code

    this.start = function() {
         //start code
    }

    this.stop = function() {
         //stop code
    }
}

$.fn.ajaxIcon = function(options) {
    this.each(function () {
        //This is where the magic happens
        jQuery(this).data('ajaxIcon', new jQuery.ajaxIcon.init(this, opts));
    });

return this;
}

Puis de l'utiliser ailleurs dans votre code :

var myIcon = $("#myId").ajaxIcon.data('ajaxIcon') 
// myIcon: a reference to the 'init' object specific to this plugin instance
myIcon.start();
myIcon.stop();

Voilà, j'ai répondu à ma propre question :)

0 votes

Avez-vous trouvé cet exemple ailleurs, car j'aimerais en savoir un peu plus sur les bits de données - il semble idiot que l'appelant ait besoin d'en savoir plus lors de la création d'une instance.

0 votes

En fait, après une recherche plus approfondie, vous n'avez pas besoin de vous embêter avec tout cela, voir ma réponse.

1 votes

La méthode de DEfusion est bien meilleure... Je n'utiliserais pas cette méthode à moins que vous ne vouliez pas attacher les fonctions directement dans le DOM pour une raison quelconque.

1voto

Jony Points 1

Exemple de plugin avec toutes les fonctions :

    <script type="text/javascript">
(function( $ ) {

    $.fn.PluginX = function( options ) {
        // Default variables
        // var defaults = {textColor: "#000", backgroundColor: "#fff"}
        // var opts = $.extend( {}, defaults, options );

        // Or
        var settings = $.extend( {}, $.fn.PluginX.defaults, options );

        // Private function
        var privFunc = function(txt) {
            return "Private function " + txt;
        };

        // Public function
        this.pubFunc = function(txt) {
            console.log("\r\nPublic function " + txt);
            return this;
        };

        // Public function2
        this.pubFunc2 = function(txt) {
            console.log("\r\nPublic function " + txt);

            // Private from public
            privFunc("\r\nPrivate function from public -- " + txt);
            return this;
        };

        // Our plugin implementation code goes here.
        return this.each(function() {
            // alert(opts.validate);
            $(this).on('click',function(){
                var elem = $( this );
                var markup = elem.text();                                
                console.log("\r\nElement text " + markup);

                // Function private
                console.log(privFunc(markup));

                // External func
                console.log($.fn.PluginX.format(markup));

                // External function
                console.log(external(markup));
            });

            return this;
        });
    };

    // Variable
    $.fn.PluginX.defaults = {
        validate: "username"
    };

    // External Function
    $.fn.PluginX.format = function(txt) {
        return "<strong>" + txt + "</strong>";
    };

    // External Function
    function external(txt){
        return "External " + txt;
    }

})(jQuery);

$(document).ready(function() {
    var pl = $('.txt').PluginX({validate: "words"}).pubFunc("Hello Public").pubFunc2("Hello Public2");        
});
</script>
<p class="txt">Hello Max</p>
<p class="txt">Hello Pax</p>

0voto

Josh E Points 4449

Je pense que vous pourriez accomplir ce que vous cherchez avec quelque chose comme ça :

var myIcon = $("myId").ajaxIcon(); //myIcon = a reference to the ajaxIcon 
$.ajaxIcon.start(myIcon);//some stuff
$.ajaxIcon.stop(myIcon);

Je ne l'ai pas testé - je n'ai pas accès à un environnement où je peux le faire pour le moment.

-1voto

Andrew Noyes Points 2150

La plupart des plugins jQuery que je vois essayer d'accomplir ceci utiliseront un scope anonyme et des closures pour référencer les fonctions et les variables uniques à cette instance. Par exemple, en utilisant le modèle suivant :

;(function ($) {
    // your code
})(jQuery);

Entre le début et la fin du module, vous pouvez déclarer toutes les fonctions que vous voulez. Vous ne polluerez pas l'espace de noms global et vous pourrez conserver l'accès aux variables locales grâce aux closures, ce qui pourrait résoudre beaucoup de vos problèmes. De plus, n'ayez pas peur d'utiliser la fonction $.data fonctions.

0 votes

Hmm.... je pense que mes questions ne sont pas assez claires. Je comprends comment créer un plugin jQuery, avec les closures et autres, mais ce que je veux vraiment savoir, c'est comment accéder aux instances existantes du plugin pour accéder aux propriétés et déclencher les méthodes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X