Grow your CSS skills. Land your dream job.

Namespaced Events in jQuery

Published by Chris Coyier

It's really easy to add an event listener in jQuery. It's equally easy to remove an event listener. You might want to remove a listener because you don't care to perform any actions on that event anymore, to reduce memory usage, or both. But let's say you've attached several listeners to the same event. How do you remove just one of them? Namespacing can help.

Let's look at code.

$("#element")
  .on("click", doSomething)
  .on("click", doSomethingElse);

Both doSomething and doSomethingElse will fire when that element we've selected is clicked. That's good. It's one advantage of using jQuery to bind events rather than super old school onclick which would overwrite previously declared event handlers.

Now let's say you want to remove the first of those event listeners, the one that fires doSomething. How do you do that?

$("#element").off("click");

Careful there, that will unbind both of those handlers which is not what we want.

Luckily jQuery will take the same second parameter with .off() as it does with .on().

$("#element").off("click", doSomething);

That's great if you have a reference to an actual function that you can pass in as that parameter. But what if you don't have that reference? Either because you don't know what it is or you used an anonymous function as the handler, like this:

$("#element")
  .on("click", function() { 
     console.log("doSomething");
   });

How do you unbind that one in a safe way that won't accidentally unbind other click handlers? Namespaced events!

Instead of just click as the name of the event, you can use click.namespace.

$("#element")
  .on("click.myNamespace", function() { 
     console.log("doSomething");
   });

Now you can use .off() with that exact event name to unbind just it.

$("#element").off("click.myNamespace");

Just one of those cool useful things in jQuery. Even with modern event binding using addEventListener and removeEventListener this would be a bit tricky (I think).

I used it recently in that bookmarklet I made to test line length. I essentially wanted to bind a mouseenter event on every single element on the page (using delegation) and then when one is clicked, unbind both those events. But I wanted to be careful not to unbind anything that I didn't bind myself. Hence, namespacing!

Want to learn more about jQuery? I have a complete course available.

Comments

  1. Matt Wistrand
    Permalink to comment#

    This also works with Zepto, and is incredibly helpful when you’re writing unit tests and need to clean up your objects for subsequent tests.

  2. Luca R.
    Permalink to comment#

    Shoosh, I knew about namespaces but honestly I didn’t think they were implemented natively in jQuery. I thought you had to manually add an event listener to use namespaced events in a plugin.

    Thanks for the tip!

  3. Permalink to comment#

    This article should also mention about canceling all events from a namespace, which is very useful for jQuery plugins.

    $("div").off(".myNamespace");
    
    • KHS
      Permalink to comment#

      +1

      It’s surprising that this little piece of info is so hard to find online. A little jsfiddle worked though, so I was looking for a place to verify whether my hunch was right about ONLY namespace being passed to unbind an event.

      Thanks

  4. Permalink to comment#

    I’ve been thinking about namespaces and wondering if there were a way to inject Geolocation into namespace so RSS feeds convert to GeoRSS. Is this something that can be achieved with jquery?

  5. Permalink to comment#

    You can use $("#element").on("click",function(){})? I thought the only way was $("element").onclick(function(){});. Any advantages of the former?

    • Permalink to comment#

      I don’t think onclick() is a function in jQuery, click() is though. The difference I believe is on() will bind to elements whether they are present in the DOM or whether they are added dynamically at a later point in time.

    • Permalink to comment#

      Not “onclick”, but “click”, which is a shortcut to the on("click", function). With on you can attach multiple events – $(el).on("click focus", function (){});, also you can create single event which will fire if e.target is in event bubble, which gives you performance boost.

      $("table").on("click", "td", function () {}); – single event

      $("table td").click(function () {}); – amount of events == $(‘table td’).length

  6. Permalink to comment#

    As mentioned there is support for this in Zepto too, but I’ve noticed you use the .MyNamespace for native events like click.MyNamespace or focus.MyNamespace, and custom events you use a reversed syntax: MyNamespace:eventName.

    Seems that jQuery is smart enough to figure it out either way, but if you want it to work in both Zepto and jQuery you have to use the different syntax for custom events.

    I fought this battle with Intimidatetime. So standard native events it uses click.intimidatetime, but for custom events I have to use intimidatetime:open or intimidatetime:change

  7. Permalink to comment#

    Thanks very much for that post. That will fix some problems I had in the past with some of my functions.

  8. David
    Permalink to comment#

    Hey Chris, can you post a snippet tutorial for the navbar animation as shown in Digitally Imported:

    http://www.di.fm

    Click on Channels.
    I believe it’s jQuery UI but not sure.

  9. Ah that’s awesome, going to try this asap.
    Thanks!
    :D

  10. Richard
    Permalink to comment#

    The two uses for this are if we don’t know the name of the function in question or an anonymous function has been used. However the only way to implement the namespace seems to be at the time of declaring the function, where you would be able to pass in a function with a name you know. It seems to be just an alternative method to passing in a function you have named? Are there any other uses for this that I am missing?

    • Matt Wistrand
      Permalink to comment#

      If you’re using proxies ($.proxy), and you need to detach them later, you either need to keep track of every proxy you create, or just use namespacing .

  11. Permalink to comment#

    This is terrific.

  12. One thing that is very nice, but I had trouble with, is Dynamic Namspacing… below is how I prefer to bind events (in a json format):

    $("element").on({
      "click.namespace": function(){},
      "hover.namespace": function(){}
    });
    

    in this scenario I cannot make the name spaces dynamic, but in this next scenario I could create a dynamic namespace:

    var ins = ins+1 || 0;
    $("element").on("click.namespace.subspace"+ins , function(){});
    

    Dynamic namespacing can be really useful for plugins and such where you’d like to create > 1 instances of a plugin on a page, but not unbind all the other bindings when destroy()ing the plugin.

  13. Ronda Pederson

    Very nicely done. I am planning to access your jquery tutorials later this month.

    Do you know if anyone has an example of using fittext for the text inside gridcells (kendoui jquery grid)

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".