If you’re looking for an in-depth tutorial on writing a jQuery plugin, learning jQuery and JavaScript in general – this is not the article for you. There’s plenty of resources, both free and paid, covering those topics. What we’re exploring is a quick, real-world way of writing jQuery plugins and converting plain JS functions into jQuery plugins that’ll help you in your day-to-day jQuery code. We won’t be writing code or plugins that get hosted on GitHub and used by thousands. We’ll write one-liners that speed up development.

There’s nothing special about jQuery plugins

jQuery plugins don’t use any “special” JavaScript code. It’s just plain old JavaScript. Period. Some rules have to be followed for a piece of code to be a jQuery plugin, but there’s nothing magical about them. Here’s what you need to know:

  • jQuery plugins are plain JavaScript, nothing special about them
  • they “live” in the jQuery namespace jQuery.fn., so they’re accessible via usual jQuery().myPlugin() calls
  • whenever possible plugins should return the original jQuery object to maintain the chaining feature – $('.selector').function1().function2().function3()
  • plugins that return a boolean, string or some other data other than a jQuery object are perfectly fine, and often called utilities like $.trim()
  • to ease maintenance; big plugins are kept in separate files, but there’s no technical reason for that – keep your small plugins wherever you please

Your typical jQuery setup

First you engueue jQuery, some plugins and your custom JS code in HTML;

<script src="/js/jquery-3.3.1.min.js"></script>
<script src="/js/jquery.some-plugin.min.js"></script>
<script src="/js/jquery.some-other-plugin.min.js"></script>
<script src="/js/frontend.js"></script>

Then, in frontend.js you init all plugins and write some custom code. It’s all wrapped in an anonymous function fired after page DOM is ready. Just your standard stuff:

jQuery( document ).ready(function( $ ) {
  $( '#some-element' ).plugin1({ opt1: val1, opt2: val2 });
  $( '#mybutton' ).on( 'click', function( e ) {
    alert( 'Button clicked!' );
  });
});

// or you may use the shorthand version to save a few keystrokes
jQuery( function( $ ) {
  $( '#some-element' ).plugin1({ opt1: val1, opt2: val2 });
  $( '#mybutton' ).on( 'click', function( e ) {
    alert( 'Button clicked!' );
  }); 
});

After a while, you realize there’s a need for a function that counts the number of times the word “HTML” appears in a string (case sensitive). Nothing easier, so you add:

function count_html( my_str ) {
  var count = ( my_str.match(/HTML/g) || [] ).length;
  return count;
}

A perfectly fine function but now, all of a sudden we’re no longer using the object-oriented syntax and are switching to function-oriented. Not the cleanest approach but not a deal-breaker either. The second problem is the scope. The count_html() function will not be available in the global scope if you defined it inside the ready() anonymous function. You’ll get the “Uncaught ReferenceError: count_html is not defined” error. “OK, so I just put it outside in the global scope, and it’s all good?” True. However, in practice you’ll forget to do that, the function will remain inside the anonymous function, and you’ll have to debug things. Solution to the problem is to rewrite the function as a jQuery plugin. It’ll also help you keep the code cleaner.

Your first jQuery plugin – easier than you think

Rewriting the count_html() function into a jQuery plugin is easy:

jQuery( document ).ready(function( $ ) {
  // your other custom code
  $.fn.countHtml = function( my_str ) {
    var count = (my_str.match(/HTML/g) || []).length;
    return count;
  };
  // more custom code
});

That’s it! Now you can use $().countHtml('some text') where ever you need it in code. Please note it’s $() and not just $. “Wait a minute! Isn’t that function-oriented code, again?” It is because we wrote a jQuery utility – a plugin that doesn’t manipulate jQuery objects. Let’s write a “proper” jQuery plugin that maintains the chain. Our plugin will add a red border to all paragraph elements passed to it:

jQuery( document ).ready(function( $ ) {
  $.fn.addRedBorder = function() {
    this.find( 'p' ).css( 'border', '1px solid red' );
    return this;
  };
});

Alternatively, if you want to define the function outside the ready() function (and technically you should because it’s the right thing to do but previous code works too so 90% of you won’t care), use this in order to protect the $ alias and add scope;

(function ( $ ) {
  $.fn.addRedBorder = function() {
    this.find( 'p' ).css( 'border', '1px solid red' );
    return this;
  };
}( jQuery ));

Clean and simple

Not that difficult, right? Rewriting small reusable pieces of code from standard functions to jQuery plugins will speed up your development, keep code concise and clean. It’ll also give you a chance to identify pieces of code that could be turned into proper jQuery plugins, with options and everything that could one day end up on GitHub. If you’re into that sort of thing 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *