Jak utworzyć wtyczkę jQuery metodami?

191

Próbuję napisać wtyczkę jQuery, która zapewni dodatkowe funkcje / metody do obiektu, który ją wywołuje. Wszystkie samouczki, które czytam online (przeglądałem przez ostatnie 2 godziny) obejmują co najwyżej, jak dodawać opcje, ale nie dodatkowe funkcje.

Oto, co chcę zrobić:

// formatuj div, aby był kontenerem wiadomości, wywołując wtyczkę dla tego diva

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

lub coś podobnego. Oto, do czego sprowadza się: wywołuję wtyczkę, a następnie wywołuję funkcję związaną z tą wtyczką. Nie mogę znaleźć sposobu, aby to zrobić i widziałem już wiele wtyczek, które robią to wcześniej.

Oto, co mam do tej pory dla wtyczki:

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

Jak mogę osiągnąć coś takiego?

Dziękuję Ci!


Aktualizacja 18 listopada 2013: Zmieniłem poprawną odpowiedź na odpowiedź na następujące komentarze i opinie Hari.

Yuval Karmi
źródło

Odpowiedzi:

310

Zgodnie ze stroną tworzenia wtyczek jQuery ( http://docs.jquery.com/Plugins/Authoring ) najlepiej nie zamazać przestrzeni nazw jQuery i jQuery.fn. Sugerują tę metodę:

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

Zasadniczo przechowujesz swoje funkcje w tablicy (zakres do funkcji zawijania) i sprawdzasz, czy przekazany parametr jest łańcuchem, powracając do domyślnej metody (tutaj „init”), jeśli parametr jest obiektem (lub zerowym).

Następnie możesz wywołać takie metody ...

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

Zmienna „arguments” JavaScript jest tablicą wszystkich przekazanych argumentów, więc działa z dowolnymi długościami parametrów funkcji.

Hari Karam Singh
źródło
2
To jest metoda, której używam. Możesz także wywoływać metody statycznie za pomocą $ .fn.tooltip ('nazwa metody', parametry);
Rake36
1
Bardzo przydatna architektura. Dodałem również ten wiersz przed wywołaniem metody init:, this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));więc teraz mogę uzyskać dostęp do opcji w dowolnym momencie po inicjalizacji.
ivkremer
16
Dla każdego takiego jak ja, który pierwszy powiedział: „skąd pochodzi zmienna argumentów” - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - Używam JS od zawsze i nigdy o tym nie wiedziałem. Codziennie uczysz się czegoś nowego!
streetlogics,
2
@DiH, jestem z tobą w tej sprawie. To podejście wydaje się świetne, ale nie zapewnia dostępu do ustawień globalnych z dowolnego miejsca poza init.
Stephen Collins
4
Z tą techniką jest poważny problem! Nie tworzy nowej instancji dla każdego elementu w selektorze, tak jak myślisz, że robisz, ale tworzy tylko jedną instancję dołączoną do samego selektora. Zobacz moją odpowiedź na rozwiązanie.
Kevin Jurkowski
56

Oto wzorzec, którego użyłem do tworzenia wtyczek za pomocą dodatkowych metod. Użyłbyś tego w następujący sposób:

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

lub, aby wywołać metodę bezpośrednio,

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

Przykład:

;(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
źródło
9
ten sam wzór co jquery-ui, nie podoba mi się wszystkie magiczne ciągi, ale czy jest jakiś inny sposób!
redsquare
8
wydaje się to niestandardowym sposobem robienia rzeczy - czy jest coś prostszego, na przykład łączenie funkcji? Dziękuję Ci!
Yuval Karmi
2
@yuval - zazwyczaj wtyczki jQuery zwracają wartość jQuery lub wartość, a nie samą wtyczkę. Dlatego nazwa metody jest przekazywana jako argument do wtyczki, gdy chcesz ją wywołać. Możesz przekazać dowolną liczbę argumentów, ale będziesz musiał dostosować funkcje i parsowanie argumentów. Prawdopodobnie najlepiej umieścić je w anonimowym obiekcie, jak pokazano.
tvanfosson
1
Jakie jest znaczenie ;pierwszego wiersza? proszę wyjaśnij mi :)
GusDeCooL
4
@GusDeCooL po prostu upewnia się, że uruchamiamy nową instrukcję, aby nasza definicja funkcji nie była interpretowana jako argument za źle sformatowanym kodem JavaScript innej osoby (tzn. Początkowy paren nie jest traktowany jako operator wywołania funkcji). Zobacz stackoverflow.com/questions/7365172/...
tvanfosson
35

Co z tym podejściem:

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

Wybrane obiekty są przechowywane w komunikacie Zamknięcie wtyczki, a ta funkcja zwraca obiekt zawierający funkcje związane z wtyczką, w każdej funkcji możesz wykonać pożądane działania na aktualnie wybranych obiektach.

Możesz przetestować i bawić się kodem tutaj .

Edycja: Zaktualizowano kod, aby zachować moc łańcuchowości jQuery.

CMS
źródło
1
trudno mi zrozumieć, jak by to wyglądało. Zakładając, że mam kod, który należy wykonać przy pierwszym uruchomieniu, będę musiał najpierw zainicjować go w moim kodzie - coś takiego: $ ('p'). MessagePlugin (); potem w kodzie chciałbym wywołać funkcję saySomething w ten sposób $ ('p'). messagePlugin (). saySomething ('coś'); czy nie spowoduje to ponownego zainicjowania wtyczki, a następnie wywołania funkcji? jak by to wyglądało z obudową i opcjami? Dziękuję Ci bardzo. -yuval
Yuval Karmi
1
Jednak w pewnym sensie łamie paradygmat łańcuchowości jQuery.
tvanfosson
może to powinna być najlepsza odpowiedź
Dragouf
3
Za każdym razem, gdy wywołasz messagePlugin (), utworzy nowy obiekt z tymi dwiema funkcjami, prawda?
w00t
4
Głównym problemem związanym z tym podejściem jest to, że nie może on zachować łańcuchowości, $('p').messagePlugin()dopóki nie wywołasz jednej z dwóch funkcji, które zwraca.
Joshua Bambrick
18

Problem z aktualnie wybraną odpowiedzią polega na tym, że tak naprawdę nie tworzysz nowej instancji niestandardowej wtyczki dla każdego elementu w selektorze, tak jak myślisz, że robisz ... w rzeczywistości tworzysz tylko jedną instancję i przekazujesz sam selektor jako zakres.

Zobacz to skrzypce, aby uzyskać głębsze wyjaśnienie.

Zamiast tego musisz zapętlić selektor za pomocą jQuery.each i utworzyć nową instancję niestandardowej wtyczki dla każdego elementu w selektorze.

Oto jak:

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

I działające skrzypce .

Zauważysz, jak w pierwszym skrzypce wszystkie divy są zawsze przesuwane w prawo dokładnie taką samą liczbę pikseli. Jest tak, ponieważ istnieje tylko jeden obiekt opcji dla wszystkich elementów w selektorze.

Stosując powyższą technikę, zauważysz, że w drugim skrzypce każdy div nie jest wyrównany i jest losowo przenoszony (z wyłączeniem pierwszego div, ponieważ jego randomizator jest zawsze ustawiony na 1 w linii 89). Wynika to z tego, że teraz właściwie tworzymy nową instancję niestandardowej wtyczki dla każdego elementu w selektorze. Każdy element ma swój własny obiekt opcji i nie jest zapisywany w selektorze, ale w samej niestandardowej wtyczce.

Oznacza to, że będziesz mógł uzyskać dostęp do metod niestandardowej wtyczki utworzonej na określonym elemencie DOM z nowych selektorów jQuery i nie będziesz zmuszony do buforowania ich, jak w pierwszym skrzypce.

Na przykład, zwróciłoby to tablicę wszystkich obiektów opcji przy użyciu techniki z drugiego skrzypce. Wróciłby niezdefiniowany w pierwszym.

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

W ten sposób będziesz musiał uzyskać dostęp do obiektu opcji w pierwszym skrzypcach i zwróciłby tylko jeden obiekt, a nie ich tablicę:

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

Sugeruję użycie powyższej techniki, a nie tej z obecnie wybranej odpowiedzi.

Kevin Jurkowski
źródło
Dzięki, bardzo mi to pomogło, szczególnie wprowadzając do mnie metodę .data (). Bardzo przydatny. FWIW możesz także uprościć część kodu, korzystając z anonimowych metod.
dalemac
jQuery chainability nie działa przy użyciu tej metody ... $('.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 znacznie ułatwił to dzięki wprowadzeniu fabryki widżetów .

Przykład:

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

});

Inicjalizacja:

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

Wywołanie metody:

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

(Tak budowana jest biblioteka interfejsu użytkownika jQuery .)

Yarin
źródło
@ daniel.sedlacek a) „bardzo zła architektura” - to standardowa architektura widgetów jQuery b) „sprawdzona pod kątem integralności w czasie kompilacji” - JavaScript to dynamiczny język c) „TypeScript” - co?
Yarin
a) to jest argumentum ad populum, b) każde lepsze JS IDE ma uzupełnianie lub
szufladkowanie
To czyste złudzenie, panie Sedlacek.
mystrdat
Według dokumentów: Ten system nazywa się Fabryką Widżetów i jest widoczny jako jQuery.widget jako część jQuery UI 1.8; Można go jednak używać niezależnie od interfejsu użytkownika jQuery. Jak używać $ .widget bez interfejsu użytkownika jQuery?
Airn5475,
13

Prostszym podejściem jest użycie funkcji zagnieżdżonych. Następnie możesz je połączyć w sposób obiektowy. Przykład:

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

A oto jak to nazwać:

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

Bądź jednak ostrożny. Nie można wywołać funkcji zagnieżdżonej, dopóki nie zostanie ona utworzona. Więc nie możesz tego zrobić:

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

Funkcja DoEvenMore nawet nie istnieje, ponieważ funkcja DoSomething nie została jeszcze uruchomiona, co jest wymagane do utworzenia funkcji DoEvenMore. W przypadku większości wtyczek jQuery naprawdę będziesz mieć tylko jeden poziom zagnieżdżonych funkcji, a nie dwa, jak pokazałem tutaj.
Upewnij się tylko, że podczas tworzenia funkcji zagnieżdżonych definiujesz te funkcje na początku ich funkcji nadrzędnej, zanim zostanie wykonany inny kod w funkcji nadrzędnej.

Na koniec zauważ, że element „ten” jest przechowywany w zmiennej o nazwie „_this”. W przypadku funkcji zagnieżdżonych powinieneś zwrócić „_this”, jeśli potrzebujesz odwołania do instancji w wywołującym kliencie. Nie można po prostu zwrócić „this” w zagnieżdżonej funkcji, ponieważ zwróci to odwołanie do funkcji, a nie do instancji jQuery. Zwrócenie referencji jQuery umożliwia połączenie wewnętrznych metod jQuery po powrocie.

Polaris431
źródło
2
To wspaniale - zastanawiam się tylko, dlaczego jQuery wydaje się preferować wywoływanie metod według nazw, tak jak we wzorcu .plugin („method”)?
w00t
6
To nie działa. Jeśli wywołasz wtyczkę w dwóch różnych kontenerach, zmienne wewnętrzne zostaną zastąpione (a mianowicie _this)
mbrochh
Błąd: nie zezwala na pluginContainer.MyPlugin.DoEvenMore (). DoSomething ();
Paul Swetz,
9

Mam go od jQuery Plugin Boilerplate

Opisano również w 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
źródło
Twoja metoda zrywa łańcuch łączący jQuery: $('.first-input').data('pluginName').publicMethod('new value').css('color', red);zwraca Cannot read property 'css' of undefined jsfiddle.net/h8v1k2pL/1
Alex G
@AlexG, podając ten przykład, dodałbyś, return $elementwięc w tym przykładzie zmieniłbyś go na plugin.foo_public_method = function() {/* Your Code */ return $element;}@Salim dzięki za pomoc ... github.com/AndreaLombardo/BootSideMenu/pull/34
CrandellWS
6

Za późno, ale może kiedyś komuś pomoże.

Byłem w takiej samej sytuacji, jak tworzenie wtyczki jQuery za pomocą niektórych metod, a po przeczytaniu niektórych artykułów i niektórych opon tworzę szablon kafelka wtyczki jQuery ( https://github.com/acanimal/jQuery-Plugin-Boilerplate ).

Ponadto opracowuję z nim wtyczkę do zarządzania tagami ( https://github.com/acanimal/tagger.js ) i napisałem dwa posty na blogu wyjaśniające krok po kroku tworzenie wtyczki jQuery ( http: // acuriousanimal. com / blog / 2013/01/15 / Things-i-Learn-Creating-a-jquery-plugin-part-i / ).

EricSonaron
źródło
prawdopodobnie najlepszy post, jaki kiedykolwiek spotkałem na temat tworzenia wtyczek jQuery jako początkujący - dzięki;)
Dex Dave
5

Możesz to zrobić:

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

W ten sposób twój obiekt wtyczek jest przechowywany jako wartość danych w twoim elemencie.

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

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

// call show method
$('#myId').yourPlugin('show');
Mazaher Bazari
źródło
3

Co z używaniem wyzwalaczy? Czy ktoś zna jakąś wadę korzystania z nich? Korzyścią jest to, że wszystkie zmienne wewnętrzne są dostępne za pośrednictwem wyzwalaczy, a kod jest bardzo prosty.

Zobacz na jsfiddle .

Przykładowe użycie

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

Podłącz

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
źródło
1
por. Twój komentarz. Jedyny problem, jaki tu widzę, to prawdopodobnie niewłaściwe użycie systemu zdarzeń. Używanie zdarzeń w celu wywołania funkcji jest nietypowe; wydaje się to przesadą i może być łatwo złamane. Zwykle używasz zdarzeń w sposób publikowania-subskrybowania, np. Funkcja publikuje, że wystąpił jakiś warunek „A”. Inne byty zainteresowane literą „A” nasłuchują komunikatu o „A”, a następnie coś robią. Wydaje się, że używasz go zamiast tego jako polecenia „push”, ale zakładając, że jest tylko jeden słuchacz. Chcesz być ostrożny, aby twoja semantyka nie została złamana przez (innych) dodawanie słuchaczy.
tvanfosson
@tvanfosson Dziękujemy za komentarz. Rozumiem, że nie jest to powszechna technika i może powodować problemy, jeśli ktoś przypadkowo doda detektor zdarzeń, ale jeśli nazwa pochodzi od wtyczki, jest bardzo mało prawdopodobne. Nie wiem o żadnych problemach związanych z wydajnością, ale sam kod wydaje mi się znacznie prostszy niż w przypadku innych rozwiązań, ale coś może mi brakować.
István Ujj-Mészáros
3

Tutaj chcę zasugerować kroki tworzenia prostej wtyczki z argumentami.

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

Tutaj dodaliśmy domyślny obiekt o nazwie paramsi ustawiliśmy domyślne wartości opcji za pomocą extendfunkcji. Stąd, jeśli przekażemy pusty argument, to ustawi wartości domyślne zamiast tego ustawi.

Czytaj więcej: Jak utworzyć wtyczkę JQuery

Gopal Joshi
źródło
Cześć Gopal Joshi, Proszę podać tworzenie wtyczek jquery następnego poziomu. oczekujemy od twojej potrzebnej odpowiedzi.
Sakthi Karthik
Cześć @SakthiKarthik, Off cource Niedługo opublikuję nowy samouczek na moim blogu
Gopal Joshi
1
Cześć @SakthiKarthik, możesz odnieść się do nowego artykułu na temat wtyczki jquery następnego poziomu tutaj sgeek.org/…
Gopal Joshi
2

Spróbuj tego:

$.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
źródło
1

Oto moja wersja tego produktu. Podobnie do tych opublikowanych wcześniej, możesz zadzwonić:

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

- lub uzyskaj bezpośredni dostęp do instancji @ 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
źródło
1

Poniższy wtyczki struktura wykorzystuje jQuery- data()-method zapewnienie interfejsu publicznego do wewnętrznych wtyczki-metod / -Settings (przy zachowaniu jQuery chainability)

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

Teraz możesz wywoływać wewnętrzne metody wtyczek w celu uzyskania dostępu lub modyfikacji danych wtyczki lub odpowiedniego elementu za pomocą tej składni:

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

Tak długo, jak myPublicPluginMethod()zwrócisz bieżący element (this) od wewnątrz, twoja implementacja jQuery-chainability będzie zachowana - więc następujące działania:

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

Oto kilka przykładów (szczegóły - sprawdź to skrzypce ):

// 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
źródło
0

Można to zrobić tak, aby działało w „przyjemny” sposób defineProperty. Gdzie „miły” oznacza bez konieczności ()uzyskiwania przestrzeni nazw wtyczek ani przekazywania nazwy funkcji ciągiem.

Zgodność nit: defineProperty nie działa w starożytnych przeglądarkach, takich jak IE8 i starsze. Uwaga: $.fn.color.blue.apply(foo, args) nie działa, musisz użyć 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();

Łącze JSFiddle

kralyk
źródło
0

Zgodnie ze standardem jquery możesz utworzyć wtyczkę w następujący sposób:

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

Jak wywołać tę wtyczkę?

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

Odniesienie: link

Mahesh
źródło
0

Myślę, że to może ci pomóc ...

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

W powyższym przykładzie stworzyłem prostą wtyczkę podświetlającą jquery. Udostępniłem artykuł, w którym dyskutowałem o tym, jak stworzyć własną wtyczkę jQuery od Basic do Advance. Myślę, że powinieneś to sprawdzić ... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/

Shubham Kumar
źródło
0

Poniżej znajduje się mała wtyczka, która ma metodę ostrzegania w celu debugowania. Zachowaj ten kod w pliku 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
źródło
0

Oto jak to robię:

(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
źródło
-2

To, co zrobiłeś, to zasadniczo rozszerzenie obiektu jQuery.fn.messagePlugin o nową metodę. Co jest przydatne, ale nie w twoim przypadku.

Musisz zrobić, używając tej techniki

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

};

Ale możesz osiągnąć to, co chcesz. Mam na myśli, że jest sposób na zrobienie $ („# mydiv”). MessagePlugin (). SaySomething („hello”); Mój przyjaciel zaczął pisać o luginach i jak rozszerzyć je o łańcuch funkcjonalności tutaj jest link do jego bloga

James
źródło