Hackernoon logoWhat I Learnt From Creating A jQuery Plugin by@kelvinzhao

What I Learnt From Creating A jQuery Plugin

image
Kelvin Zhao Hacker Noon profile picture

Kelvin Zhao

As always, here’s the TLDR link to the plugin and an obligatory GIF to get the party started.

Jiggle jiggle.

Why My Own Plugin?

The world of plugins is a fascinating one. Any effect or function you need, there’s probably a jQuery or JavaScript plugin for it.

Need a cat that pops up with sad face whenever users try to leave the site? Yes, there’s probably a plugin for it.

Don’t go.

Which is why when I needed a particle effect for a site I’m creating, I turned to GitHub instead of trying to write one myself.

Of course, having no idea how to create one is one tiny reason too. 😂

After digging around a little, I’ve found plenty of particle effects and one of the best, imho, is particles.js by Vincent Garreau. Do check it out! He seems like a pretty nice guy too. Yes, he replied to my question about his plugin. That’s how I judge the niceness of people. Don’t judge me judging people!

Now here’s the part where we’re supposed to use the plugin and live happily ever after.

Except -spoiler alert- fairytales are not real.

Well, actually that is only partially true. Me, being my worst client ever, decided I want customizations in my particles that are not covered by the default settings.

Initially, I thought I’ll just pop into the plugin and try to tweak it a little to fit my needs. But, oh boy, what a can of worms I’ve opened. Much of the structure inside the plugin seems alien to me and I have no idea what’s really going on. The part about how I started learning JavaScript only early this year might have something to do with it. ¯\_(ツ)_/¯ Still, I could theoretically hack and slash to make things work the way I want.

I think.

Somehow, interestingly, I concluded and convinced myself that I need to learn how to create my own plugin instead. It’ll not be the first time I sabotaged myself like that.

How Did I End Up Here?

I hope you’re not asking yourself the same question. For me, I’ve always been that one curious kid that could not stop asking why. When I read an article and come across a foreign name or event, I would wiki the sh*t out of it. I’ll always try to understand the context and reasons behind decisions and results. Why things work the way they do.

I’ve always preferred understanding to knowing.

Thus, this is not going to be a copy and paste hackathon. I’m trying to build some foundations here. It will be rather opinionated; and coming from a coding noob, it might not be a good thing.

You’ve been warned.

Here’s a quick cheatsheet of a few key resources that I’ve used.

What Did I Learn About jQuery Plugins?

Before this, the whole concept of plugins was a huge black box to me. I know that if I follow the readme instructions, copy and paste the given code, magic will happen. But what is really happening under the hood?

Let’s start with a typical jQuery plugin use case:

$( '.myDiv' ).myPlugin( 'doSomething' );

Before, what I thought happened was that I tell the plugin which element I want to target, it will go off and do its plugin stuff. Voila, voodoo happens!

But if you really look at it closely… It’s pretty much the same as:

$( '.myDiv' ).myFunction( 'myVariable' );

Now don’t laugh at me. I’ve always been creating functions at the global level and never within an object. So this never occurred to me. What we’re really doing here is simply calling a function (or some might call method) declared within a jQuery object. And since that jQuery object contains the element you targeted. That function then activates on the element.

Wait what? Is it that simple? All that air of mystery around plugins and packages and UFOs and it’s just a simple function call?

Oh well.

Now to the alien stuff within the plugin code. The basic idea is simply this:

$.fn.myPlugin = function() {
// do your magic here
};

jQuery objects get its functions (methods) from the $.fn object. This object contains all the jQuery goodness like .css(), .mouseup.(), etc. And what we want to do is to add our own function into it as well. As shown above.

Next, we want to wrap the stuff we want to do into an Immediately Invoked Function Expression. In simple English, it is an unnamed (or anonymous) function that is called (or invoked) right after it is declared. It looks something like this:

(function() {
$.fn.myPlugin = function() {
// do your magic here
};
}());

It may look a little odd at first, but if we break things down, there are only 3 simple parts to it;

  1. There’s an outermost () that wraps everything up.
  2. Then an unnamed function with your goodies in it.
  3. And lastly a () at the end of the function that simply asks the function to do its stuff - right now. That’s the ‘self-invoking’ part.

This will add your scripts within a scope by which your variables and stuff will be contained. So to speak, not cause your sh*t to conflict with others outside your plugin or to pollute ‘global spaces’.

Of course, that’s only one of the reasons. The other reason is that we want to use the variable $ to represent jQuery. The $ variable is popular among other JavaScript libraries, and to prevent conflicts we’ll pass the $ into our ‘scope’ (mentioned above) and specifically tell it we mean jQuery in here.

Note the passing of ‘jQuery’ when invoking the function (the ending part), and slotting it in the ‘$’ (the front part) as the function’s parameters:

(function( $ ) {
$.fn.myPlugin = function() {
// do your magic here
};
}( jQuery ));

One other neat thing some people do is to add a semi-colon to the start of the code. It’s used as a safety net against concatenated scripts and/or other plugins that may not have been closed properly (just in case):

;(function( $ ) {
$.fn.myPlugin = function() {
// do your magic here
};
}( jQuery ));

And that’s about it!

The last thing we need to consider is adding options to the plugin. This is really optional (pun not intended), but I think it’ll be useful if you plan to reuse the plugin in different situations.

There are quite a few ways to do this, but my preferred method is this:

;(function( $ ) {
$.fn.myPlugin = function( options ) {
        var settings = $.extend({
// default settings
mySetting1 : 10,
mySetting2 : 100,
mySetting3 : 1000
}, options);
        // do your magic here
};
}( jQuery ));

Here, we’re creating a ‘settings’ object with the various settings we need sitting inside as variables. If you look only at it, it’s something like this:

var settings = {
// default settings
mySetting1 : 10,
mySetting2 : 100,
mySetting3 : 1000
};

And we are using the jQuery’s extend method to merge the settings object with another similar object called options. We’re passing the options from here at the function’s parameters slot:

$.fn.myPlugin = function( options ) {

To the second object of the extend method:

}, options);

So in simple English, if we did pass any options when using the plugin, it will overwrite the default settings we have, otherwise, the default settings inside the plugin stays.

So we can use our plugin with its default values like this:

$( '.myDiv' ).myPlugin();

Or we would pass the options object in like this when needed:

$( '.myDiv' ).myPlugin({
// new settings
mySetting1 : 1000,
mySetting2 : 100,
mySetting3 : 10
});

Now, let’s back up a little to the extend method. Other than the two objects we are merging, there’s also two things I’ve learned to pass in as a best practice. For me at least.

That is a true boolean and an empty object {}, added like so:

var settings = $.extend( true, {}, {

An Empty Object {}

The usual way extend works is that it will modify the default settings by adding options in to overwrite it. Adding an empty object will preserve the defaults and let the new empty object be the target of the modification. Now in theory we don’t need the default settings and it should be fine to overwrite it. But you can never be too safe, right? At least that’s how I work.

A True Boolean

Next, the true boolean. The merge performed by the extend method is not recursive by default; meaning if the property of the object itself is an object or array, it will go bonkers. Well, sort of. It’s a little hard to explain, but basically in simple English, the objects can only be one level deep. It cannot be objects within objects or arrays within objects, etc. But by passing the true boolean in, though, it will allow for recursive merging. Again, this is probably only useful if you have really complicated settings, but I like to have it there as a default in case I need it one day and I totally forgot about this option. 😅

And there we have it, the final skeleton of the jQuery plugin:

;(function( $ ) {
$.fn.myPlugin = function( options ) {
        var settings = $.extend( true, {}, {
// default settings
mySetting1 : 10,
mySetting2 : 100,
mySetting3 : 1000
}, options);
        // do your magic here
};
}( jQuery ));

And that’s really it. All the alien structure in its full glory.

I hope this cleared up some mystery behind jQuery plugins. Drop me a line if there’s anything that doesn’t make sense or if I’ve made some wrong assumptions and explanations!

If you liked what you read; help recommend the article by hitting the ♥ button below and follow me as I try my hand at sharing my thoughts and various musings. You can also stalk me @kelvin___, where I post things that I find interesting and occasional rant at life. Till next time… Stay curious!
High-five!

Tags

Join Hacker Noon

Create your free account to unlock your custom reading experience.