Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Your own plugin: $.fn

A jQuery plugin is a new method available on any set of elements, like addClass() or fadeOut(). Set methods live in the $.fn object, so a plugin is just a function added to $.fn. Thousands of ready-made plugins work this way: sliders, input masks, popups.

Where the plugin lives

Keep a plugin in a separate file and load it after jQuery but before the code that uses it:

todo/
├── index.html
├── jquery.counter.js
└── script.js
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="jquery.counter.js"></script>
<script src="script.js"></script>

By tradition the file name starts with jquery..

A first plugin

The taskCounter plugin writes how many tasks a list has next to it:

<ul id="tasks">
  <li>Buy bread</li>
  <li>Call Oleg</li>
</ul>
 
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
  $.fn.taskCounter = function () {
    return this.each(function () {
      const count = $(this).children('li').length;
      $(this).after($('<p>').text('Tasks: ' + count));
    });
  };
 
  $('#tasks').taskCounter();
</script>

The line "Tasks: 2" appears under the list. Inside a plugin this is the jQuery set itself, so it does not need wrapping in $. The each() method handles each element of the set separately, and return hands back the set so the chain can continue after the plugin.

Settings

The plugin accepts a settings object and fills in defaults with $.extend() from the previous lesson:

<style>
  .highlight { background: gold; }
</style>
 
<ul id="tasks">
  <li>Buy bread</li>
  <li>Urgent: call Oleg</li>
</ul>
 
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
  $.fn.highlightTasks = function (options) {
    const settings = $.extend({ word: 'Urgent', className: 'highlight' }, options);
 
    return this.find('li').each(function () {
      $(this).toggleClass(settings.className, $(this).text().includes(settings.word));
    }).end();
  };
 
  $('#tasks').highlightTasks().css('padding', '8px');
</script>

The item with the word "Urgent" is highlighted in yellow. Calling highlightTasks({ word: 'bread' }) would highlight the other item. The end() method returns the set that existed before find(), so css() applies to the list itself.

Protecting $

In the plugin file the code is wrapped in a function that receives jQuery under the name $:

// jquery.counter.js
(function ($) {
  $.fn.taskCounter = function () {
    return this.each(function () {
      const count = $(this).children('li').length;
      $(this).after($('<p>').text('Tasks: ' + count));
    });
  };
})(jQuery);

This way the plugin works even if $ is taken by another library on the page or jQuery runs in noConflict mode, as in WordPress.

Common mistake

Not returning this from the plugin. Then the call returns undefined, and the chain $('#tasks').taskCounter().addClass('ready') fails with Cannot read properties of undefined. Always end a plugin with return this or return this.each(...).

Thanks for reading!

Donate to the site — we work hard for you.