0

There is a number of bootstrap tabs and each tab has sample table with a big number of "td" elements. We bind a click event on the td's of the active tab. For performance, we want to unbind the click events of the previous tab each time the user changes tabs.

Here's the demo: http://jsfiddle.net/hyTCy/

(the 'shown' event is after all transitions are completed)

$('a[data-toggle="tab"]').on('shown', function (e) {

    var newt = $(e.target).attr("href"),
        prevt = $(e.relatedTarget).attr("href");

    console.log("new tab: " + newt) // activated tab
    console.log("prev tab: " + prevt); // previous tab

    $(newt + " tbody").on("click", "td", function (e) {
        console.log("click");
    });

    var validate = function () {
        console.log("prev click ok");
    };
    $(prevt + " tbody").off("click", "td", validate);
});

Normally, if you visit the demo and click the tab "profile" and then "home", there should be displayed a message in the console "prev click ok", so that we know the events in the previous tab have been unbinded.

Why isn't function validate working properly?... Thanks!

John
  • 3
  • 1

1 Answers1

0

You're mistaken about how .off() works. It just unbinds the event handler. It doesn't execute the callback function that is passed to it. You pass the callback function ONLY so that the .off() function can match up the proper event handler to remove and if passed, it must be the exact same function that was passed to .on(). It isn't actually called when you call .off().

For .off() to work properly, you have to either pass the exactly same callback function that the event was registered for or you have to pass no callback (in which case all will be deregistered). Right now, you're passing a callback that has nothing to do with the event, thus no event is deregistered.

What's important is that the .off() call must have exactly the same signature as the .on() call that you're trying to deregister. So, whatever the .on() call looked like, make sure the .off() call looks the same. The means the event name needs to be the same, the selector needs to be the same and the callback function needs to either be not passed at all or the same.

If this is what you're trying to undo:

$(newt + " tbody").on("click", "td", function (e) {
    console.log("click");
});

Then, you would want to use this:

$(prevt + " tbody").off("click", "td");

If you're trying to target ONLY that particular callback, then you need to put the first callback into a function so it can be used for the .off() like this:

function logClick(e) {
    console.log("click");
}

$(newt + " tbody").on("click", "td", logClick);

And the .off() would use the same function:

$(prevt + " tbody").off("click", "td", logClick);
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks so much for your answer!! I think they should include your information in the jquery website, it's much more informative. :) One more question I have is: So, if I do $(prevt + " tbody").off("click", "td");, is it guaranteed to unbound the events from the hidden (previous) tab? Thanks!! – John Apr 01 '13 at 19:00
  • And a followup question: is there a way to get notified when events are unbounded in jquery? That would be nice. – John Apr 01 '13 at 19:04
  • @John - not that I know of without replacing the `.off()` method with your own that adds the notification. Just curious, why do you need that? – jfriend00 Apr 01 '13 at 19:08
  • @John - when you do `$(prevt + " tbody").off("click", "td")` it is guaranteed to remove any events on `$(prevt + " tbody")` that were bound with the arguments `("click", "td")`. It won't touch any events that were for a different event name (e.g. not "click") or a different selector (e.g. not "td"). If you read and study the [jQuery doc for `.off()`](http://api.jquery.com/off/), it looks pretty thorough to me. It's all in there. – jfriend00 Apr 01 '13 at 19:11
  • There's not much more in that except from the fact that I want to be able to know that the events have been unbinded properly. When you have a table with 10 tabs and 1000 rows on each tab, isn't it important to know that all those events are now free? Normally, you could use Chrome's event watcher, but when you use a library that extends jquery, it points to jquery and not the actual function that does the binding. – John Apr 01 '13 at 19:14
  • @John - why do you have to unbind the events in the first place? Can you just bind them once and leave them? – jfriend00 Apr 01 '13 at 19:16
  • 10 tabs * 1000 rows each * 10 td each = 100.000 events live on the page. Is this performance good? Also, mind that the api says "Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on()." So, if I change the table data, what happens to the events?.. – John Apr 01 '13 at 19:19
  • @John - the ideal time to use delegated event handling with `.on()` is when you have thousands of cells and dynamic cells that come and go. You can install one single event handler on a common static parent and it will work for all the child objects that match the selector even as they come and go. I don't follow exactly what you're trying to do here, but that sounds like what you want here. – jfriend00 Apr 01 '13 at 19:21
  • I thought I could attach the events only on currently existing elements. (well, I'm a newcomer to jQuery :)) From what you're saying, I'd better bind the event to the body with "td" selector. Thanks for your tips!! – John Apr 01 '13 at 19:24
  • @John - I'd suggest you read about "jQuery delegated event handling". You can attach an event handler to a static parent that will handle event events for all children that come and go. That is what you are doing with your `.on()` call. – jfriend00 Apr 01 '13 at 19:27
  • @John - Here are a few posts to read: http://stackoverflow.com/questions/8752321/jquery-live-vs-on-method-for-adding-a-click-event-after-loading-dynamic-ht/8752376#8752376, http://stackoverflow.com/questions/9814298/does-jquery-on-work-for-elements-that-are-added-after-the-event-handler-is-cre/9814409#9814409, http://stackoverflow.com/questions/9730277/jquery-event-handlers-whats-the-best-method/9730309#9730309 and a google search will probably find much more. – jfriend00 Apr 01 '13 at 19:29