views:

52

answers:

4

I have HTML similar to the following in my page

<div id="someDiv">
    <img src="foo.gif" class="someImg" />
</div>

The wrapper div is set up such that when it is clicked, it's background-color changes using the following jQuery code.

$("div").click(function(event){
    $(this).css("background-color", "blue");
});

I also have some jQuery associated with my img that will do some other function (for the sake of argument I am going to display and alert box) like so:

$("img[class=someImg]").click(function(event){
    alert("Image clicked");
});

The issue I have come across is that when I click on the img, the event associated with the div is also triggered. I'm pretty sure that this is due to the way that jQuery (or indeed JavaScript) is handling the two DOM elements - clicking the img would require you to also technically click the div, thus triggering both events.

Two questions then really:

  1. Is my understanding of the DOM/JavaScript flawed in some way or is this actually how things are occurring?
  2. Are there any jQuery methods that would allow me to perform actions on a child element without invoking those associated with its parent?
+5  A: 

That is known as event bubbling, you can prevent it with stopPropagation():

$("img[class=someImg]").click(function(event){
    alert("Image clicked");
    event.stopPropagation();
});

.

  1. Is my understanding of the DOM/JavaScript flawed in some way or is this actually how things are occurring?

That is because of what is known event bubbling.

  1. Are there any jQuery methods that would allow me to perform actions on a child element without invoking those associated with its parent?

Yes, you need stopPropagation()

Sarfraz
Great answer, thanks!
Matt Weldon
@Matt Weldon: You are welcome :)
Sarfraz
+3  A: 

This is what's called event bubbling, and you can stop it to get the behavior you want with .stopPropagation() (or return false; if you want to stop the event completely, including handlers on the same level), like this:

$("img[class=someImg]").click(function(event){
  alert("Image clicked");
  event.stopPropagation();
});

You can view a demo here, comment it out and click run again to see the difference.

The short version is that when most event types happen, they happen on the immediate element, then bubble up the DOM, occurring on each parent as they go. This is not jQuery specific at all, native JavaScript does this. If you're more curious, I'd read the linked article, it has a great explanation of what's going on.

Nick Craver
+3  A: 
  1. No, this is by design. Events bubble up through the entire dom, if you put another handler on body, it would fire too
  2. Yes :) JQuery normalizes the event object, so adding event.stopPropagation() in your img click handler will give you the behavior you expect on all browsers
Matt Briggs
+3  A: 

The problem you just facing is called "event bubbling". That means, if you click on a nested element, that click event will "bubble up" the DOM tree. If other elements also are bound to an click event, their listeners will fire aswell.

Solution to prevent this is called:

stopPropagation()

which is used within your event handler

$("img[class=someImg]").click(function(event){
   event.stopPropagation();
   alert("Image clicked");
});
jAndy