Use your business data to your advantage with the help of Syncfusion’s new data science offerings. Discover how a custom big data solution can provide your company with valuable predictions about key market trends.

Defining our own default plugin structure

To make things easier to remember and apply, we are going to start off with the definition of what we will be referring to when speaking of the basic template that all the plugins we are going to develop should conform to.

Actually, we have already had a quick look at it earlier in the previous chapter, but there's something more definitely worth saying.

From now on, we will call the following code the default structure for our plugins. This is what we will promptly copy and paste into each file we're going to write a plugin into.

Needless to say, the this.each loop iterates all of the matching elements. We return the jQuery object (this) to allow chaining. We extend the jQuery.fn object; all of the code will be put inside the function.

Also:

The file name of every plugin we're going to develop will bejquery.PLUGINNAME.js.

For the moment, remember to always avoid referring to the jQuery object with the dollar sign ($), to prevent possible conflicts with other libraries. We'll get to using aliases very soon.

All of the functions that we write to make our plugin work should be private and not accessible from outside, in an attempt to avoid cluttering and possible backwards incompatibility.

If not from the very start, at least at the end, a user will be able to specify options to control the plugin behavior.

Default options for the plugin will be publicly accessible to allow for easier customization with minimal code.

The directory that the plugin resides in will also contain two other files, by default:

index.html: This is our test page.

jquery.js: This is the jQuery library that we need to make things work.

Setting the basics for our first plugin

As our first plugin, we might want to create something uncomplicated but somewhat impressive: what about something that, when the cursor is hovering over an element, substitutes the text contained with some words of our choice?

Time for action – our first plugin, Part I

Getting started in creating jQuery plugins in not difficult at all. For example, creating this simple plugin should help us in understanding how things actually work.

Given that our plugin name is txtHover, create all the directories and files we need by default, and copy over the jquery.js file.

Copy the default structure for our plugins to the plugin file and make sure the function is named accordingly. It should look like this:

Unfortunately, the result is neither fancy nor satisfactory—something we've experienced earlier too. But we're just getting started; we won't stop here this time!

What just happened?

The plugin is working correctly so far. When the page loads, the text is changed to what we had defined into the plugin code.

However, there are a couple of things to pay attention to:

The function text() from the jQuery API expects either one or no arguments to be passed: if there is no argument the function returns the current content of the selected element. The text string passed as an argument substitutes the element text otherwise.

There are, however, some similarities with the html() function, which treats the text it operates on as if it were HTML code. That is, passing any tag to the html() function results in having the element possibly containing other elements after the operation (also, the same applies for getting HTML code from within the element), whereas the this function will just treat the HTML code as plain text and not affect any element hierarchy.

The fact that the text cannot be changed, unless we directly modify the code of the plugin.

Getting a step farther

Despite the good realization, our plugin still misses the point. Our goal was to activate the text substitution whenever the mouse pointer hovered over the text to be replaced, whereas our current implementation does it right after the page is loaded.

We put it inside the "document ready" statement, after all!

Time for action – our first plugin, Part II: Hovering

By adding little pieces of code one at a time, we can easily understand what we are going to do and which is the best layout for our plugin. Activating the plugin whenever the mouse pointer hovers over the selected elements is surely another little step that adds up to reach our final goal.

Back to our plugin file, we have to change the code so that the whole mechanism activates when the hover event is triggered. jQuery provides a function called hover(), which we can use to achieve our objective:

The result is somewhat better now: the text is changed when we leave the pointer on the paragraph, and is changed again to its original form once the pointer is moved away.

What just happened?

We might be a little more satisfied with this evolution of our plugin, even though it's far from complete.

Its functioning is fairly straightforward: we have made use of a variable (oldTxt) to store the old content, and we then have proceeded to using two anonymous functions (function(){ }), passed as arguments to the hover() function, to handle the mouse hover event (write our string) and the mouse out event (text back to original).

There's still something to do though:

We have used far too many instances of $(this) in our code and, on a larger scale application, a lot of memory would be wasted this way. It will be incredibly better for performance to make up a variable and use it every time we refer to the element with $(this).

The text cannot be changed, unless we directly modify the code of the plugin.

Have a go hero – html () versus text ()

Read the documentation for the html() function.

Create a plugin that, once the mouse pointer hovers over an element, displays the HTML code of its content. The content should then change back to normal once the mouse pointer is moved away from that space.

What happens if the html() and text() functions are used one inside the other, that is, $(sel).text($(sel).html()) or $(sel).html($(sel).text())? Just play around a little bit.

Dealing with options

An aspect that we left out in the creation of our plugin is the one concerning options and, thus, customization.

Implementing options not only will drastically increase the flexibility and ease of customization of the plugin, but will also quicken later modifications by the author himself or herself, as it results in the whole code being simpler to understand and the important bits would be all grouped together.

Time for action – our first plugin, Part III: Options

To allow for options to be specified and the behavior of our plugin to be customized and modified to users' liking, we need options.

The code we use for our plugin will be modified to look like the following:

And the result would look something like this, with the text changed to whatever we like:

What just happened?

The structure we've just used to get our plugin packed with options is quite flexible and easily extensible.

We first made sure the function definition would include an argument (that is, options) for settings to be specified. The options object must be formatted following the inline object creation method (that is, { option1: value1, option2: value2 } and so on).

But what would happen if the user does not specify any options? Or, if we are dealing with a number of options, wouldn't writing the same lines of code everytime to reset option values be incredibly annoying?

Instead, we create a new (plain) object (default) in which we store the default values of options we plan on accepting as valid. This way, users may check if the default value is acceptable to them and either leave it untouched (the plugin will then use the default value) or change it to their needs, resulting in the plugin making use of the customized value for that particular option.

The very next line is the way jQuery is instructed to combine the two objects. If any of the options we are going to make use of later on in the code (and want the user to be able to modify) is not passed to the function, we use the default one instead.

What we'll get at the end is another object (o) with the values we need for the plugin to work with. From this moment onwards, we'll use this object's values to access options we need during development.

The rest of the code is left untouched, except for the o.txt part that replaces the old string. Users are now able to choose what they want to replace the original content with.

Also, the keyword $(this), much abused of in the previous version, has been replaced with the variable e, into which all of the information of the element has been copied. In a large-scale environment, this little tweak will result in a huge boost to the script performance.

Have a go hero – adding colors

Accessing and modifying an element's CSS properties through the css() method is not only possible, but quite simple and straightforward too.

The css() method works very much like the text() and html() ones do, with the difference being that it always expects at least one argument to be passed, as the first parameter is responsible for selecting which property we want to get access to.

Using your knowledge about the above-mentioned method and what you've just learned from the latest Time for action, extend the plugin so it accepts two other options: fgColor and bgColor.

Needless to say, these two options make the users able to change the element's background and foreground color whenever the mouse pointer hovers over the element. When the mouse pointer gets off the area, colors should revert to original.

Keep in mind that, if either of those two options is not passed, the user does not intend to have the color(s) changed at all and they should appear as they already are, not just as black text on white background!

Using functions inside the plugin

Repetitive tasks are boring. And this is the reason functions exist. However, how do functions interact with the code of a plugin?

Very simply, every function declared outside the plugin's own code (note that defining a function right inside it is allowed) is accessible as it would be in any other piece of code.

Time for action – our first plugin, Part IV: Functions

For testing reasons only, we need a debug function to tell us what happens at certain points when the code runs. This will also help us in understanding when and how functions are accessible from a particular portion of code.

We could add the following function (from our previous log script) at the very beginning of the plugin file:

There's still some trouble, though: what happens if we use the debug function outside the plugin file?

We expect it not to be accessible or to be somehow unusable, as we have declared it inside the plugin file and it was intended for use inside the plugin only.

If we try to put a sample call right after the "document ready" statement, we can see the function to be actually accessible from everywhere in the code.

$(document).ready(function() { _debug("Hello, this is a test call."); $("p#one").txtHover({ txt: 'This is some custom text.' });});

What just happened?

Dealing with functions shouldn't be much of a problem. We are supposed to be used to making heavy use of them.

However, the point is their accessibility from different parts of the code. At first, we create the function(s) we need without thinking about the number of problems that could arise if we do not protect them and struggle to make the functions we use in our plugin private (that is, not accessible from outside our plugin).

What we must be aware of are the issues we could bump into when defining a certain function in our plugin file without thinking that the very same name we originally thought would have been unique (for example, _debug) has been used somewhere else in the code to name a function whose goal is completely different.

The correct (or, at least, expected) behavior of our plugin is compromised and for no reason should we permit such a stupid error.

Another point of particular interest, in case it's not been noticed before, is the way the o object is used everywhere at any point of time that we need to refer to the current set of options, whereas e is the current element being processed.

Have a go hero – experimenting with functions

Play around with functions. Try to define some functions nearly everywhere it is possible and try calling them from other parts of the code to see what happens, which functions override which, and the difference between calls to functions with one or more arguments.

Also, make sure you notice where (that is, in what parts of code) a function can be defined and where, instead, it's not possible.

Is it possible to define a function inside the document ready statement? If so, what would it mean and is there any advantage?

Closures: Making functions private

With the aim of keeping our own functions, those needed by our plugin only, private, so that others cannot access and misuse them, we're going on to discovering closures.

Time for action – our first plugin, Part V: Closures

Closures make it possible for the developer (that is, us) to avoid creating functions in the main namespace and keep them private to avoid problems with naming, backward compatibility issues, and excessive cluttering.

We're now going to add a function to the index.html file, called _debug.

This new function will take one argument (just like our plugin's one) and will do nothing more than just display an alert reporting some random text.

function _debug(argument){ // Note we don't make use of the 'argument' // we just need it for the function to look // exactly the same as our plugin's debug function alert("Hi, this is the fake debug function.");}

$(document).ready(function() { _debug("Hello, this is a test call."); $("p#one").txtHover({ txt: 'This is some custom text.' });});

Now, on loading the page, how does the result appear? Is it what you expected? The newly created function completely replaced our plugin's function, making the behavior definitely not the same.

What would happen if we use closures to prevent this type of inconvenience from happening?

Here is how closures work. This is how the plugin code should look now:

And here is how the page looks now, after we have modified the plugin code. When the page loads, we get to see the pop up:

But when we hover the mouse pointer over the text we actually see what we expected to see:

What just happened?

Using closures is definitely a best practice that everyone should follow.

Not only does it allow functions to be defined for the plugin only (keeping them private and not accessible from outside the plugin's code), but many other advantages come as well.

The way in which closures operate is quite simple after all. By creating a closure, several things actually happen: first of all, closures create a function with $ as its parameter.

Then that function is immediately called with the value jQuery, which gets mapped onto the $, letting us use the $ sign without the fear of creating any kind of issue.

When we first defined the fake debug function, we probably didn't think it would've overwritten the whole content of the plugin's original function. Perhaps it would've given an error; or just the first call (the one right before the plugin call) would've been compromised.

Actually, this behavior is perfectly explainable. Looking at the file structure, we see the jquery.js file is included first, then comes the plugin, and finally the inline script part containing the fake function and the "document ready" statement.

This means the latest part quite naturally overwrites the earlier ones.

Thus, having defined the fake debug function at the very end, it obviously overwrites the old debug function coming before it.

The whole example would have been quite different if we had put the above-mentioned function before the inclusion of the plugin file, in which case the dynamics would have been worthy of notice.

In the latest version, the original debug function is kept private and thus the fake function cannot overwrite it, resulting in the correct behavior that we would've expected from the very beginning. As the page loads, a pop up is displayed with some text, whereas the hovering effect still works correctly thanks to closures preventing the functions declared inside them from being publicly visible.

Have a go hero – avoid conflicts

With closures in mind, try to replace all the jQuery words with the dollar sign, as if you where using normal jQuery syntax in a normal script.

If you even try to throw in some conflicts over the dollar sign, which is often used by other libraries as well (for example, by including another JavaScript library and using both to get something done), you can see the plugin still works correctly.

In fact, apart from keeping functions to themselves, this closure alias the word jQuery to the symbol $, acting as the noConflict() function would on the plugin code.

This is particularly handy because it allows the normal syntax, the one we're all most used to and that comes out without thinking, to be used with no worries at all.

Summary

This article has covered, step by step, the creation of a simple plugin. At the very beginning, the plugin was really simple and far from being well thought out. However, by the end of the process we ended up with a simple plugin, capable of doing several things, and a structure evolving constantly after each step.

Perhaps without having noticed, we've taken care of event handling (for example, the hovering effect, with its hover and leave events), customization, modification, user personalization (making a set of options available and thinking about the default values), security, compatibility issues, and aliasing (making the plugin work within closures and having the possibility to use the dollar sign ($) again).

Alerts & Offers

Series & Level

We understand your time is important. Uniquely amongst the major publishers, we seek to develop and publish the broadest range of learning and information products on each technology. Every Packt product delivers a specific learning pathway, broadly defined by the Series type. This structured approach enables you to select the pathway which best suits your knowledge level, learning style and task objectives.

Learning

As a new user, these step-by-step tutorial guides will give you all the practical skills necessary to become competent and efficient.

Beginner's Guide

Friendly, informal tutorials that provide a practical introduction using examples, activities, and challenges.

Essentials

Fast paced, concentrated introductions showing the quickest way to put the tool to work in the real world.

Cookbook

A collection of practical self-contained recipes that all users of the technology will find useful for building more powerful and reliable systems.

Blueprints

Guides you through the most common types of project you'll encounter, giving you end-to-end guidance on how to build your specific solution quickly and reliably.

Mastering

Take your skills to the next level with advanced tutorials that will give you confidence to master the tool's most powerful features.

Starting

Accessible to readers adopting the topic, these titles get you into the tool or technology so that you can become an effective user.

Progressing

Building on core skills you already have, these titles share solutions and expertise so you become a highly productive power user.