Bubble-Up vs. Trickle-Down Javascript Events

The standard event model for Javascript is bubble-up: that's how jQuery, Backbone.js, and plain old addEventListener models events. Given the following DOM:

<div id="container">
    <a id="signup" href="/signup">Sign Up</a>

And the following jQuery event handlers:

$('#signup').on('click', function(e) {
  console.log('#signup click');

$('nav').on('click', function(e) {
  console.log('nav click');

$('#container').on('click', function(e) {
  console.log('#container click');

If you clicked on the "Sign Up" link, your console would look like this:

#signup click
nav click
#container click

And then you would be redirected to /signup.


preventDefault does not affect the event handler tree; it just prevents the default browser action for this event. In our example, an e.preventDefault() in the click handler for #signup would prevent you from being redirected to /signup, but all the other event handlers would still fire.


stopPropagation does the opposite; no other event handlers would fire, but you would still be redirected to /signup.

return false

return false in any event handler in a bubble-up scenario is basically a combination of preventDefault and stopPropagation: it will not only prevent any default browser action, but will also stop the event from bubbling up any further.

Trickle Down

You can also setup event handlers that are trickle-down instead of bubble-up. Trickle down event handlers are setup with addEventListener:

window.document.addEventListener('click', function(e) {
}, true);

The key to setting up a trickle-down event handler is the true argument at the end of addEventListener. In our example above, clicking on #signup would result in this in your console:

#container click
nav click
#signup click

In other words, the event propagation happens in reverse. This could be useful if you wanted to capture every event that happened in your app, for analytics purposes for example.