0

I was answering a question here in SO, and I stumbled on an odd behavior. Check this demo

It's working great. I'm adding event handlers and when I click the image I have alert(2) without firing the link handler alert(1). The odd part is that, if I remove the preventDefault, alert(1) still doesn't fire, but it follows the link. How come that stopPropagation, prevents the handler from bubbling the event, but it needs preventDefault to not follow the link?

This is purely for an educational reason. I just want to understand what's happening.

//EDIT please see the demo before answering. I have handlers on two different elements. Although stopPropagation prevents the handler of the parent element to fire, it doesn't prevent it from following the link. But doesn't stopPropagation, prevent it the event from bubbling? Doesn't it nullify the event for the parent element?

//Why the event is nullified for the handler alert(1) but not for the following of the link?

Alkis Kalogeris
  • 17,044
  • 15
  • 59
  • 113
  • No, I've read this post. I actually pasted it on the answer I am talking about. Please see the demo. – Alkis Kalogeris Jun 12 '13 at 23:08
  • I think that that question answers your problem very well. `preventDefault` and `stopPropagation` do different things. `preventDefault` stops the _browser's_ action, where `stopPropegation` prevents the event from propegating across. – Benjamin Gruenbaum Jun 12 '13 at 23:15
  • Yes I agree but, you say "stopPropegation prevents the event from propegating across", then why does it reach the link tag and follows the link? – Alkis Kalogeris Jun 12 '13 at 23:17
  • Umm, it doesn't? If you [click the image](http://jsfiddle.net/VAFb4/) (small and broken in the top-left corner. You'll only see `2` and not `1`. – Benjamin Gruenbaum Jun 12 '13 at 23:19
  • I didn't say it does. I know what my example does, that's why it bothers me. Why does it follow the link, when it doesn't alert(1)? It works as it's supposed to with alert, but not with the following of the link – Alkis Kalogeris Jun 12 '13 at 23:25

2 Answers2

2

All events in Javascript fire on the outermost element interacted with and then fire again on every element in it's ancestry until it reaches the body. In this way the event is firing first on your img and then again on your a because your img is inside the a.

If this behavior is not desired, that is why you would use stopPropagation to prevent it from bubbling up the chain. In jQuery, it is easy to check what element originated the event, so you can ignore it in certain cases by using event.target.

if (e.target == this) { 
  // run code only when this element is the originator of the event 
}

When a click event is fired there are basically two veins, the Javascript event, and the native event. If the native event isn't preventDefault() or return false somewhere, it is going to fire, regardless of any stopPropagation().

Owen Allen
  • 11,348
  • 9
  • 51
  • 63
  • 2
    `"All events in Javascript fire on the outermost element interacted with"` That's actually not true. See the `useCapture` optional flag in `addEventListener`. You can set an event to hit an element before being dispatched to elements beneath it in the DOM tree. – Benjamin Gruenbaum Jun 12 '13 at 23:16
  • 1
    With `useCapture` the event still bubbles. It bubbles from the outermost element all the way up looking for `useCapture = true` events, and then it does another pass for `useCapture = false`. See this fiddle: http://jsfiddle.net/Af6AU/. – Owen Allen Jun 12 '13 at 23:22
  • That's what I am saying in my post. Since the stopPropagation() is clear on this, why does it follow the link (although it does not alert(1))? – Alkis Kalogeris Jun 12 '13 at 23:22
  • `stopPropagation` has no effect positive or negative at all on whether the link directs your browser. This is solely handled by `preventDefault` or `return false`. – Owen Allen Jun 12 '13 at 23:23
  • Yes but why? Since the bubbling stops with stopPropagation, what triggers the following of the link? – Alkis Kalogeris Jun 12 '13 at 23:30
  • Right, but if you call `stopPropagation` inside a capturing event, it will not propagate to events that are not using capturing. That was my point. – Benjamin Gruenbaum Jun 12 '13 at 23:30
  • That answers my question. Thank you. Could you provide a reference for further studying? – Alkis Kalogeris Jun 12 '13 at 23:50
  • Not all event-types bubble (propagate): https://stackoverflow.com/a/5575576/613004 – Faust Sep 14 '18 at 17:35
1

How come that stopPropagation, prevents the handler from bubbling the event, but it needs preventDefault to not follow the link?

Well, you explained it well.

Default behaviour of a link is being followed. Preventing the default is stopping it from being followed.

Propagation behavior is event bubbling to the parent, preventing propagation stops the bubbling to the parent. This is different from following the link because following the link is something related to the link itself not attached to its parent, so, it's still there.

return false; if I remember correctly tells jQuery to do both.

Update:

I see you are differentiating the handlers from following the link, based on this, I think this is the answer for you:

jQuery stopPropagation not working when applied to textbox inside anchor

Community
  • 1
  • 1
Meligy
  • 35,654
  • 11
  • 85
  • 109
  • I'm sorry but, if stopPropegation prevents the event from reaching the parent, it means that it should not reach the link tag to follow. What do I miss? – Alkis Kalogeris Jun 12 '13 at 23:20
  • This is what happens for me. In your fiddle, at least in Chrome, when I comment preventDefault, if I click the image placeholder (no real image there) I get alert 2 only, if I click the rest of the link, I get alert 1 only – Meligy Jun 12 '13 at 23:23
  • The parent is the link. Clicking the img is the propegated event. – Alkis Kalogeris Jun 12 '13 at 23:42
  • 1
    Yes this answers my question. Only upvote though. Nucleon answered first. – Alkis Kalogeris Jun 12 '13 at 23:51