jquery Plugin Development Boutique Tutorial (get your jquery a step closer) _jquery

Source: Internet
Author: User
Tags anonymous beautifier closure extend advantage

Liu Yongyong's blog is about the most successful place in jquery, and I think its scalability has attracted a lot of developers to develop plug-ins for them, thus building an ecosystem. This is like the big companies scramble to do the platform, the platform to get the world. Apple, Microsoft, Google and other giants, have their own platform and ecological circle.

Learning to use jquery is not difficult, because it is easy to learn, and believe that you have access to jquery will certainly use or familiar with many of its plug-ins. If you want to increase the ability to a higher level, writing a plug-in of their own is a good choice.

This tutorial may not be the most exquisite, but it must be the most meticulous.

jquery Plug-in development model

In the process of software development, a certain design pattern is needed to guide the development, and with the model, we can better organize our code and learn a lot of good practice from these predecessors ' models.

According to the description of the jquery advanced programming, jquery plug-in development methods are mainly three kinds:

Extend jquery through $.extend ()
Adding new methods to jquery via $.fn
Creating a part Factory by $.widget () applying the jquery UI
Usually we use the second method for simple plug-in development, which is relative to the third way of saying simple. The third way is to develop more advanced jquery components, the model developed parts with a lot of jquery built-in features, such as plug-in state information automatically save, a variety of plug-ins are commonly used methods, and so, very intimate, here do not elaborate.

The first is too simple, just adding a static method to the jquery namespace or understanding jquery. So we call the function added through $.extend () directly through the $ symbol call ($.myfunction ()) without the need to select the DOM element ($ (' #example '). MyFunction ()). Take a look at the example below.

$.extend ({
  sayhello:function (name) {
    Console.log (' Hello, ' + (name Name: ' Dude ') + '! ');
  }
)
$.sayhello (); Call
$.sayhello (' wayou ');//Call with parameter

Run Result:

In the code above, a SayHello function is added to jquery via $.extend (), which is then called directly through $. Here you can think that we have completed a simple jquery plugin.

But as you can see, this is a convenient way to define some helper methods. For example, a custom console that outputs a specific format of information, once defined, can be invoked at any point in the program through jquery.

$.extend ({
  log:function (message) {
    var now = new Date (),
      y = now.getfullyear (),
      m = now.getmonth () + 1, ! JavaScript in the month is starting from 0
      d = now.getdate (),
      h = now.gethours (),
      min = Now.getminutes (),
      s = Now.getseconds (), Time
      = y + '/' + M + '/' + D + ' + H + ': ' + min + ': ' + S;
    Console.log (Time + "my App:" + message);
  }
)
$.log (' initializing ... '); Call

This approach, however, does not take advantage of the powerful selectors of jquery, and the second development approach is needed to handle DOM elements and to better apply Plug-ins to selected elements. Most of the plug-ins you see or use are developed in this way.

Plug-in development

Here we will look at the second way of jquery plugin development.

Basic methods

Let's take a look at its basic format:

$.fn.pluginname = function () {
  //your code goes here
}

It's basically adding a method to the $.fn name is our plugin name. Our plug-in code is then expanded in this method.

For example, if we turn all the link colors in the page to red, we can write this plugin as follows:

$.fn.myplugin = function () {
  //In here, this refers to the element selected with jquery
  //example: $ (' a '), then this=$ (' a ')
  this.css (' Color ', ' red ');

Within this function defined by the plug-in name, this refers to the element that we selected with the jquery selector when invoking the plug-in, typically a collection of jquery types. For example, $ (' a ') returns a collection of all a tags on the page, and the collection is already the jquery wrapper type, which means you can invoke other methods of jquery directly when you're working on it without having to wrap it in dollar notation.

So in the above plug-in code, we invoke the jquery CSS () method on this, which is equivalent to calling $ (' a '). css ().

It is important to understand the meaning of this place. So you know why the direct commercial jquery method can be used at the same time in other places this refers to not at the same time we need to use jquery to repackage to call, the following will be mentioned. Beginners easily be the value of this whole halo, but understand it is not difficult.

Now you can go to the page to try our code, put a few links on the page, call the plugin after the link font turned red.

<ul>
	<li>
		<a href= "Http://www.webo.com/liuwayong" > My microblog </a>
	</li>
	<li>
		<a href= "http://http://www.cnblogs.com/Wayou/" > My blog </a>
	</li>
	<li >
		<a href= "http://wayouliu.duapp.com/" > My station </a>
	</li>
</ul>
<p > This is P tag is not a label, I will not be affected </p>
<script src= "jquery-1.11.0.min.js" ></script>
<script Src= "Jquery.myplugin.js" ></script>
<script type= "Text/javascript" >
	$ (function () {
		$ (' a '). Myplugin ();
	})
</script>

Run Result:

The next step is to process each concrete element in the plug-in code instead of a collection, so that we can work on each element accordingly.

We already know that this refers to the collection returned by the jquery selector, so you can handle each element of the collection by invoking the jquery. each () method, but now notice that within each method, this refers to the normal DOM element. If you need to invoke the jquery method then you need to repackage it with $.

For example, now we're going to show the real address of the link in each link, first traversing all a tags through each, and then getting the value of the href attribute and then adding it to the link text.

After the change our plug-in code is:

$.fn.myplugin = function () {
  //here, this refers to the element
  this.css (' Color ', ' red ') selected with jquery;
  This.each (function () {
    //action on each element
    $ (this). Append ("+ $ (This). attr (' href '))
  }"
}

The calling code is the same, and we call this plugin by selecting all the a tags on the page.

Run Result:

By this, you can write a simple jquery plugin. It's not that hard.

Here's an important part of the jquery plugin writing, the receipt of the parameters.

Support Chained calls

We all know that jquery is a often elegant feature that supports chained calls, and you can always invoke other methods after selecting a good DOM element.

To make the plugin not break this chain call, just return it.

$.fn.myplugin = function () {
  //here, this refers to the element
  this.css (' Color ', ' red ') selected with jquery;
  Return This.each (function () {
    //action on each element
    $ (this). Append ("+ $ (This). attr (' href '))
  }"
}

Let the plug-in receive parameters

A strong plugin allows users to customize them at will, which requires us to be more comprehensive when writing plug-ins and to provide the right parameters as far as possible.

For example, now we do not want to make the link only red, we let the user of the plug-in to define what color to display, to do this is very convenient, only the user in the call to pass a parameter. At the same time we receive in the code of the plugin. On the other hand, in order to be flexible, the user can not pass the parameter, the plug-in will give the default value of the parameter.

In the process of receiving a plug-in parameter, the Extend method of jquery is usually used, as mentioned above, but that is when a single object is passed to the Extend method, and the object is merged into jquery so that we can invoke the method contained in the new merged object on jquery. Like the example above. When you pass more than one parameter to the Extend method, it merges all the parameter objects into the first one. Also, if an object has an attribute of the same name, the one behind the merge overwrites the previous.

With this, we can define an object in the plug-in that holds the default value of the plug-in parameter, combine the received parameter object with the default object, and finally implement the parameter with the specified value, and use the plug-in default value for the parameter that is not specified.

For demonstration convenience, specify a parameter fontsize to allow the font size to be set when invoking Plug-ins.

$.fn.myplugin = function (options) {
  var defaults = {
    ' color ': ' Red ',
    ' fontsize ': ' 12px '
  };
  var settings = $.extend (defaults, options);
  Return this.css ({
    ' color ': Settings.color,
    ' fontsize ': Settings.fontsize
  });
}

Now, when we call the specified color, the font size is not specified, will use the default value 12px in the plug-in.

$ (' a '). Myplugin ({
  ' color ': ' #2C9929 '
});

Run Result:

Specify both color and font size:

$ (' a '). Myplugin ({
  ' color ': ' #2C9929 ', '
  fontsize ': ' 20px '
});

Protect the default parameters.

Note that the above code will change the value of the defaults when it calls extend. This is not good, because some of the things it does as a plugin should remain the same, and if you have to use these defaults in subsequent code, it has been changed by the parameters that the user has passed in when you visit it again.

A good practice is to make a new empty object the first parameter of $.extend, the defaults and the parameter object passed by the user followed, the benefit of which is that all values are merged onto this empty object, protecting the default value inside the plugin.

$.fn.myplugin = function (options) {
  var defaults = {
    ' color ': ' Red ',
    ' fontsize ': ' 12px '
  };
  var settings = $.extend ({},defaults, options);//An empty object as the first argument return
  this.css ({
    ' color ': Settings.color,
    ' fontsize ': Settings.fontsize
  });

By this, the plug-in can receive and process parameters, you can write a more robust and flexible plug-ins. To write a complex plug-in, the amount of code is very large, how to organize the code has become a need to face the problem, there is no good way to organize the code, the overall feeling will be messy, but also difficult to maintain, so the plug-ins all the methods of the property packaging to an object, with object-oriented thinking to develop, Will undoubtedly make the work much easier.

Object-oriented plug-in development

Why should there be object-oriented thinking, because if you don't, you might want to define a function when you need a method, and when you need another method, define a function, and then, when you need a variable, define the variables that are scattered around the code without any rules.

Or the old problem, not convenient maintenance, nor clear enough. Of course, these problems are not reflected in the small size of the code.

If you define the important variables that you want on the object's properties, the function becomes the object's method, and when we need it, it's easy to manage, and it doesn't affect the external namespace, because all of these variable names and the method names are inside the object.

Then the above example, we can abstract this plugin into a landscaping object, because his function is to set the color Ah ah what, of course, we can also add other features such as the set underline ah what. Of course it's a bit of a fuss to abstract this example into an object, just for demonstration purposes. Later I might introduce a jquery plugin I wrote sliphover, where the code is more, such a pattern can be used.

So we create a new object named Beautifier, and then we use this object in the plugin to encode it.

Defines the constructor of the Beautifier
var beautifier = function (Ele, opt) {this
  . $element = ele,
  this.defaults = {
    ' Color ': ' Red ',
    ' fontsize ': ' 12px ',
    ' textdecoration ': ' None '
  },
  this.options = $.extend ({}, This.defaults, opt)
}
//define Beautifier method
Beautifier.prototype = {
  beautify:function () {
    return this. $element. css ({
      ' color ': This.options.color,
      ' fontsize ': this.options.fontSize,
      ' TextDecoration ': This.options.textDecoration
    });
  }
Using the Beautifier object
$.fn.myplugin = function (options) {
  ///Create Beautifier entity
  var beautifier = new Beautifier (this, options);
  Call its method return
  beautifier.beautify ();
}

Through the above transformation, our code has become more object-oriented, and better maintenance and understanding, to add new features in the new method, simply add new variables and methods to the object, and then instantiate in the plug-in can invoke the new additions.

Plug-in calls are the same, our code changes do not affect the other parts of the plug-in, but the code's organizational structure has changed.

$ (function () {
  $ (' a '). Myplugin ({
    ' color ': ' #2C9929 ', '
    fontsize ': ' 20px '
  })

Specifies that the text is underlined (the functionality we add in the Beautifier object, which is not underlined by default, as in the example above):

$ (function () {
  $ (' a '). Myplugin ({
    ' color ': ' #2C9929 ', '
    fontsize ': ' 20px ',
    ' textdecoration '): ' Underline '
  })

Here, you can better write complex plug-ins and organize your code well. When we look back at the code above, there is still room for improvement. This is the following about namespaces and variables of what, some miscellaneous.

About namespaces

Not only the development of jquery Plug-ins, we write any JS code should pay attention to the point is not to pollute the global namespace. Because as you code increases, if intentionally or unintentionally in the global scope of the definition of some variables, it is difficult to maintain, but also easy to write with other people's code conflict.

For example, you add a variable status to the Global window object in your code to hold the state, while the page references another other person's written library, and adds a variable with the same name globally, and the end result is definitely not what you want. Therefore, we do not have to define variables as a whole as a last resort.

A good practice is to always use the call anonymous function to wrap your code, so that you can safely safely use it anywhere, with absolutely no conflict.

Wrapping your code with a self-invoking anonymous function

We know that JavaScript cannot easily create scopes with curly braces, but functions can form a scope, and code within a domain cannot be accessed by outsiders. If we put our own code into a function, then the global namespace will not be polluted, and no other code will be conflicted.

As above we define a beautifier global variable, which is attached to the global Window object, and to prevent this from happening, you might say, put all the code inside the jquery plug-in definition code, which is put in the $.fn.myplugin. Doing so is also a choice. But the code that we actually have with the plug-in definition becomes bloated, and in $.fn.myplugin we should be more focused on the invocation of plug-ins and how to interact with jquery.

So keep the original code unchanged and we'll wrap all the code with the anonymous function from the call.

(function () {
  //define Beautifier constructor
  var beautifier = function (Ele, opt) {this
    . $element = Ele,
    This.defaults = {
      ' color ': ' Red ',
      ' fontsize ': ' 12px ',
      ' textdecoration ': ' None '
    },
    this.options = $.extend ({}, this.defaults, opt)
  }
  //define Beautifier method
  Beautifier.prototype = {
    beautify: function () {return this
      . $element. css ({
        ' color ': This.options.color,
        ' fontsize ': This.options.fontSize,
        ' textdecoration ': This.options.textDecoration
      });
    }
  Using the Beautifier object
  $.fn.myplugin = function (options) {
    ///Create Beautifier entity
    var beautifier = new Beautifier (this, options);
    Call its method return
    beautifier.beautify ();
  }
}) ();

The benefits of doing so are as stated above. Another advantage is that the code inside the anonymous function will be executed the first time, the page is ready, the above code will be ready for the plug-in to facilitate the use of plug-ins in the following code.

So far it seems to be close to perfection. If you take into account some other factors, such as we put this code on the page, the previous code written by others did not end with a semicolon, or the previous code will be window, undefined, such as the system variables or keywords modified, just in our own code inside the use, The result is unpredictable, and that's not what we want. I know you're not quite sure yet, here's a detailed description.

Passing system variables to internal plug-ins as variables

Look at the code below, what do you think will happen to him?

var foo=function () {
  //Others ' code
}//Note there is no semicolon ending

//start our code ...
(function () {
  //our code ...
  alert (' hello! ');
}) ();

Other people's code is also normal work, but the last definition of the function did not end with a semicolon, and then when the page to introduce our plug-ins, the error, our code can not be properly executed.

The reason is that the first pair of parentheses that we use to act as a calling anonymous function is connected to the function defined above, because there is no semicolon in the middle, our code cannot parse correctly, so the error is not correct.

So the good thing is that we add a semicolon at the beginning of the code, which is a good habit at all times.

var foo=function () {
  //Others ' code
}//Note there is no semicolon ending

//start our code ...
;(function () {
  //our code ...
  alert (' hello! ');
}) ();

At the same time, it is a good practice to pass the system variables in the form of parameters to the internal plug-ins.

When we do this, Windows and other system variables inside the plug-in has a local reference, can improve access speed, there will be some performance improvement

Finally, we get a very safe and well structured code:

;(function ($,window,document,undefined) {
  //our code ...
  //blah blah blah ...
}) (jquery,window,document);

And as for this undefined, a little more interesting, in order to get the undefined that has not been modified, we did not pass this parameter, but received it when receiving it, because the actual did not pass, so ' undefined ' that position received is real ' Undefined ' up. is not a bit of hack taste, it is worth to understand the technology, of course, not I invented, are from the experience of the predecessors to learn.

So in the end our plugin became this way:

;(function ($, window, document,undefined) {
  //define Beautifier's constructor
  var beautifier = function (Ele, opt) {this
    . $element = Ele,
    this.defaults = {
      ' color ': ' Red ',
      ' fontsize ': ' 12px ',
      ' textdecoration ': ' None '
    } ,
    this.options = $.extend ({}, this.defaults, opt)
  }
  //define Beautifier method
  Beautifier.prototype = {
    beautify:function () {return this
      . $element. css ({
        ' color ': This.options.color,
        ' fontsize '): This.options.fontSize,
        ' textdecoration ': This.options.textDecoration
      });
    }
  Using the Beautifier object
  $.fn.myplugin = function (options) {
    ///Create Beautifier entity
    var beautifier = new Beautifier (this, options);
    Call its method return
    beautifier.beautify ();
  }
}) (JQuery, window, document);

A safe, well structured, well-organized plug-in is completed.

About variable definitions and naming

Now talk about the variables and methods, such as naming, there is no hard rules, but in order to standardize, to follow some agreement is still very necessary.

Variable definition: A good practice is to define the name of the variable to be used together with a var keyword at the beginning of the code, separated by commas between the variable names. There are two reasons:

One is easy to understand, know the following code will use which variables, while the code appears neat and regular, but also convenient management, variable definition and logical code separate;
Second, because all variables and function names in JavaScript are automatically elevated, also called JavaScript's hoist feature, even if you insert the definition of a variable into the logical code, the declaration of these variables is elevated to the top of the current scope during the parsing run of the code, So we define a variable at the beginning of a scope as a more logical approach. Again, of course, this is just a convention, not a requirement.

Variables and function names generally use the Hump nomenclature (CamelCase), which is the first word in lowercase, followed by the first letter of the word, such as resultarray,requestanimationframe. For constants, all letters are capitalized and multiple words are separated by an underscore, such as width=100,brush_color= ' #00ff00 '. When a variable is a jquery type, it is recommended to start with $, but it is often very convenient to use it later, because it is easy to distinguish it from ordinary variables, and when you see a $ beginning we know that it is a jquery type that can directly invoke jquery-related methods on it. such as Var $element =$ (' a '); It can then be easily used in later code and easily distinguishable from other variables.

The use of quotes: Since all this has nothing to do with the plugin theme, here's one more word, use double quotes in general HTML code, and use single quotes in JavaScript, as shown in the following code:

var name = ' Wayou ';
document.getElementById (' example '). InnerHTML = ' < a href= ' http://wayouliu.duapp.com/' > ' +name+ ' </a> '; Href= "..." Keep double quotes in HTML, keep single quotes in JavaScript

On the one hand, the HTML code is used in the double quotes, on the other hand, in the JavaScript in quotation marks in the need for quotation marks, we require a single double quotation mark between the write is a valid statement, unless you use the signifier that is also possible. Furthermore, insisting on such a unification would keep the code style consistent, and there would be no strings wrapped in double quotes, and in the other place, single quotes.

Code obfuscation and compression

After the above steps, has been small has become. Perhaps you have noticed very early, you download the plugin inside, generally will provide a compressed version generally in the filename with a ' min ' words. Which is the meaning of minified, compress the condensed version. And we usually use jquery is the official website of the compression version, Jquery.min.js.

The compression here does not mean that the code does function compression, but instead replaces it with a shorter name by changing the name of the variable in the code, the method function name, and so on, and deletes the annotation (if any) to remove the blank between the code and the condensed version of the line. At the same time, because the various names in the code have been replaced, others can not read and distinguish their logic, also played a role in confusing the code.

The benefits of compression

After the source code after confusing compression, the volume is greatly reduced, so that codes become lightweight, while speeding up the download speed, both sides load faster. For example, the normal jquery v1.11.0 source code is 276KB, and the compressed version only 94.1kb! The volume is reduced by more than half. This reduction in the volume of the file download speed can not be underestimated.
After the compression is confusing, can the code still read? Of course not, so incidentally also played a role in code protection. Of course, only for you to write some cool code and do not want someone to copy the situation. For the jquery community, here itself is the open source world, while JavaScript is not really a real way to prevent others from viewing your code, after all, there is obfuscation tool, where the code compression is more or the above mentioned the role of the compressed file, At the same time, to some extent to prevent others plagiarism.
Tools

The tools used are highly valued by Google-developed closure Compiler. The tool requires support from the Java environment, so you may need to install the JRE first on the machine before you can use it to get closure.

At the same time there are a lot of friends online code obfuscation compression tool, it is also very convenient to use. These tools are a lot of search.

Plugin Publishing

This step is not necessary, but in the spirit of doing things in a holistic manner, you may also want more people to see or use your plugin.

First you need to put the plug-in code on the GitHub to create a service Hook, so that after you update the plugin, jquery can automatically get the new version of the information and then display in the Plug-in Center page. about how to send code to GitHub, you go to download GitHub provided by the client tools, you will know how to operate, very convenient. About creating service hooks in GitHub is only a matter of a few points. Here is a screenshot of the introduction.
Then you need to make a JSON-formatted list file that includes basic information about the plugin, and the format and parameters can be learned in the jquery website Plugin release Guide page, which provides a sample file that I wrote before in a jquery plugin sliphover:

{"Name": "Sliphover", "title": "Sliphover", "description": "Apply direction aware 2d/3d hover effect to images", "keywords": ["Direction-aware", "animation", "effect", "hover", "image", "overlay", "gallery "]," version ":" 1.1.1 "," author ": {" name ":" Wayou "," email ":" liuwayong@gmail.com "," url ":" Https://gi Thub.com/wayou "}," maintainers ": [{" Name ":" Wayou "," email ":" liuwayong@gmail.com "," url ":" H Ttps://github.com/wayou '}], ' licenses ': [{' type ': ' MIT ', ' url ': ' Https://github.com/jquery/jqu Ery-color/blob/2.1.2/mit-license.txt "}]," Bugs ":" Https://github.com/Wayou/sliphover/issues "," homepage ":" Htt p://wayou.github.io/sliphover/"," Docs ":" http://wayou.github.io/SlipHover/"," Demo ":" http://wayou.github.io/ sliphover/"," Download ":" Https://github.com/Wayou/SlipHover/zipball/master "," dependencies ": {" jquery ":" >=1. " 5 "}}

You can then publish the plugin by executing the existing Git code in the root directory of the plug-in. Where 0.1.0 is the version number, each time your plug-in has a new version of the release only need to update the version above, create a new tag, so the jquery plug-in center will automatically get the new version of information

$ git tag 0.1.0
$ Git push origin--tags

GitHub Service Hook

1 Click to set the right menu for the item

2 Enter the Settings page and click ' Webhooks & Services '

3 then click on the ' Configure Services ' button on the right side of the homepage

4 then appears a very long list, down to find jquery Plugins click

5 Click on the ' Update Settings ' button after clicking the check box

The setup is complete.

Reference:

    1. jquery Website Learning Center about plug-in development article: http://learn.jquery.com/plugins/
    2. jquery Website Plugin Center: http://plugins.jquery.com/
    3. jquery website Plugin release Guide: http://plugins.jquery.com/docs/publish/
    4. JavaScript hoist:http://www.adequatelygood.com/javascript-scoping-and-hoisting.html
    5. Google Web Developer tool:https://developers.google.com/closure/

Original: Liu Yongyong's Blog

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.