{"componentChunkName":"component---src-pages-markdown-remark-fields-slug-js","path":"/engineering/javascript-events-bubbling-capturing-and-propagation/","result":{"data":{"markdownRemark":{"id":"41249db1-bbc4-561f-9e26-b45636298819","excerpt":"A basic example of a JavaScript event Events, in JavaScript, are occurrences that can trigger certain functionality, and can result in certain behaviour. A…","html":"<p><strong>A basic example of a JavaScript event</strong></p>\n<p>Events, in JavaScript, are occurrences that can trigger certain functionality, and can result in certain behaviour. A common example of an event, is a “click”, or a “hover”. You can set listeners to watch for these events that will trigger your desired functionality.</p>\n<p><strong>What is “propagation”?</strong></p>\n<p>Propagation refers to how events travel through the Document Object Model (DOM) tree. The DOM tree is the structure which contains parent/child/sibling elements in relation to each other. You can think of propagation as electricity running through a wire, until it reaches its destination. The event needs to pass through every node on the DOM until it reaches the end, or if it is forcibly stopped.</p>\n<p><strong>Event Bubbling and Capturing</strong></p>\n<p>Bubbling and Capturing are the two phases of propagation. In their simplest definitions, <strong>bubbling</strong> travels from the <em>target</em> to the <em>root</em>, and <strong>capturing</strong> travels from the <em>root</em> to the <em>target</em>. However, that doesn’t make much sense without first defining what a target and a root is.</p>\n<p>The <em>target</em> is the DOM node on which you click, or trigger with any other event.</p>\n<p>For example, a button with a click event would be the event target.</p>\n<p>The <em>root</em> is the highest-level parent of the target. This is usually the <strong>document</strong>, which is a parent of the <strong><body></strong>, which is a (possibly distant) parent of your target element.</p>\n<p>Capturing is not used nearly as commonly as bubbling, so our examples will revolve around the bubbling phase. As an option though, <strong>EventTarget.addEventListener()</strong> has an optional third parameter - which takes its argument as a boolean - which controls the phase of the propagation. The parameter is called <strong>useCapture</strong>, and passing <strong>true</strong> will cause the listener to be on the capturing phase. The default is <strong>false</strong>, which will apply it to the bubbling phase.</p>\n<p>Once you trigger the event, it will <em>propagate</em> up to the root, and it will trigger every single event handler which is associated with the same type. For example, if your button has a click event, during the bubbling phase, it will bubble up to the root, and trigger every click event along the way.</p>\n<p>This kind of behaviour might not sound desirable - and it often isn’t - but there’s an easy workaround...</p>\n<p><strong>Event.stopPropagation()</strong></p>\n<p>These two methods are used for solving the previously mentioned problem regarding event propagation. Calling <strong>Event.stopPropagation()</strong> will prevent further propagation through the DOM tree, and only run the event handler from which it was called.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">Try</span><span class=\"mtk1\"> </span><span class=\"mtk12\">it</span><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">first</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">second</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">2</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">button</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;button&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">container</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">button</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;click&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">first</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">container</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;click&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">second</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>In this example, clicking the button will cause the console to print <strong>1, 2</strong>. If we wanted to modify this so that <em>only</em> the button’s click event is triggered, we could use <strong>Event.stopPropagation()</strong> to immediately stop the event from bubbling to its parent.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">first</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">event</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stopPropagation</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>This modification will allow the console to print <strong>1</strong>, but it will end the event chain right away, preventing it from reaching <strong>2</strong>.</p>\n<p><strong>How does this differ from <code>Event.stopImmediatePropagation()</code>? When would you use either?</strong></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">Try</span><span class=\"mtk1\"> </span><span class=\"mtk12\">it</span><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">first</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">second</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">2</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">third</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">3</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">button</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;button&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">container</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;container&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">button</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;click&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">first</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">button</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;click&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">second</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">container</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;click&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">third</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Let’s suppose we wanted to add a third function, which prints <strong>3</strong> to the console. In this scenario, we will also move the <strong>second</strong> function to also be on the button. We will apply <strong>third</strong> to the container now.</p>\n<p><strong>Long story short</strong>: we have two event handlers on the button, and clicking <strong>&#x3C;div#container></strong> will now print <strong>3</strong>.</p>\n<p>What will happen now? This will behave the same as before, and it will propagate through the DOM tree, and print <strong>1, 2, 3</strong>, in that order.</p>\n<p><strong>How does this tie in to <code>Event.stopPropagation()</code> and <code>Event.stopImmediatePropagation()</code>?</strong></p>\n<p>Adding <strong>Event.stopPropagation()</strong> to the first function, like so, will print <strong>1, 2</strong> to the console.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">first</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">event</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stopPropagation</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>This is because <strong>Event.stopPropagation()</strong> will immediately prevent all click events on the <em>parent</em> from being triggered, but it does <strong>not</strong> stop any <strong>other</strong> event handlers from being called.</p>\n<p>As you can see in our example, our button has two click handlers, and it <em>did</em> stop the propagation to its parents. If you wanted to stop <em>all</em> event handlers after the first, <em>that’s where</em> <strong>Event.stopImmediatePropagation()</strong> <em>comes in.</em></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">first</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">event</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stopImmediatePropagation</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Now, the first function <em>really will</em> stop the parent click handlers, and all other click handlers. The console will now print just <strong>1</strong>, whereas if we simply used <strong>Event.stopPropagation()</strong>, it would print <strong>1, 2</strong>, and not including either would print <strong>1, 2, 3</strong> .</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n</style>","headings":[],"fields":{"slug":"/engineering/javascript-events-bubbling-capturing-and-propagation/"},"frontmatter":{"metatitle":null,"metadescription":null,"description":null,"title":"JavaScript Events: Bubbling, Capturing, and Propagation","canonical":null,"date":"July 22, 2019","updated_date":null,"tags":["JavaScript","JavaScript Events"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.3333333333333333,"src":"/static/53a3895e9c38870937a9136813ac9e10/01e2b/bubbles.webp","srcSet":"/static/53a3895e9c38870937a9136813ac9e10/1c9b5/bubbles.webp 200w,\n/static/53a3895e9c38870937a9136813ac9e10/f1752/bubbles.webp 400w,\n/static/53a3895e9c38870937a9136813ac9e10/01e2b/bubbles.webp 772w","sizes":"(max-width: 772px) 100vw, 772px"}}},"author":{"id":"Greg Sakai","github":null,"bio":"Greg Sakai is a Software Developer at LoginRadius. He is currently studying Computer Science part time, and he loves all things JavaScript. In his spare time, he likes doing homework.","avatar":null}}}},"pageContext":{"id":"41249db1-bbc4-561f-9e26-b45636298819","fields__slug":"/engineering/javascript-events-bubbling-capturing-and-propagation/","__params":{"fields__slug":"engineering"}}},"staticQueryHashes":["1171199041","1384082988","1711371485","1753898100","2100481360","229320306","23180105","528864852"]}