<div class="gmail_quote"><font color="#003300"><font face="courier new,monospace"><div>Hey all,</div><div><br></div><div>I was experimenting with event capturing and bubbling when I noticed something odd: "capturing" event handlers are executed for the target of an event AFTER "bubbling" event handlers have been executed for that target. For example, if an event is fired on a "div" inside a "body", I see the following event listeners being fired in the same order in all mayor browser (Chrome, FF, MSIE (9 beta), Opera, Safari):</div>

<div><div>1) "capture" event listeners for the Document element</div></div><div><div>2) "capture" event listeners for the "html" element</div></div><div><div><div><div>3) "capture" event listeners for the "body" element</div>

</div></div></div><div><div><div><div>4) "bubble"  event listeners for the "div" element</div></div><div><span style="background-color:rgb(255, 204, 204)">5) "capture" event listeners for the "div" element</span></div>

</div></div><div><div><div>6) "bubble"  event listeners for the "body" element</div></div></div><div><div><div>7) "bubble"  event listeners for the "html" element</div></div></div>
<div>
<div><div>8) "bubble"  event listeners for the Document element</div></div></div><div><br></div><div>This fifth entry is odd because:</div><div>1) I didn't expect to see "capturing" event listeners to get executed for the target at all.</div>

<div>2) I expected all "capturing" event handlers to be executed before any "bubbling" event listeners.</div><div><br></div><div>Let me explain where these expectations come from by showing how I interpret the spec at(<a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture" target="_blank">http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture</a>):</div>

<div><div><div><span style="background-color:rgb(255, 255, 255)">Section 1.2.1, paragraph 1:</span></div></div></div></font></font><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<font color="#003300"><font face="courier new,monospace"><div><div><div><span style="background-color:rgb(255, 255, 255)">"<span style="color:rgb(0, 0, 0);font-family:sans-serif">Although all <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener" style="color:rgb(0, 0, 204)" target="_blank"><code style="font-family:monospace">EventListeners</code></a> on the <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget" style="color:rgb(0, 0, 204)" target="_blank"><code style="font-family:monospace">EventTarget</code></a> are guaranteed to be triggered by any event which is received by that <code style="font-family:monospace">EventTarget</code>, no specification is made as to the order in which they will receive the event with regards to the other <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener" style="color:rgb(0, 0, 204)" target="_blank"><code style="font-family:monospace">EventListeners</code></a> on the <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget" style="color:rgb(0, 0, 204)" target="_blank"><code style="font-family:monospace">EventTarget</code></a>. <i><snip></i> If event capture or event bubbling is in use, the event flow will be modified as described in the sections below.</span>".</span></div>

</div></div></font></font></blockquote><font color="#003300"><font face="courier new,monospace"><div><div><span style="background-color:rgb(255, 255, 255)">Section 1.2.2, paragraph 2:</span></div>
</div></font></font><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><font style="color:rgb(0, 51, 0)"><div><div style="font-family:'courier new', monospace">
<span style="background-color:rgb(255, 255, 255)">"</span><span style="font-family:arial"><span style="color:rgb(0, 0, 0);font-family:sans-serif"><span style="background-color:rgb(255, 255, 255)">when an event of the given type is dispatched toward a <em>descendant</em> of the capturing object, the event will trigger any capturing event listeners of the appropriate type which exist in the direct line between the top of the document and the event's target. This downward propagation continues until the event's target is reached.</span><span style="background-color:rgb(255, 255, 204)"> A capturing </span><code style="font-family:monospace;background-color:rgb(255, 255, 204)">EventListener</code><span style="background-color:rgb(255, 255, 204)"> will not be triggered by events dispatched directly to the </span><code style="font-family:monospace;background-color:rgb(255, 255, 204)">EventTarget</code><span style="background-color:rgb(255, 255, 204)"> upon which it is registered.</span></span><span style="background-color:rgb(255, 255, 255)">"</span></span></div>

</div></font></blockquote><font color="#003300"><span style="font-family:'courier new', monospace">paragraph 3:</span><br></font><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<span style="font-family:'courier new', monospace;color:rgb(0, 51, 0)">"</span><span style="color:rgb(0, 0, 0);font-family:sans-serif;background-color:rgb(255, 255, 204)">event capture only allows interception of events which are targeted at <em>descendants</em> of the capturing <code style="font-family:monospace">EventTarget</code>.</span><span style="background-color:rgb(255, 255, 255)">" and "</span><span style="color:rgb(0, 0, 0);font-family:sans-serif;background-color:rgb(255, 255, 204)">event capture intercepts all events of the specified type targeted toward any of the capturer's <em>descendants</em>.</span><span style="background-color:rgb(255, 255, 255)">").</span><span style="font-family:'courier new', monospace;color:rgb(0, 51, 0)">"</span></blockquote>

<div><font color="#003300"><font face="courier new,monospace"><div><div><div><div><span style="background-color:rgb(255, 255, 255)">To me this means </span>"capture" event listeners are <u>not</u> executed for the target element.</div>

</div><div>Section 1.2.2, paragraph 1.2.2:</div></div></div></font></font></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font color="#003300"><font face="courier new,monospace"><div>
<div><div><span style="background-color:rgb(255, 255, 255)">"</span><span style="color:rgb(0, 0, 0);font-family:arial"><span style="color:rgb(0, 0, 0);font-family:sans-serif;background-color:rgb(255, 255, 204)">If no additional capturers exist and <code style="font-family:monospace">stopPropagation </code>has not been called, the event triggers the appropriate <code style="font-family:monospace">EventListeners</code> on the target itself.</span><span style="background-color:rgb(255, 255, 255)">"</span></span></div>

</div></div></font></font></div></blockquote><div><font color="#003300"><font face="courier new,monospace"><div><span style="background-color:rgb(255, 255, 255)"><div><span style="background-color:rgb(255, 255, 255)">This means "bubbling" event listeners <u>are</u> executed for the target element </span><u>after</u> the last "capturing" event listener has been executed.</div>

</span></div><div><br></div><div>Here's how I interpret the spec step-by-step:</div><div>1) Create a list of all nodes from the target "upwards" through its parents towards the Document element. This list is not modified even if elements are removed or added while executing the next steps.</div>

<div><br></div><div>== Capturing phase ==</div><div>2) Set the current element to the "topmost" element at of the list.</div><div>3) Fire all "capture" event listeners for the current element (in any order).</div>

<div>4) If "stopPropagation()" has been called go to step 12.</div><div>5) Set the current element to the next element "down" in the list.</div><div>6) If the current element is not the target element go to step 3.</div>

<div><div><br></div></div><div>== Bubbling phase ==</div><div>7) Fire all "bubbling" event listeners for the current element (in any order).</div><div>8) If "stopPropagation()" has been called stop executing these steps.</div>

<div><div>9) If the current element is the Document element at the "top" of the list stop executing these steps.</div></div><div>10) Set the current element to the next element "up" in the list.</div>
<div>
11) Go to step 7</div><div><br></div><div>== Default behavior phase ==</div><div>12) if "preventDefault()" has been called, stop executing these steps</div><div>13) Execute the default browser behavior for the event and the target, such as opening a link when clicking on it.</div>

<div><br></div><div>I've attached a test case that I used to find out about this. They way I see it, there are a few options:</div><div>- I am interpreting the output of my test wrong,</div><div>- The test has a bug that causes it to display the event order incorrectly,</div>

<div>- The spec is not clear on this subject and I am interpreting it incorrectly,</div><div>- The spec is incorrect,</div><div>- All mayor browser have implemented "capturing" incorrectly.</div><div><br></div>
<div>
Let me know if you have any idea what is going on!</div><div><br></div><div>Cheers,</div><div><br></div><div>SkyLined</div><div><br></div><br clear="all"></font></font>Berend-Jan Wever (<a href="mailto:SkyLined@google.com" target="_blank">SkyLined@google.com</a>) | Security Software Engineer<br>

Google Netherlands B.V. | Reg: Claude Debussylaan 34, 15th floor 1082 MD Amsterdam<br>34198589 | NETHERLANDS | VAT / Tax ID:- 812788515 B01<br>
</div>
</div><br><br clear="all">Berend-Jan Wever (<a href="mailto:SkyLined@google.com">SkyLined@google.com</a>) | Security Software Engineer<br>Google Netherlands B.V. | Reg: Claude Debussylaan 34, 15th floor 1082 MD Amsterdam<br>
34198589 | NETHERLANDS | VAT / Tax ID:- 812788515 B01<br>