Come creare un plugin jQuery con metodi?


191

Sto cercando di scrivere un plugin jQuery che fornirà ulteriori funzioni / metodi all'oggetto che lo chiama. Tutti i tutorial che ho letto online (ho cercato nelle ultime 2 ore) includono, al massimo, come aggiungere opzioni, ma non funzioni aggiuntive.

Ecco cosa sto cercando di fare:

// formatta div come contenitore di messaggi chiamando il plug-in per quel div

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

o qualcosa del genere. Ecco cosa si riduce a: chiamo il plug-in, quindi chiamo una funzione associata a quel plug-in. Non riesco a trovare un modo per farlo e ho visto molti plugin farlo prima.

Ecco cosa ho finora per il 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);
  }
};

Come posso ottenere qualcosa del genere?

Grazie!


Aggiornamento del 18 novembre 2013: ho modificato la risposta corretta a quella dei seguenti commenti e voti di Hari.

Risposte:


311

Secondo la pagina di creazione dei plugin jQuery ( http://docs.jquery.com/Plugins/Authoring ), è meglio non confondere gli spazi dei nomi jQuery e jQuery.fn. Suggeriscono questo metodo:

(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 );

Fondamentalmente si memorizzano le proprie funzioni in un array (nell'ambito della funzione wrapping) e si controlla una voce se il parametro passato è una stringa, ripristinando un metodo predefinito ("init" qui) se il parametro è un oggetto (o null).

Quindi puoi chiamare i metodi in questo modo ...

$('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 variabile "argomenti" di Javascripts è un array di tutti gli argomenti passati, quindi funziona con lunghezze arbitrarie di parametri di funzione.


2
Questo è il metodo che uso. Puoi anche chiamare i metodi staticamente tramite $ .fn.tooltip ('methodname', params);
Rake36,

1
Architettura molto utile. Ho anche aggiunto questa linea prima di chiamare il metodo init:, this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));quindi ora posso accedere alle opzioni ogni volta che voglio dopo l'inizializzazione.
Ivkremer,

16
Per tutti quelli come me che per primi hanno detto "da dove proviene la variabile argomenti" - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - Uso JS da sempre e non l'ho mai saputo. Si impara qualcosa di nuovo ogni giorno!
streetlogics

2
@DiH, sono con te su questo. Questo approccio sembra eccezionale, ma non ti dà accesso alle tue impostazioni globali da nessun'altra parte init.
Stephen Collins,

4
C'è un grosso problema con questa tecnica! Non crea una nuova istanza per ogni elemento nel selettore come pensi di fare, ma crea solo una singola istanza collegata al selettore stesso. Visualizza la mia risposta per una soluzione.
Kevin Jurkowski il

56

Ecco lo schema che ho usato per creare plugin con metodi aggiuntivi. Lo useresti come:

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

o, per invocare direttamente un metodo,

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

Esempio:

;(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);

9
stesso schema di jquery-ui, non mi piacciono tutte le corde magiche ma c'è un altro modo!
redsquare,

8
questo sembra un modo non standard di fare le cose - c'è qualcosa di più semplice di questo, come concatenare funzioni? grazie!
Yuval Karmi,

2
@yuval: in genere i plug-in jQuery restituiscono jQuery o un valore, non il plug-in stesso. Ecco perché il nome del metodo viene passato come argomento al plug-in quando si desidera invocare il plug-in. Potresti passare qualsiasi numero di argomenti, ma dovrai adattare le funzioni e l'analisi degli argomenti. Probabilmente è meglio metterli in un oggetto anonimo come hai mostrato.
tvanfosson,

1
Qual è il significato di ;nella tua prima riga? per favore
spiegami

4
@GusDeCooL si assicura solo che stiamo iniziando una nuova istruzione in modo che la nostra definizione di funzione non venga interpretata come argomento per il Javascript mal formattato di qualcun altro (ovvero, la parentesi iniziale non viene considerata come un operatore di invocazione della funzione). Vedere stackoverflow.com/questions/7365172/...
tvanfosson

35

Che dire di questo approccio:

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');

Gli oggetti selezionati sono memorizzati nella chiusura messagePlugin e quella funzione restituisce un oggetto che contiene le funzioni associate al plugin, in ciascuna funzione è possibile eseguire le azioni desiderate sugli oggetti attualmente selezionati.

Puoi testare e giocare con il codice qui .

Modifica: codice aggiornato per preservare la potenza della catenabilità jQuery.


1
Sto facendo fatica a capire come sarebbe. Supponendo che ho il codice che deve essere eseguito la prima volta che viene eseguito, dovrò inizializzarlo nel mio codice - qualcosa del genere: $ ('p'). MessagePlugin (); poi più avanti nel codice vorrei chiamare la funzione saySomething like this $ ('p'). messagePlugin (). saySomething ('qualcosa'); questo non reinizializzerà il plugin e quindi chiamerà la funzione? come sarebbe questo con la custodia e le opzioni? Grazie mille. -yuval
Yuval Karmi,

1
In qualche modo, però, si rompe il paradigma della catenabilità di jQuery.
tvanfosson,

forse questa dovrebbe essere la risposta migliore
Dragouf,

3
Ogni volta che chiami messagePlugin () creerà un nuovo oggetto con queste due funzioni, no?
wt

4
Il problema principale con questo approccio è che non può preservare la seguente catenabilità $('p').messagePlugin()se non si chiama una delle due funzioni che restituisce.
Joshua Bambrick,

18

Il problema con la risposta attualmente selezionata è che in realtà non stai creando una nuova istanza del plug-in personalizzato per ogni elemento nel selettore come pensi di fare ... in realtà stai solo creando una singola istanza e passando il selettore stesso come ambito.

Guarda questo violino per una spiegazione più approfondita.

Invece, dovrai eseguire il ciclo attraverso il selettore usando jQuery.each e creare un'istanza di una nuova istanza del plug-in personalizzato per ogni elemento nel selettore.

Ecco come:

(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);

E un violino funzionante .

Noterai come nel primo violino, tutti i div vengono sempre spostati a destra dello stesso numero esatto di pixel. Questo perché esiste un solo oggetto opzioni per tutti gli elementi nel selettore.

Usando la tecnica scritta sopra, noterai che nel secondo violino, ogni div non è allineato e viene spostato casualmente (escluso il primo div in quanto il suo randomizzatore è sempre impostato su 1 sulla linea 89). Questo perché ora stiamo correttamente istanziando una nuova istanza di plug-in personalizzata per ogni elemento nel selettore. Ogni elemento ha il suo oggetto opzioni e non viene salvato nel selettore, ma nell'istanza del plugin personalizzato stesso.

Ciò significa che sarai in grado di accedere ai metodi del plug-in personalizzato istanziato su un elemento specifico nel DOM da nuovi selettori jQuery e non sei obbligato a memorizzarli nella cache, come faresti con il primo violino.

Ad esempio, ciò restituirebbe una matrice di tutti gli oggetti opzioni usando la tecnica nel secondo violino. Sarebbe tornato indefinito nel primo.

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

Ecco come dovresti accedere all'oggetto options nel primo violino e restituire solo un singolo oggetto, non un array di essi:

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

Suggerirei di utilizzare la tecnica sopra, non quella della risposta attualmente selezionata.


Grazie, questo mi ha aiutato molto, in particolare introducendomi il metodo .data (). Molto maneggevole. FWIW puoi anche semplificare parte del tuo codice usando metodi anonimi.
dalemac,

jQuery chainability non funziona con questo metodo ... $('.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 ha reso tutto molto più semplice con l'introduzione di Widget Factory .

Esempio:

$.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 ) {
        // ...
    }

});

Inizializzazione:

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

Metodo di chiamata:

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

(Ecco come viene costruita la libreria dell'interfaccia utente jQuery .)


@ daniel.sedlacek a) "architettura molto scadente" - è l'architettura widget standard di jQuery b) "verificato l'integrità al momento della compilazione" - JavaScript è un linguaggio dinamico c) "TypeScript" - wha?
Yarin,

a) questo è topicum ad populum, b) ogni ID JS migliore ha il completamento del codice o linting, c) google it
daniel.sedlacek,

Questa è pura illusione, signor Sedlacek.
mystrdat,

Per documenti: questo sistema è chiamato Widget Factory ed è esposto come jQuery.widget come parte dell'interfaccia utente 1.8 di jQuery; tuttavia, può essere utilizzato indipendentemente dall'interfaccia utente di jQuery. Come viene utilizzato $ .widget senza l' interfaccia utente di jQuery?
Airn5475,

13

Un approccio più semplice consiste nell'utilizzare le funzioni nidificate. Quindi puoi incatenarli in modo orientato agli oggetti. Esempio:

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;
};

Ed ecco come chiamarlo:

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

Stai attento però. Non è possibile chiamare una funzione nidificata fino a quando non è stata creata. Quindi non puoi farlo:

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

La funzione DoEvenMore non esiste nemmeno perché la funzione DoSomething non è stata ancora eseguita, il che è necessario per creare la funzione DoEvenMore. Per la maggior parte dei plugin jQuery, avrai davvero solo un livello di funzioni nidificate e non due come ho mostrato qui.
Quando si creano funzioni nidificate, accertarsi di definire tali funzioni all'inizio della funzione padre prima di eseguire qualsiasi altro codice nella funzione padre.

Infine, nota che il membro "this" è memorizzato in una variabile chiamata "_this". Per le funzioni nidificate, è necessario restituire "_questo" se è necessario un riferimento all'istanza nel client chiamante. Non puoi semplicemente restituire "this" nella funzione nidificata perché restituirà un riferimento alla funzione e non all'istanza jQuery. La restituzione di un riferimento jQuery consente di concatenare i metodi intrinseci di jQuery al ritorno.


2
Questo è fantastico - mi chiedo solo perché jQuery sembra preferire chiamare i metodi per nome come nel modello .plugin ('metodo')?
wt

6
Questo non funziona. Se invochi il plug-in su due contenitori diversi, le variabili interne vengono sovrascritte (vale a dire _questo)
mbrochh

Fallito: non consente pluginContainer.MyPlugin.DoEvenMore (). DoSomething ();
Paul Swetz,

9

L'ho preso da jQuery Plugin Boilerplate

Descritto anche in 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);

Il tuo metodo rompe il concatenamento di jQuery: $('.first-input').data('pluginName').publicMethod('new value').css('color', red);restituisce Cannot read property 'css' of undefined jsfiddle.net/h8v1k2pL/1
Alex G

@AlexG in questo esempio lo aggiungeresti, return $elementquindi in questo esempio lo cambierai in plugin.foo_public_method = function() {/* Your Code */ return $element;}@Salim grazie per l'aiuto ... github.com/AndreaLombardo/BootSideMenu/pull/34
CrandellWS

6

Troppo tardi, ma forse può aiutare qualcuno un giorno.

Ero nella stessa situazione, come, creando un plug-in jQuery con alcuni metodi, e dopo aver letto alcuni articoli e alcune gomme ho creato un plug-in del plug-in jQuery ( https://github.com/acanimal/jQuery-Plugin-Boilerplate ).

Inoltre, sviluppo un plug-in per gestire i tag ( https://github.com/acanimal/tagger.js ) e ho scritto due post sul blog spiegando passo dopo passo la creazione di un plug-in jQuery ( http: // acuriousanimal. com / blog / 2013/01/15 / cose-ho-imparato-creando-a-jquery-plugin-parte-i / ).


forse il miglior post in cui mi sia mai imbattuto sulla creazione di plugin jQuery come principiante - grazie;)
Dex Dave il

5

Tu puoi fare:

(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]();
        }
      }
    });
  };
});

In questo modo l'oggetto plug-in viene archiviato come valore di dati nel tuo elemento.

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

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

// call show method
$('#myId').yourPlugin('show');

3

Che dire dell'utilizzo dei trigger? Qualcuno conosce qualche inconveniente che li utilizza? Il vantaggio è che tutte le variabili interne sono accessibili tramite i trigger e il codice è molto semplice.

Vedi su jsfiddle .

Esempio di utilizzo

<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>

Collegare

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>');
        }

    });

}

1
cf. il tuo commento. L'unico problema che vedo qui è probabilmente un uso improprio del sistema di eventi. È atipico usare eventi puramente per invocare una funzione; sembra eccessivo e può essere facilmente rotto. Normalmente, useresti gli eventi in modo pubblicazione-abbonamento, ad es. Una funzione pubblica che si è verificata una condizione "A". Altre entità, interessate a "A", ascoltano il messaggio che è successo "A", quindi fanno qualcosa. Sembra che tu lo stia usando come "comando" push, ma supponendo che ci sia un solo ascoltatore. Dovresti stare attento che la tua semantica non venga interrotta da (altri) aggiungendo ascoltatori.
tvanfosson,

@tvanfosson Grazie per il tuo commento. Capisco che non è una tecnica comune e può causare problemi se qualcuno aggiunge accidentalmente un listener di eventi, ma se prende il nome dal plug-in, è molto improbabile. Non conosco problemi legati alle prestazioni, ma il codice stesso mi sembra molto più semplice rispetto alle altre soluzioni, ma potrei mancare qualcosa.
István Ujj-Mészáros,

3

Qui voglio suggerire i passaggi per creare un semplice plugin con argomenti.

(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>

Qui, abbiamo aggiunto l'oggetto predefinito chiamato paramse impostato i valori predefiniti delle opzioni usando la extendfunzione. Quindi, se passiamo argomenti vuoti, imposterà valori predefiniti, altrimenti imposterà.

Ulteriori informazioni: Come creare il plug-in JQuery


Ciao Gopal Joshi, per favore dai la creazione del plugin jquery di livello successivo. ci aspettiamo dalla tua risposta necessaria.
Sakthi Karthik,

Ciao @SakthiKarthik, Off cource Pubblicherò presto un nuovo tutorial nel mio blog
Gopal Joshi,

1
Ciao @SakthiKarthik, puoi fare riferimento al nuovo articolo sul plugin jquery di livello successivo qui sgeek.org/…
Gopal Joshi

2

Prova questo:

$.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

1

Ecco la mia versione bare-bones di questo. Simile a quelli pubblicati prima, chiameresti come:

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

-oppure accedere direttamente all'istanza @ 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);

1

La seguente struttura di plug-in utilizza il metodo data()jQuery per fornire un'interfaccia pubblica ai metodi / impostazioni interni del plug-in (preservando al contempo la catenabilità 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));

Ora puoi chiamare metodi interni del plugin per accedere o modificare i dati del plugin o l'elemento pertinente usando questa sintassi:

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

Finché si restituisce l'elemento corrente (questo) dall'interno dell'implementazione della myPublicPluginMethod()jability-chainability sarà preservata, quindi i seguenti lavori:

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

Ecco alcuni esempi (per dettagli controlla questo violino ):

// 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. ...     

0

Questo può effettivamente essere fatto funzionare in modo "carino" usando defineProperty. Dove "bello" significa senza dover utilizzare ()per ottenere lo spazio dei nomi dei plug-in né passare il nome della funzione per stringa.

Compatibilità nit: defineProperty non funziona nei browser antichi come IE8 e precedenti. Avvertenza: $.fn.color.blue.apply(foo, args) non funzionerà, è necessario utilizzare 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();

JSFiddle link


0

Secondo lo standard jquery è possibile creare plugin come segue:

(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);

Come chiamare questo plugin?

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

Riferimento: link


0

Penso che questo potrebbe aiutarti ...

(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 ));

Nell'esempio sopra ho creato un semplice plug-in di evidenziazione di jquery. Avevo condiviso un articolo in cui avevo discusso su come creare il tuo plug-in jQuery da Basic a Advance. Penso che dovresti dare un'occhiata ... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/


0

Di seguito è riportato un piccolo plug-in per avere un metodo di avviso a scopo di debug. Conservare questo codice nel file 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>

0

Ecco come lo faccio:

(function ( $ ) {

$.fn.gridview = function( options ) {

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


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

    ........

};

}( jQuery ));


var htmlFactory = function(){

    //header
     this.header = function(object){
       console.log(object);
  }
 }

-2

Quello che hai fatto è stato sostanzialmente l'estensione dell'oggetto jQuery.fn.messagePlugin con un nuovo metodo. Che è utile ma non nel tuo caso.

Devi fare è usare questa tecnica

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);
  });

};

Ma puoi realizzare quello che vuoi, intendo dire che esiste un modo per fare $ ("# mydiv"). MessagePlugin (). SaySomething ("ciao"); Il mio amico ha iniziato a scrivere su lugin e su come estenderli con il tuo chainf di funzionalità ecco il link al suo blog

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.