1

I have the following listeners:

$('td').on('click', '.time_note', function (e) { // When the user clicks the note div
    alert('note click');
});

$('table').on('click', 'td', function(e) {
    alert('time click');
});

I need two different actions depending on whether the note is clicked or the entire cell is clicked. I tried doing this, however, if the note is clicked - so is the cell. Both actions are fired, subsequently. Makes perfect sense.

However, I don't want that to happen. If the note is clicked, the action for the entire cell should not fire and vice-versa. What way is there to accomplish this? I tried to use .off, but that didn't work.

Cody
  • 8,686
  • 18
  • 71
  • 126

3 Answers3

3

You can't...

You can't stop propagation unless both of the events are delegate events.

Since the .live() method handles events once they have propagated to the top of the document, it is not possible to stop propagation of live events. Similarly, events handled by .delegate() will propagate to the elements to which they are delegated; event handlers bound on any elements below it in the DOM tree will already have been executed by the time the delegated event handler is called. These handlers, therefore, may prevent the delegated handler from triggering by calling event.stopPropagation() or returning false.

docs

Note: on is just like delegate in this case. I guess they just didn't update the docs...


Update:

  • It can work if both of the events are delegate events: @josef DEMO.
  • It won't work if the other event isn't delegate: DEMO

What are the differences between delegates and direct events:

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(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page. If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler, as described next.

Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.

Community
  • 1
  • 1
gdoron
  • 147,333
  • 58
  • 291
  • 367
  • 1
    Not sure why you're saying I can't, I just tried the `stopPropagation` and it works brilliantly.. – Cody Mar 21 '12 at 21:26
  • @DoctorOreo. It depends on the DOM and which handlers you trying to block. I'll make a fiddle to show you. – gdoron Mar 21 '12 at 21:34
  • @DoctorOreo. Check [this](http://jsfiddle.net/HvQuk/1/) fiddle. Your works only because they are both delegate events. – gdoron Mar 21 '12 at 21:37
  • The only difference I see between the two are number of selectors - you have `table td` - is that the difference between `live` and `delegate` events? – Cody Mar 21 '12 at 21:53
  • @DoctorOreo. I added the docs the answer and updated the fiddle. Did you got the differences? – gdoron Mar 21 '12 at 22:16
2

try to check event.currentTarget:

$('table').on('click', 'td', function(e) {
    if(e.currentTarget.tagName.toLowerCase() == 'td') {
        alert('time click');
    } else {
        alert('note click');
    }
});

You can find more information here

Vitaly Muminov
  • 1,914
  • 12
  • 11
0

DEMO

this is the case: .note's handler is on the td. clicking .note, the event bubbles up to td where it fires the handler for it. but you didn't stop there. events bubble up to the root, clicking a child element is synonymous to clicking it's ancestors. that's why it's like clicking the td whose handler is in table.

early on, you should prevent it.

$(function() {

    $('td').on('click', '.note', function(e) {
        alert('note click');
        return false; //prevent bubbling to the second handler
    });

    $('table').on('click', 'td', function(e) {
        alert('td click');
    });

});​
Joseph
  • 117,725
  • 30
  • 181
  • 234