Proper handling of event bindings in jQuery plugin

28 Jul 2017

JQuery Offers simple way to create plugins, that maintains its state and offers same flexibility as the core plugins. Check this article - Essential jQuery Plugin Patterns by Addy Osmani that covers most of the patterns used for creating a plugin. I'm sure you would say Wow after reading it and also appreciate how jQuery simplifies plugin creation pattern.

While creating a plugin, I found it hard to find a proper way to bind and unbind events from the objects in global scope like window, document.

For e.g., You want your plugin to refresh its styling or component interaction based on screen size, you will bind your logic like below

$(window).on('resize', doSomeChanges); 

Above code works fine, but becomes a challenge when you decide to unbind its event. $(window).off('resize'); will remove all events bound to 'resize' event including the ones created by other plugins/code.

Option 1:

You can go ahead and pass the function again to unbind the event as follows

$(window).off('resize', doSomeChanges);

Well above will work flawlessly if your plugin appears once in that page. What happens if it is place more than once ? A simple call to 'off' particular event from window object in a plugin instance will unbind it from all instances of your plugin in that page.

Option 2:

jQuery comes up with event namespacing that helps to remove the events that you have bound through your plugin, without impacting others. 'myNamespace' is just a simple name, it can be anything specific to your plugin.

// Bind
$(window).on('resize.myNamespace', doSomeChanges);

// Unbind

Simply removes just the event in the specified namespace. but this still doesn't solve the issue when more that one instance is used in the page.

Option 3:

You can properly subspace your namespaces with unique names to unbind just those like below.

In your plugin, you can generate a unique eventNamespace and then bind or unbind using it as follows

$.fn.myPlugin = function(option){
 this.eventNamespace = '.id-' + random-unique-number;
 // Bind
 $(window).on('resize.myPlugin'+ this.eventNamespace, doSomeChanges);

 // Unbind
 $(window).off('resize.myPlugin' + this.eventNamespace);

That's all now your plugin event binding will be more specific and proper.

Option 4:

When using jQuery UI, you can modify the unique Id generation as follows that helps you to add a unique id to your plugin element as well as get a unique name / namespace

 var table = $(this); // Your plugin object
 table = table.uniqueId(); // Generate unique element id if not present
 var namespace = table.attr('id');

Happy jQuerying wink