22

Lets say we have a HTML structure like this

<div id="container">
    <div id="nested">
        <span id="someElement"></span>
    </div>
</div>

...and our goal is to have an event listener on the #container only ! So, we bind a listener (jQuery code)

$("#container").on('click', function(event) {
    alert("container was clicked");
});

That works of course, but my problem with this approach is that, since events usually bubble up, that listener will also fire if we actually click on #nested or #someElement. My current solution to only handle the click when the #container is clicked is to compare this with event.target

$("#container").on('click', function(event) {
    if(this === event.target) {
        alert("container was clicked");
    }
});

My question: Is that considered "best practice" ? Is there a better way with jQuery to accomplish the same result "out of the box" ?

Example in action: http://jsfiddle.net/FKX7p/

Andre Meinhold
  • 5,087
  • 3
  • 21
  • 29

3 Answers3

2

An alternative way to prevent events from bubbling up is to use event.stopPropagation();

$("#container").on('click', function(event) {
    alert("container was clicked");
})
.children().on('click', function(event) {
    event.stopPropagation();
});

I think the advantage of using this approach is that if you want to attach another event to the nested div, you can just use

$("#nested").on('click', function(event) {
    event.stopPropagation();
    // some action
});

$("#container").on('click', function(event) {
    alert("container was clicked");
});​
Mr. 14
  • 9,228
  • 6
  • 37
  • 54
0

Alternative solution:

$("#container").click(function(){
    alert("container was clicked");
}).children().click(function(e) {
    return false;
});

But your solution is better. jsfiddle.net/FKX7p/2/ (with return false) OR jsfiddle.net/FKX7p/3/ (using stopPropagation)

I prefer use return in your example (code becomes easier to read):

if(this !== event.target) return;
Nikola K.
  • 7,093
  • 13
  • 31
  • 39
webdeveloper
  • 17,174
  • 3
  • 48
  • 47
  • 1
    In addition use `event.CurrentTarget !== event.Target` instead of `this` when required, due to the possible context change of `this` when using jQuery.proxy: http://api.jquery.com/jQuery.proxy/ – Nope Sep 17 '12 at 14:28
  • The alternative solution is worse, as it adds a lot of event handlers. – naugtur Sep 19 '12 at 11:21
  • @naugtur I agree with you, but before `on` function this solution was popular. – webdeveloper Sep 19 '12 at 12:18
  • if popular != good then yes ;) Comparing target and currentTarget is way better. (notice I'm not giving you a -1; mostly because I used to do stuff like that) – naugtur Sep 20 '12 at 13:16
  • @naugtur Yes, you're right. I want to note that nobody give me -1 :) – webdeveloper Sep 20 '12 at 13:25
0

I'm not sure which one work's faster but it make sense that the next code will be better:

$("#container").click(function (e) {
    if (e.target.id && e.target.id !== "container") return false;
});
Ponpon32
  • 2,150
  • 2
  • 15
  • 26
  • Now i'ts only check the identifier, with complex selectors i can't see another way except comparing the objects – Ponpon32 Sep 20 '12 at 13:58