Comment créer un plugin jQuery avec des méthodes?

191

J'essaie d'écrire un plugin jQuery qui fournira des fonctions / méthodes supplémentaires à l'objet qui l'appelle. Tous les didacticiels que j'ai lus en ligne (que j'ai parcourus ces 2 dernières heures) comprennent au maximum comment ajouter des options, mais pas des fonctions supplémentaires.

Voici ce que je cherche à faire:

// formater div pour être un conteneur de messages en appelant le plugin pour ce div

$("#mydiv").messagePlugin();
$("#mydiv").messagePlugin().saySomething("hello");

Ou quelque chose de ce genre. Voici à quoi cela se résume: j'appelle le plugin, puis j'appelle une fonction associée à ce plugin. Je n'arrive pas à trouver un moyen de le faire, et j'ai déjà vu de nombreux plugins le faire.

Voici ce que j'ai jusqu'à présent pour le plugin:

jQuery.fn.messagePlugin = function() {
  return this.each(function(){
    alert(this);
  });

  //i tried to do this, but it does not seem to work
  jQuery.fn.messagePlugin.saySomething = function(message){
    $(this).html(message);
  }
};

Comment puis-je réaliser quelque chose comme ça?

Merci!


Mise à jour du 18 novembre 2013: J'ai changé la bonne réponse en celle des commentaires et votes positifs suivants de Hari.

Yuval Karmi
la source

Réponses:

313

Selon la page jQuery Plugin Authoring ( http://docs.jquery.com/Plugins/Authoring ), il vaut mieux ne pas brouiller les espaces de noms jQuery et jQuery.fn. Ils suggèrent cette méthode:

(function( $ ){

    var methods = {
        init : function(options) {

        },
        show : function( ) {    },// IS
        hide : function( ) {  },// GOOD
        update : function( content ) {  }// !!!
    };

    $.fn.tooltip = function(methodOrOptions) {
        if ( methods[methodOrOptions] ) {
            return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
            // Default to "init"
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  methodOrOptions + ' does not exist on jQuery.tooltip' );
        }    
    };


})( jQuery );

Fondamentalement, vous stockez vos fonctions dans un tableau (étendu à la fonction d'encapsulation) et recherchez une entrée si le paramètre passé est une chaîne, en revenant à une méthode par défaut ("init" ici) si le paramètre est un objet (ou nul).

Ensuite, vous pouvez appeler les méthodes comme ça ...

$('div').tooltip(); // calls the init method
$('div').tooltip({  // calls the init method
  foo : 'bar'
});
$('div').tooltip('hide'); // calls the hide method
$('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method

La variable Javascripts "arguments" est un tableau de tous les arguments passés afin qu'elle fonctionne avec des longueurs arbitraires de paramètres de fonction.

Hari Karam Singh
la source
2
C'est la méthode que j'utilise. Vous pouvez également appeler les méthodes de manière statique via $ .fn.tooltip ('methodname', params);
Rake36 du
1
Architecture très pratique. J'ai également ajouté cette ligne avant d'appeler la méthode init:, this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));donc maintenant je peux accéder aux options quand je veux après l'initialisation.
ivkremer
16
Pour tous ceux comme moi qui ont dit pour la première fois "d'où vient la variable arguments" - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference /... - J'utilise JS depuis toujours et je ne l'ai jamais su. Vous apprenez quelque chose de nouveau tous les jours!
streetlogics
2
@DiH, je suis avec vous sur celui-ci. Cette approche semble excellente, mais elle ne vous donne pas accès à vos paramètres globaux depuis un autre endroit que init.
Stephen Collins
4
Il y a un problème majeur avec cette technique! Il ne crée pas une nouvelle instance pour chaque élément du sélecteur comme vous pensez que vous le faites, au lieu de cela, il ne crée qu'une seule instance attachée au sélecteur lui-même. Voir ma réponse pour une solution.
Kevin Jurkowski
56

Voici le modèle que j'ai utilisé pour créer des plugins avec des méthodes supplémentaires. Vous l'utiliseriez comme:

$('selector').myplugin( { key: 'value' } );

ou, pour invoquer directement une méthode,

$('selector').myplugin( 'mymethod1', 'argument' );

Exemple:

;(function($) {

    $.fn.extend({
        myplugin: function(options,arg) {
            if (options && typeof(options) == 'object') {
                options = $.extend( {}, $.myplugin.defaults, options );
            }

            // this creates a plugin for each element in
            // the selector or runs the function once per
            // selector.  To have it do so for just the
            // first element (once), return false after
            // creating the plugin to stop the each iteration 
            this.each(function() {
                new $.myplugin(this, options, arg );
            });
            return;
        }
    });

    $.myplugin = function( elem, options, arg ) {

        if (options && typeof(options) == 'string') {
           if (options == 'mymethod1') {
               myplugin_method1( arg );
           }
           else if (options == 'mymethod2') {
               myplugin_method2( arg );
           }
           return;
        }

        ...normal plugin actions...

        function myplugin_method1(arg)
        {
            ...do method1 with this and arg
        }

        function myplugin_method2(arg)
        {
            ...do method2 with this and arg
        }

    };

    $.myplugin.defaults = {
       ...
    };

})(jQuery);
Tvanfosson
la source
9
même modèle que jquery-ui, je n'aime pas toutes les cordes magiques mais y a-t-il un autre moyen!
redsquare
8
cela semble être une façon non standard de faire les choses - y a-t-il quelque chose de plus simple que cela, comme le chaînage des fonctions? Merci!
Yuval Karmi
2
@yuval - généralement les plugins jQuery renvoient jQuery ou une valeur, pas le plugin lui-même. C'est pourquoi le nom de la méthode est passé en argument au plugin lorsque vous souhaitez invoquer le plugin. Vous pouvez passer n'importe quel nombre d'arguments, mais vous devrez ajuster les fonctions et l'analyse des arguments. Il est probablement préférable de les définir dans un objet anonyme comme vous l'avez montré.
tvanfosson
1
Quelle est la signification de ;dans votre première ligne? veuillez m'expliquer :)
GusDeCooL
4
@GusDeCooL il s'assure simplement que nous commençons une nouvelle instruction afin que notre définition de fonction ne soit pas interprétée comme un argument du Javascript mal formaté de quelqu'un d'autre (c'est-à-dire que le paren initial n'est pas considéré comme un opérateur d'appel de fonction). Voir stackoverflow.com/questions/7365172/…
tvanfosson
35

Qu'en est-il de cette approche:

jQuery.fn.messagePlugin = function(){
    var selectedObjects = this;
    return {
             saySomething : function(message){
                              $(selectedObjects).each(function(){
                                $(this).html(message);
                              });
                              return selectedObjects; // Preserve the jQuery chainability 
                            },
             anotherAction : function(){
                               //...
                               return selectedObjects;
                             }
           };
}
// Usage:
$('p').messagePlugin().saySomething('I am a Paragraph').css('color', 'red');

Les objets sélectionnés sont stockés dans la fermeture messagePlugin, et cette fonction renvoie un objet qui contient les fonctions associées au plugin, dans chaque fonction, vous pouvez effectuer les actions souhaitées sur les objets actuellement sélectionnés.

Vous pouvez tester et jouer avec le code ici .

Edit: code mis à jour pour préserver la puissance de la chaînabilité jQuery.

Christian C. Salvadó
la source
1
J'ai un peu de mal à comprendre à quoi cela ressemblerait. En supposant que j'ai du code qui doit être exécuté la première fois qu'il est exécuté, je devrai d'abord l'initialiser dans mon code - quelque chose comme ceci: $ ('p'). MessagePlugin (); puis plus tard dans le code, j'aimerais appeler la fonction saySomething comme ceci $ ('p'). messagePlugin (). saySomething ('something'); cela ne réinitialisera-t-il pas le plugin puis n'appellera pas la fonction? à quoi cela ressemblerait-il avec le boîtier et les options? Merci beaucoup. -yuval
Yuval Karmi
1
Cependant, une sorte de rupture du paradigme de chaînabilité de jQuery.
tvanfosson
peut-être que cela devrait être la meilleure réponse
Dragouf
3
Chaque fois que vous appelez messagePlugin (), il créera un nouvel objet avec ces deux fonctions, non?
w00t
4
Le principal problème avec cette approche est qu'elle ne peut pas préserver la chaînabilité à $('p').messagePlugin()moins que vous n'appeliez l' une des deux fonctions qu'elle renvoie.
Joshua Bambrick
18

Le problème avec la réponse actuellement sélectionnée est que vous ne créez pas réellement une nouvelle instance du plugin personnalisé pour chaque élément du sélecteur comme vous pensez que vous le faites ... le sélecteur lui-même comme champ d'application.

Regardez ce violon pour une explication plus approfondie.

Au lieu de cela, vous devrez parcourir le sélecteur en utilisant jQuery.each et instancier une nouvelle instance du plugin personnalisé pour chaque élément du sélecteur.

Voici comment:

(function($) {

    var CustomPlugin = function($el, options) {

        this._defaults = {
            randomizer: Math.random()
        };

        this._options = $.extend(true, {}, this._defaults, options);

        this.options = function(options) {
            return (options) ?
                $.extend(true, this._options, options) :
                this._options;
        };

        this.move = function() {
            $el.css('margin-left', this._options.randomizer * 100);
        };

    };

    $.fn.customPlugin = function(methodOrOptions) {

        var method = (typeof methodOrOptions === 'string') ? methodOrOptions : undefined;

        if (method) {
            var customPlugins = [];

            function getCustomPlugin() {
                var $el          = $(this);
                var customPlugin = $el.data('customPlugin');

                customPlugins.push(customPlugin);
            }

            this.each(getCustomPlugin);

            var args    = (arguments.length > 1) ? Array.prototype.slice.call(arguments, 1) : undefined;
            var results = [];

            function applyMethod(index) {
                var customPlugin = customPlugins[index];

                if (!customPlugin) {
                    console.warn('$.customPlugin not instantiated yet');
                    console.info(this);
                    results.push(undefined);
                    return;
                }

                if (typeof customPlugin[method] === 'function') {
                    var result = customPlugin[method].apply(customPlugin, args);
                    results.push(result);
                } else {
                    console.warn('Method \'' + method + '\' not defined in $.customPlugin');
                }
            }

            this.each(applyMethod);

            return (results.length > 1) ? results : results[0];
        } else {
            var options = (typeof methodOrOptions === 'object') ? methodOrOptions : undefined;

            function init() {
                var $el          = $(this);
                var customPlugin = new CustomPlugin($el, options);

                $el.data('customPlugin', customPlugin);
            }

            return this.each(init);
        }

    };

})(jQuery);

Et un violon qui fonctionne .

Vous remarquerez que dans le premier violon, tous les div sont toujours déplacés vers la droite du même nombre de pixels. En effet, un seul objet d'options existe pour tous les éléments du sélecteur.

En utilisant la technique écrite ci-dessus, vous remarquerez que dans le deuxième violon, chaque div n'est pas aligné et est déplacé aléatoirement (à l'exclusion du premier div car son randomiseur est toujours réglé sur 1 à la ligne 89). C'est parce que nous instancions maintenant correctement une nouvelle instance de plugin personnalisée pour chaque élément du sélecteur. Chaque élément a son propre objet d'options et n'est pas enregistré dans le sélecteur, mais dans l'instance du plugin personnalisé lui-même.

Cela signifie que vous serez en mesure d'accéder aux méthodes du plugin personnalisé instancié sur un élément spécifique du DOM à partir de nouveaux sélecteurs jQuery et que vous ne serez pas obligé de les mettre en cache, comme vous le seriez dans le premier violon.

Par exemple, cela renvoie un tableau de tous les objets d'options en utilisant la technique du second violon. Il reviendrait indéfini dans le premier.

$('div').customPlugin();
$('div').customPlugin('options'); // would return an array of all options objects

Voici comment vous devriez accéder à l'objet d'options dans le premier violon, et ne retourneriez qu'un seul objet, pas un tableau d'entre eux:

var divs = $('div').customPlugin();
divs.customPlugin('options'); // would return a single options object

$('div').customPlugin('options');
// would return undefined, since it's not a cached selector

Je suggère d'utiliser la technique ci-dessus, pas celle de la réponse actuellement sélectionnée.

Kevin Jurkowski
la source
Merci, cela m'a beaucoup aidé, en particulier en me présentant la méthode .data (). Très utile. FWIW, vous pouvez également simplifier une partie de votre code en utilisant des méthodes anonymes.
dalemac
jQuery chainability ne fonctionne pas avec cette méthode ... $('.my-elements').find('.first-input').customPlugin('update'‌​, 'first value').end().find('.second-input').customPlugin('update', 'second value'); returns Cannot read property 'end' of undefined. jsfiddle.net/h8v1k2pL
Alex G
16

jQuery a rendu cela beaucoup plus facile avec l'introduction de la Widget Factory .

Exemple:

$.widget( "myNamespace.myPlugin", {

    options: {
        // Default options
    },

    _create: function() {
        // Initialization logic here
    },

    // Create a public method.
    myPublicMethod: function( argument ) {
        // ...
    },

    // Create a private method.
    _myPrivateMethod: function( argument ) {
        // ...
    }

});

Initialisation:

$('#my-element').myPlugin();
$('#my-element').myPlugin( {defaultValue:10} );

Appel de méthode:

$('#my-element').myPlugin('myPublicMethod', 20);

(C'est ainsi que la bibliothèque d'interface utilisateur jQuery est construite.)

Yarin
la source
@ daniel.sedlacek a) "très mauvaise architecture" - c'est l'architecture de widget standard de jQuery b) "vérifié pour l'intégrité au moment de la compilation" - JavaScript est un langage dynamique c) "TypeScript" - quoi?
Yarin
a) c'est l'argumentum ad populum, b) chaque meilleur IDE JS a une complétion de code ou un linting, c) google it
daniel.sedlacek
C'est une pure illusion, M. Sedlacek.
mystrdat
Par docs: Ce système est appelé Widget Factory et est exposé en tant que jQuery.widget dans le cadre de jQuery UI 1.8; cependant, il peut être utilisé indépendamment de l'interface utilisateur jQuery. Comment $ .widget est-il utilisé sans l' interface utilisateur jQuery?
Airn5475
13

Une approche plus simple consiste à utiliser des fonctions imbriquées. Ensuite, vous pouvez les chaîner de manière orientée objet. Exemple:

jQuery.fn.MyPlugin = function()
{
  var _this = this;
  var a = 1;

  jQuery.fn.MyPlugin.DoSomething = function()
  {
    var b = a;
    var c = 2;

    jQuery.fn.MyPlugin.DoSomething.DoEvenMore = function()
    {
      var d = a;
      var e = c;
      var f = 3;
      return _this;
    };

    return _this;
  };

  return this;
};

Et voici comment l'appeler:

var pluginContainer = $("#divSomeContainer");
pluginContainer.MyPlugin();
pluginContainer.MyPlugin.DoSomething();
pluginContainer.MyPlugin.DoSomething.DoEvenMore();

Attention cependant. Vous ne pouvez pas appeler une fonction imbriquée tant qu'elle n'a pas été créée. Vous ne pouvez donc pas faire ceci:

var pluginContainer = $("#divSomeContainer");
pluginContainer.MyPlugin();
pluginContainer.MyPlugin.DoSomething.DoEvenMore();
pluginContainer.MyPlugin.DoSomething();

La fonction DoEvenMore n'existe même pas car la fonction DoSomething n'a pas encore été exécutée, ce qui est nécessaire pour créer la fonction DoEvenMore. Pour la plupart des plugins jQuery, vous n'aurez vraiment qu'un seul niveau de fonctions imbriquées et non deux comme je l'ai montré ici.
Assurez-vous simplement que lorsque vous créez des fonctions imbriquées, vous définissez ces fonctions au début de leur fonction parente avant que tout autre code de la fonction parente ne soit exécuté.

Enfin, notez que le membre "this" est stocké dans une variable appelée "_this". Pour les fonctions imbriquées, vous devez renvoyer "_this" si vous avez besoin d'une référence à l'instance dans le client appelant. Vous ne pouvez pas simplement renvoyer "this" dans la fonction imbriquée car cela renverra une référence à la fonction et non à l'instance jQuery. Le renvoi d'une référence jQuery vous permet d'enchaîner des méthodes jQuery intrinsèques au retour.

Polaris431
la source
2
C'est génial - je me demande seulement pourquoi jQuery semble favoriser l'appel des méthodes par leur nom comme dans le modèle .plugin ('method')?
w00t
6
Cela ne fonctionne pas. Si vous invoquez le plugin sur deux conteneurs différents, les variables internes sont remplacées (à savoir _this)
mbrochh
Échec: n'autorise pas pluginContainer.MyPlugin.DoEvenMore (). DoSomething ();
Paul Swetz du
9

Je l'ai obtenu de jQuery Plugin Boilerplate

Également décrit dans jQuery Plugin Boilerplate, reprise

// jQuery Plugin Boilerplate
// A boilerplate for jumpstarting jQuery plugins development
// version 1.1, May 14th, 2011
// by Stefan Gabos

// remember to change every instance of "pluginName" to the name of your plugin!
(function($) {

    // here we go!
    $.pluginName = function(element, options) {

    // plugin's default options
    // this is private property and is accessible only from inside the plugin
    var defaults = {

        foo: 'bar',

        // if your plugin is event-driven, you may provide callback capabilities
        // for its events. execute these functions before or after events of your
        // plugin, so that users may customize those particular events without
        // changing the plugin's code
        onFoo: function() {}

    }

    // to avoid confusions, use "plugin" to reference the
    // current instance of the object
    var plugin = this;

    // this will hold the merged default, and user-provided options
    // plugin's properties will be available through this object like:
    // plugin.settings.propertyName from inside the plugin or
    // element.data('pluginName').settings.propertyName from outside the plugin,
    // where "element" is the element the plugin is attached to;
    plugin.settings = {}

    var $element = $(element), // reference to the jQuery version of DOM element
    element = element; // reference to the actual DOM element

    // the "constructor" method that gets called when the object is created
    plugin.init = function() {

    // the plugin's final properties are the merged default and
    // user-provided options (if any)
    plugin.settings = $.extend({}, defaults, options);

    // code goes here

   }

   // public methods
   // these methods can be called like:
   // plugin.methodName(arg1, arg2, ... argn) from inside the plugin or
   // element.data('pluginName').publicMethod(arg1, arg2, ... argn) from outside
   // the plugin, where "element" is the element the plugin is attached to;

   // a public method. for demonstration purposes only - remove it!
   plugin.foo_public_method = function() {

   // code goes here

    }

     // private methods
     // these methods can be called only from inside the plugin like:
     // methodName(arg1, arg2, ... argn)

     // a private method. for demonstration purposes only - remove it!
     var foo_private_method = function() {

        // code goes here

     }

     // fire up the plugin!
     // call the "constructor" method
     plugin.init();

     }

     // add the plugin to the jQuery.fn object
     $.fn.pluginName = function(options) {

        // iterate through the DOM elements we are attaching the plugin to
        return this.each(function() {

          // if plugin has not already been attached to the element
          if (undefined == $(this).data('pluginName')) {

              // create a new instance of the plugin
              // pass the DOM element and the user-provided options as arguments
              var plugin = new $.pluginName(this, options);

              // in the jQuery version of the element
              // store a reference to the plugin object
              // you can later access the plugin and its methods and properties like
              // element.data('pluginName').publicMethod(arg1, arg2, ... argn) or
              // element.data('pluginName').settings.propertyName
              $(this).data('pluginName', plugin);

           }

        });

    }

})(jQuery);
MaxEcho
la source
Votre méthode rompt le chaînage jQuery: $('.first-input').data('pluginName').publicMethod('new value').css('color', red);renvoie Cannot read property 'css' of undefined jsfiddle.net/h8v1k2pL/1
Alex G
@AlexG étant donné cet exemple, vous l'ajouteriez return $elementdonc dans cet exemple, vous le plugin.foo_public_method = function() {/* Your Code */ return $element;}changeriez en @Salim merci de m'avoir aidé ... github.com/AndreaLombardo/BootSideMenu/pull/34
CrandellWS
6

Trop tard mais peut-être que ça pourra aider quelqu'un un jour.

J'étais dans la même situation que créer un plugin jQuery avec certaines méthodes, et après avoir lu quelques articles et quelques pneus, je crée un plugin jQuery standard ( https://github.com/acanimal/jQuery-Plugin-Boilerplate ).

De plus, je développe avec lui un plugin pour gérer les tags ( https://github.com/acanimal/tagger.js ) et rédige deux articles de blog expliquant pas à pas la création d'un plugin jQuery ( http: // acuriousanimal. com / blog / 2013/01/15 / choses-que-j'ai-apprises-en-creant-un-plugin-jquery-partie-i / ).

EricSonaron
la source
probablement le meilleur article que j'ai rencontré à ce jour sur la création de plugins jQuery en tant que débutant - merci;)
Dex Dave
5

Tu peux faire:

(function($) {
  var YourPlugin = function(element, option) {
    var defaults = {
      //default value
    }

    this.option = $.extend({}, defaults, option);
    this.$element = $(element);
    this.init();
  }

  YourPlugin.prototype = {
    init: function() { },
    show: function() { },
    //another functions
  }

  $.fn.yourPlugin = function(option) {
    var arg = arguments,
        options = typeof option == 'object' && option;;
    return this.each(function() {
      var $this = $(this),
          data = $this.data('yourPlugin');

      if (!data) $this.data('yourPlugin', (data = new YourPlugin(this, options)));
      if (typeof option === 'string') {
        if (arg.length > 1) {
          data[option].apply(data, Array.prototype.slice.call(arg, 1));
        } else {
          data[option]();
        }
      }
    });
  };
});

De cette façon, votre objet plugins est stocké en tant que valeur de données dans votre élément.

//Initialization without option
$('#myId').yourPlugin();

//Initialization with option
$('#myId').yourPlugin({
  // your option
});

// call show method
$('#myId').yourPlugin('show');
Mazaher Bazari
la source
3

Qu'en est-il des déclencheurs? Quelqu'un connaît-il un inconvénient de les utiliser? L'avantage est que toutes les variables internes sont accessibles via les déclencheurs, et le code est très simple.

Voir sur jsfiddle .

Exemple d'utilisation

<div id="mydiv">This is the message container...</div>

<script>
    var mp = $("#mydiv").messagePlugin();

    // the plugin returns the element it is called on
    mp.trigger("messagePlugin.saySomething", "hello");

    // so defining the mp variable is not needed...
    $("#mydiv").trigger("messagePlugin.repeatLastMessage");
</script>

Brancher

jQuery.fn.messagePlugin = function() {

    return this.each(function() {

        var lastmessage,
            $this = $(this);

        $this.on('messagePlugin.saySomething', function(e, message) {
            lastmessage = message;
            saySomething(message);
        });

        $this.on('messagePlugin.repeatLastMessage', function(e) {
            repeatLastMessage();
        });

        function saySomething(message) {
            $this.html("<p>" + message + "</p>");
        }

        function repeatLastMessage() {
            $this.append('<p>Last message was: ' + lastmessage + '</p>');
        }

    });

}
István Ujj-Mészáros
la source
1
cf. votre commentaire. Le seul problème que je vois ici est sans doute une mauvaise utilisation du système d'événements. Il est atypique d'utiliser des événements uniquement pour appeler une fonction; cela semble excessif et peut être facilement cassé. Normalement, vous utiliseriez des événements de façon publication-abonnement, par exemple, une fonction publie qu'une condition "A" s'est produite. D'autres entités, intéressées par «A», écoutent le message que «A» s'est produit, puis font quelque chose. Vous semblez l'utiliser comme "commande" push à la place, mais en supposant qu'il n'y a qu'un seul écouteur. Vous devriez faire attention à ce que votre sémantique ne soit pas interrompue par (d'autres) ajoutant des écouteurs.
tvanfosson
@tvanfosson Merci pour votre commentaire. Je comprends que ce n'est pas une technique courante et que cela peut causer des problèmes si quelqu'un ajoute accidentellement un écouteur d'événements, mais s'il est nommé d'après le plugin, alors c'est très peu probable. Je ne connais aucun problème lié aux performances, mais le code lui-même me semble beaucoup plus simple qu'avec les autres solutions, mais il me manque peut-être quelque chose.
István Ujj-Mészáros
3

Ici, je veux suggérer des étapes pour créer un plugin simple avec des arguments.

(function($) {
  $.fn.myFirstPlugin = function(options) {
    // Default params
    var params = $.extend({
      text     : 'Default Title',
      fontsize : 10,
    }, options);
    return $(this).text(params.text);
  }
}(jQuery));

$('.cls-title').myFirstPlugin({ text : 'Argument Title' });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 class="cls-title"></h1>

Ici, nous avons ajouté un objet par défaut appelé paramset défini les valeurs par défaut des options à l'aide de extendfunction. Par conséquent, si nous passons un argument vide, il définira les valeurs par défaut à la place, sinon il sera défini.

Lire la suite: Comment créer un plugin JQuery

Gopal Joshi
la source
Salut Gopal Joshi, Veuillez donner la création de plugin jquery de niveau supérieur. nous attendons de votre réponse nécessaire.
Sakthi Karthik
Bonjour @SakthiKarthik, Off cource je publierai bientôt un nouveau tutoriel dans mon blog
Gopal Joshi
1
Salut @SakthiKarthik, Vous pouvez renvoyer un nouvel article sur le plugin jquery de niveau supérieur ici sgeek.org
Gopal Joshi
2

Essaye celui-là:

$.fn.extend({
"calendar":function(){
    console.log(this);
    var methods = {
            "add":function(){console.log("add"); return this;},
            "init":function(){console.log("init"); return this;},
            "sample":function(){console.log("sample"); return this;}
    };

    methods.init(); // you can call any method inside
    return methods;
}}); 
$.fn.calendar() // caller or 
$.fn.calendar().sample().add().sample() ......; // call methods
Serkan KONAKCI
la source
1

Voici ma version simple de ceci. Semblable à ceux publiés précédemment, vous appelleriez comme:

$('#myDiv').MessagePlugin({ yourSettings: 'here' })
           .MessagePlugin('saySomething','Hello World!');

-ou accéder directement à l'instance @ plugin_MessagePlugin

$elem = $('#myDiv').MessagePlugin();
var instance = $elem.data('plugin_MessagePlugin');
instance.saySomething('Hello World!');

MessagePlugin.js

;(function($){

    function MessagePlugin(element,settings){ // The Plugin
        this.$elem = element;
        this._settings = settings;
        this.settings = $.extend(this._default,settings);
    }

    MessagePlugin.prototype = { // The Plugin prototype
        _default: {
            message: 'Generic message'
        },
        initialize: function(){},
        saySomething: function(message){
            message = message || this._default.message;
            return this.$elem.html(message);
        }
    };

    $.fn.MessagePlugin = function(settings){ // The Plugin call

        var instance = this.data('plugin_MessagePlugin'); // Get instance

        if(instance===undefined){ // Do instantiate if undefined
            settings = settings || {};
            this.data('plugin_MessagePlugin',new MessagePlugin(this,settings));
            return this;
        }

        if($.isFunction(MessagePlugin.prototype[settings])){ // Call method if argument is name of method
            var args = Array.prototype.slice.call(arguments); // Get the arguments as Array
            args.shift(); // Remove first argument (name of method)
            return MessagePlugin.prototype[settings].apply(instance, args); // Call the method
        }

        // Do error handling

        return this;
    }

})(jQuery);
jtrumbull
la source
1

La structure de plugin suivante utilise la méthode data()jQuery- pour fournir une interface publique aux méthodes / paramètres internes du plugin (tout en préservant la chaînabilité de jQuery):

(function($, window, undefined) { 
  const defaults = {
    elementId   : null,
    shape       : "square",
    color       : "aqua",
    borderWidth : "10px",
    borderColor : "DarkGray"
  };

  $.fn.myPlugin = function(options) {
    // settings, e.g.:  
    var settings = $.extend({}, defaults, options);

    // private methods, e.g.:
    var setBorder = function(color, width) {        
      settings.borderColor = color;
      settings.borderWidth = width;          
      drawShape();
    };

    var drawShape = function() {         
      $('#' + settings.elementId).attr('class', settings.shape + " " + "center"); 
      $('#' + settings.elementId).css({
        'background-color': settings.color,
        'border': settings.borderWidth + ' solid ' + settings.borderColor      
      });
      $('#' + settings.elementId).html(settings.color + " " + settings.shape);            
    };

    return this.each(function() { // jQuery chainability     
      // set stuff on ini, e.g.:
      settings.elementId = $(this).attr('id'); 
      drawShape();

      // PUBLIC INTERFACE 
      // gives us stuff like: 
      //
      //    $("#...").data('myPlugin').myPublicPluginMethod();
      //
      var myPlugin = {
        element: $(this),
        // access private plugin methods, e.g.: 
        setBorder: function(color, width) {        
          setBorder(color, width);
          return this.element; // To ensure jQuery chainability 
        },
        // access plugin settings, e.g.: 
        color: function() {
          return settings.color;
        },        
        // access setting "shape" 
        shape: function() {
          return settings.shape;
        },     
        // inspect settings 
        inspectSettings: function() {
          msg = "inspecting settings for element '" + settings.elementId + "':";   
          msg += "\n--- shape: '" + settings.shape + "'";
          msg += "\n--- color: '" + settings.color + "'";
          msg += "\n--- border: '" + settings.borderWidth + ' solid ' + settings.borderColor + "'";
          return msg;
        },               
        // do stuff on element, e.g.:  
        change: function(shape, color) {        
          settings.shape = shape;
          settings.color = color;
          drawShape();   
          return this.element; // To ensure jQuery chainability 
        }
      };
      $(this).data("myPlugin", myPlugin);
    }); // return this.each 
  }; // myPlugin
}(jQuery));

Vous pouvez maintenant appeler des méthodes de plugin internes pour accéder ou modifier les données du plugin ou l'élément pertinent en utilisant cette syntaxe:

$("#...").data('myPlugin').myPublicPluginMethod(); 

Tant que vous retournez l'élément actuel (this) de l'intérieur, votre implémentation de myPublicPluginMethod()jQuery-chainability sera préservée - donc les travaux suivants:

$("#...").data('myPlugin').myPublicPluginMethod().css("color", "red").html("...."); 

Voici quelques exemples (pour plus de détails, consultez ce violon ):

// initialize plugin on elements, e.g.:
$("#shape1").myPlugin({shape: 'square', color: 'blue', borderColor: 'SteelBlue'});
$("#shape2").myPlugin({shape: 'rectangle', color: 'red', borderColor: '#ff4d4d'});
$("#shape3").myPlugin({shape: 'circle', color: 'green', borderColor: 'LimeGreen'});

// calling plugin methods to read element specific plugin settings:
console.log($("#shape1").data('myPlugin').inspectSettings());    
console.log($("#shape2").data('myPlugin').inspectSettings());    
console.log($("#shape3").data('myPlugin').inspectSettings());      

// calling plugin methods to modify elements, e.g.:
// (OMG! And they are chainable too!) 
$("#shape1").data('myPlugin').change("circle", "green").fadeOut(2000).fadeIn(2000);      
$("#shape1").data('myPlugin').setBorder('LimeGreen', '30px');

$("#shape2").data('myPlugin').change("rectangle", "red"); 
$("#shape2").data('myPlugin').setBorder('#ff4d4d', '40px').css({
  'width': '350px',
  'font-size': '2em' 
}).slideUp(2000).slideDown(2000);              

$("#shape3").data('myPlugin').change("square", "blue").fadeOut(2000).fadeIn(2000);   
$("#shape3").data('myPlugin').setBorder('SteelBlue', '30px');

// etc. ...     
Mayinx
la source
0

Cela peut en fait être fait pour fonctionner de manière "agréable" en utilisant defineProperty. Où «nice» signifie sans avoir à utiliser ()pour obtenir l'espace de noms du plugin ni à passer le nom de la fonction par chaîne.

Compatibilité nit: defineProperty ne fonctionne pas dans les anciens navigateurs tels que IE8 et inférieurs. Attention: $.fn.color.blue.apply(foo, args) ne fonctionnera pas, vous devez utiliser foo.color.blue.apply(foo, args).

function $_color(color)
{
    return this.css('color', color);
}

function $_color_blue()
{
    return this.css('color', 'blue');
}

Object.defineProperty($.fn, 'color',
{
    enumerable: true,
    get: function()
    {
        var self = this;

        var ret = function() { return $_color.apply(self, arguments); }
        ret.blue = function() { return $_color_blue.apply(self, arguments); }

        return ret;
    }
});

$('#foo').color('#f00');
$('#bar').color.blue();

Lien JSFiddle

Kralyk
la source
0

Selon la norme jquery, vous pouvez créer un plugin comme suit:

(function($) {

    //methods starts here....
    var methods = {
        init : function(method,options) {
             this.loadKeywords.settings = $.extend({}, this.loadKeywords.defaults, options);
             methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
             $loadkeywordbase=$(this);
        },
        show : function() {
            //your code here.................
        },
        getData : function() {
           //your code here.................
        }

    } // do not put semi colon here otherwise it will not work in ie7
    //end of methods

    //main plugin function starts here...
    $.fn.loadKeywords = function(options,method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(
                    arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not ecw-Keywords');
        }
    };
    $.fn.loadKeywords.defaults = {
            keyName:     'Messages',
            Options:     '1',
            callback: '',
    };
    $.fn.loadKeywords.settings = {};
    //end of plugin keyword function.

})(jQuery);

Comment appeler ce plugin?

1.$('your element').loadKeywords('show',{'callback':callbackdata,'keyName':'myKey'}); // show() will be called

Référence: lien

Mahesh
la source
0

Je pense que cela pourrait vous aider ...

(function ( $ ) {
  
    $.fn.highlight = function( options ) {
  
        // This is the easiest way to have default options.
        var settings = $.extend({
            // These are the defaults.
            color: "#000",
            backgroundColor: "yellow"
        }, options );
  
        // Highlight the collection based on the settings variable.
        return this.css({
            color: settings.color,
            backgroundColor: settings.backgroundColor
        });
  
    };
  
}( jQuery ));

Dans l'exemple ci-dessus, j'avais créé un simple plugin de mise en évidence jquery.J'avais partagé un article dans lequel j'avais discuté de la façon de créer votre propre plugin jQuery de Basic à Advance. Je pense que vous devriez le vérifier ... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/

Shubham Kumar
la source
0

Voici un petit plug-in pour avoir une méthode d'avertissement à des fins de débogage. Conservez ce code dans le fichier jquery.debug.js: JS:

jQuery.fn.warning = function() {
   return this.each(function() {
      alert('Tag Name:"' + $(this).prop("tagName") + '".');
   });
};

HTML:

<html>
   <head>
      <title>The jQuery Example</title>

      <script type = "text/javascript" 
         src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

      <script src = "jquery.debug.js" type = "text/javascript"></script>

      <script type = "text/javascript" language = "javascript">
         $(document).ready(function() {
            $("div").warning();
            $("p").warning();
         });
      </script> 
   </head>

   <body>
      <p>This is paragraph</p>
      <div>This is division</div>
   </body>

</html>
jayaweb
la source
0

Voici comment je le fais:

(function ( $ ) {

$.fn.gridview = function( options ) {

    ..........
    ..........


    var factory = new htmlFactory();
    factory.header(...);

    ........

};

}( jQuery ));


var htmlFactory = function(){

    //header
     this.header = function(object){
       console.log(object);
  }
 }
Mina Gabriel
la source
-2

Ce que vous avez fait, c'est étendre l' objet jQuery.fn.messagePlugin par une nouvelle méthode. Ce qui est utile mais pas dans votre cas.

Vous devez faire est d'utiliser cette technique

function methodA(args){ this // refers to object... }
function saySomething(message){ this.html(message);  to first function }

jQuery.fn.messagePlugin = function(opts) {
  if(opts=='methodA') methodA.call(this);
  if(opts=='saySomething') saySomething.call(this, arguments[0]); // arguments is an array of passed parameters
  return this.each(function(){
    alert(this);
  });

};

Mais vous pouvez accomplir ce que vous voulez. Je veux dire qu'il existe un moyen de faire $ ("# mydiv"). MessagePlugin (). SaySomething ("hello"); Mon ami il a commencé à écrire sur les lugins et comment les étendre avec votre chaîne de fonctionnalités voici le lien vers son blog

James
la source