Namespace Your Events

read 13 comments

A common pattern in jQuery plugin development is the need to undo what the plugin has done. This is usually handled through a method prefixed with "un". Another common pattern is the use of anonymous functions for event handlers. Unbinding events is easy with jQuery but unbinding a single event handler requires the use of a named function. jQuery 1.2 now provides another option for binding and unbinding events: event namespaces.

A Plugin

As a very simple example, let's say I wrote a plugin called "clicked". It provides two methods: clicked and unclicked. The clicked method attaches an event to all matched elements that when clicked adds a class name of "clicked" to the clicked element. The unclicked method removes the "clicked" classes it might have set and the clicked event handlers it attached. Here is the code:

JavaScript:
  1. (function($){
  2.     $.fn.extend({
  3.         clicked: function() {
  4.             return this.bind('click', function() {
  5.                 $(this).addClass('clicked');
  6.             });
  7.         },
  8.         unclicked: function() {
  9.             retun this.removeClass('clicked').unbind('click');
  10.         }
  11.     });
  12. })(jQuery);

You could use the plugin by calling it like this:

Continue Reading Below
JavaScript:
  1. $('div').clicked();

And if you wanted to stop using the plugin, you could just call unclicked:

JavaScript:
  1. $('div').unclicked();

So far, so good.

A Problem

But let's say I'm also using another plugin that attaches a click event to the same elements that the clicked plugin does. Calling unclicked would unbind all the click events, including those bound by your own code or another plugin.

A Solution: Event Namespacing

Event namespacing provides a way to manage specific event handlers. For example, a plugin could namespace its event handlers to make them easier to unbind while still using anonymous functions. To namespace an event, just suffix the event type with a period and a name ("type.namespace").

Here is the clicked plugin again, but this time using event namespaces:

JavaScript:
  1. (function($){
  2.     $.fn.extend({
  3.         clicked: function() {
  4.             return this.bind('click.clicked', function() {
  5.                 $(this).addClass('clicked');
  6.             });
  7.         },
  8.         unclicked: function() {
  9.             retun this.removeClass('clicked').unbind('click.clicked');
  10.         }
  11.     });
  12. })(jQuery);

Now it only unbinds the events that it bound in the first place, leaving any other bound events alone.


comment feed

13 comments

  1. AD

    Please could you have more tutorials on how to integrate jQuery with PHP/MySQL -- perhaps a project, like a simple customer add/edit/delete/search/paging project, which includes auto-complete?

    Many thanks.

  2. Great write-up Karl! I actually did my first bit of real-world "event namespacing" the other day when I add a new .unmask() method to the Masked Input plugin. It was a super-simple set of changes but worked wonderfully!

  3. Oooops! I meant Brandon - great job!

  4. Stan

    Thanks for the info here, I was trying to lookup info on the namespaces this morning and couldn't find any on the jQuery website except the reference in the changelog. Keep up the good work with your blog. Pax.

  5. Thomas

    Super just what I needed... !!

  6. Kevin

    I'm just begin to use JQuery, Thanks for the info!

  7. Joshua

    It's good,
    Hope that the exchange links.
    Joshua's Blog
    http://www.joshua.org.cn

  8. thanks for this great information on Namespace events

  9. Nanda

    First I would like to congradulate you on this blog and I have found the writeup useful.

    However I have a problem where I bind a click function to the entire document but then want to unbind for a specific element in this case a textarea so that clicks inside the textarea do not trigger the anonymous function. Could using namespace s solve the problem.

    I have provided the jQuery code I am using to tdo this below:

    
    entire_document.bind('click', function(e)
    	{
    		jQuery('#textareaid').unbind('click');
                     if (condition)
                     {
                            // do some stuff
                      }
                     else 
                      {
                             // do some other stuff
                       }
            entire_document.unbind('click');
    	});
  10. Hi Nanda,

    Try something like this:

    $('body').bind('click', function(e) {
      if (e.target.nodeName != TEXTAREA) {
        // do something
      }
    });

    No need for the unbind.

  11. Thanks, that was what I was looking for :)

  12. Randy

    Beautiful! I made a jQuery plugin that makes a DOM element bordered and binds a click event handler that toggles the border color. No worry now about other plugins unbinding my plugin's handler and vice versa.

    
    $.fn.extend({
            clicked: function() {
                this.addClass('clicked off');
                return this.bind('click.clicked', function() { //namespaced handler
                    $(this).toggleClass('on off');
                });
            },
            unclicked: function() { //namespaced handler
                return this.removeClass('clicked on off').unbind('click.clicked');
            }
        });
    
    // e.g. $('#border_flasher').clicked(); <-- makes element border flashable
    //      $('#border_flasher').unclicked(); <-- safely unbinds handler that .clicked() bound
    
    

    In CSS I style all the border except the color in the 'clicked' class and the border colors are styled in the 'on' and 'off' classes. Works well so far. I love this site! So much useful info for those on the jQuery learning curve.

5 Pings

  1. [...] like ‘click.autocomplete’ were. Turns out that jQuery has a mechanism where you can namespace your events. Here is another writeup about it. Nice [...]

  2. [...] For more information about event namespacing, read Brandon Aaron's article, Namespace Your Events. [...]

  3. [...] 请阅读Brandon Aaron的文章以了解更多关于事件名称空间的知识: Namespace Your Events. [...]

  4. [...] Over time, jQuery has evolved three ways to attach events to elements: .bind() , .live(), and .delegate(). Underneath it all, though, the three event APIs call the browser’s event system; that can lead to surprising interactions. For example, $(document).unbind("click") will remove all .live("click", ...) events, since those delegated events are attached to document. (This is also why you should use event namespaces.) [...]

  5. jQuery 1.7 Beta 1 Released | Code to Preload

    [...] Over time, jQuery has evolved three ways to attach events to elements: .bind() , .live(), and .delegate(). Underneath it all, though, the three event APIs call the browser’s event system; that can lead to surprising interactions. For example, $(document).unbind("click") will remove all .live("click", ...) events, since those delegated events are attached to document. (This is also why you should use event namespaces.) [...]

Sorry, but comments for this entry are now closed.