1, start

You can write a jQuery plug-in by adding a new function to jquery.fn. The name of the property is the name of your plugin:

JQuery.fn. MyPlugin = function(){// Start writing your code! };Copy the code

But what happened to the beloved dollar sign, the $? It is jQuery, but to ensure that your plugin does not conflict with other libraries that use $, it is best to use an anonymous function that executes immediately and takes jQuery as an argument so that other libraries can safely use the $symbol.

(function($){$.fn.myplugin = function() {// }; })( jQuery );Copy the code

So much the better. Inside closures, you can safely use the $symbol ~

2. Context

Now we’re ready to write our code, but before we do, I have to say something about context. Within the scope of the plug-in, the this keyword points to the jQuery object. It’s easy to misunderstand this, because in normal jQuery usage, this usually refers to a DOM element. Without understanding this, you will often use $to wrap it again.

(function ($) {$. Fn. MyPlugin = function () {/ / there is no need to use $(this) / / $(this) and $($(' # element)) is the same as this. FadeIn (' normal ', Function (){// this is a DOM element}); }; })( jQuery ); $('#element').myPlugin();Copy the code

3. Basic development

Next, write a plug-in that works.

 (function( $ ){  
    $.fn.maxHeight = function() {  
      var max = 0;  
      this.each(function() {  
        max = Math.max( max, $(this).height() );  
      });  
      return max;  
    };  
  })( jQuery );  
  var tallest = $('div').maxHeight();  
Copy the code

Height – A simple plug-in that returns the height of the largest div on the page by calling height().

4. Maintain the characteristics of chain development

The previous example returned an integer, but in most cases, a plug-in simply modifiers the collected element and then returns the element for the next person on the chain to use. This is the beauty of jQuery’s design and one of the reasons jQuery is so popular. In order to be chain-able, you have to return this.

(function( $ ){ $.fn.lockDimensions = function( type ) { return this.each(function() { var $this = $(this); if ( ! type || type == 'width' ) { $this.width( $this.width() ); } if ( ! type || type == 'height' ) { $this.height( $this.height() ); }}); }; })( jQuery ); $('div').lockDimensions('width').css('color','red');Copy the code

Because the plug-in returns this, it guarantees chaining, so you can continue to make changes using jQuery methods, such as CSS (). If your plugin does not return a simple value, you should usually return this. And, as you might expect, the parameters you pass in can also be accessed in your plugin. So in this example, you can access type.

5. Defaults and options

For complex, customizable plug-ins, it is best to provide a set of defaults that can be extended when called. Instead of calling a function with a bunch of arguments, you pass in arguments that need to be replaced. Here’s what you can do:

(function( $ ){ $.fn.tooltip = function( options ) { var settings = { 'location' : 'top', 'background-color' : 'blue' }; Return this.each(function() {if (options) {$.extend(Settings, options); } // other code}); }; })( jQuery ); $('div').tooltip({'location':'left'});Copy the code

In this example, the default location will be replaced with ‘left’ and background-color will remain ‘blue’ after the plug-in is called. This ensures a high degree of configurability without requiring the developer to define all possible options.

6. Namespace

Proper namespaces are important in plug-in development to ensure that your plug-in is not overwritten by other plug-ins, or by other code on the page. Namespaces can help you live longer because you can record your own methods, events, data, etc. Under no circumstances should you add more than one method to jquery.fn in a single plugin. Such as:

(function($){$.fn.tooltip = function(options){// so}; $.fn.tooltipShow = function() {// yes}; $.fn.tooltipHide = function() {// bad}; $.fn.tooltipUpdate = function(content) {// }; })( jQuery );Copy the code

Not recommended, messing up the $.fn namespace. To correct this, you can put all methods into one object and call them with different arguments.

(function( $ ){ var methods = { init : function( options ) { // THIS }, show : function( ) { // IS }, hide : function( ) { // GOOD }, update : function( content ) { // !!! }}; $.fn.tooltip = function( method ) { // Method calling logic 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 exist on jQuery.tooltip' ); }}; })( jQuery ); $('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 methodCopy the code

JQuery’s own extensions also use this plug-in structure.

B) Event binding event namespaces are relatively unknown. If your plug-in is bound to an event, it is best to put it in a namespace. This way, if you need to unbind later, it won’t affect other functions bound to the event. You can use “.” to increase the namespace.

(function( $ ){ var methods = { init : function( options ) { return this.each(function(){ $(window).bind('resize.tooltip', methods.reposition); }); }, destroy : function( ) { return this.each(function(){ $(window).unbind('.tooltip'); }) }, reposition : function( ) { // ... }, show : function( ) { // ... }, hide : function( ) { // ... }, update : function( content ) { // ... }}; $.fn.tooltip = function( 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 exist on jQuery.tooltip' ); }}; })( jQuery ); $('#fun').tooltip(); // Some time later... $('#fun').tooltip('destroy');Copy the code

In this example, the tooltip is initialized in the init method, which binds the reposition method to the tooltip namespace of the window object’s resize event. Later, if the developer needs to remove the tooltip, we can unbind the binding. This will not affect other methods that bind to the window object’s resize event.

C) When developing plug-ins, you often have the need to maintain state or check if your plug-in has been initialized. Using jQuery’s data method is a great way to keep variables. However, instead of storing variables separately, we put them in an object so that they can be accessed uniformly under a namespace.

(function( $ ){ var methods = { init : function( options ) { return this.each(function(){ var $this = $(this), data = $this.data('tooltip'), tooltip = $('<div />', { text : $this.attr('title') }); // If the plugin hasn't been initialized yet if ( ! data ) { /* Do more setup stuff here */ $(this).data('tooltip', { target : $this, tooltip : tooltip }); }}); }, destroy : function( ) { return this.each(function(){ var $this = $(this), data = $this.data('tooltip'); // Namespacing FTW $(window).unbind('.tooltip'); data.tooltip.remove(); $this.removeData('tooltip'); }) }, reposition : function( ) { // ... }, show : function( ) { // ... }, hide : function( ) { // ... }, update : function( content ) { // ... }}; $.fn.tooltip = function( 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 exist on jQuery.tooltip' ); }}; })( jQuery );Copy the code

Using the data method helps you maintain variables and state between methods in your plug-in. Putting variables in a single object makes it easy to access and easy to remove. Writing jQuery plug-ins can take full advantage of the library, abstracting out common functions and “recycling” them. Here’s a quick summary:

When using (the function ($) {/ / the plugin}) (jQuery); ● Do not repeatedly wrap your plugin in the original scope of your plugin ● Return this pointer to ensure that it is chain-able unless you return the original value ● Do not use a string of arguments, use an object instead, and set the default value ● A plugin, do not attach multiple functions to jquery.fn ● For your functions, events, Data is attached to a namespace