Skip to content

Commit

Permalink
Define special dispatch behavior for click events
Browse files Browse the repository at this point in the history
User agents have always had special behavior for synthetic click
events. This is discussed to great extent in
https://www.w3.org/Bugs/Public/show_bug.cgi?id=12230.

This change introduces the hooks to no longer make that magical, but an
understood and integral part of the processing model, ugly as it is.

This changes requires corresponding changes and cleanup in HTML. See
whatwg/html#1394 for that discussion.

Fixes #325.
  • Loading branch information
annevk authored Oct 17, 2016
1 parent e19d7ee commit cb12fd4
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 8 deletions.
66 changes: 61 additions & 5 deletions dom.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,22 @@ specified otherwise it returns null.
<p class="note no-backref"><a>Nodes</a>, <a for=/>shadow roots</a>, and <a>documents</a> override
the <a>get the parent</a> algorithm.

<p>Each {{EventTarget}} object can have an associated
<dfn export for=EventTarget>activation behavior</dfn> algorithm. The <a>activation behavior</a>
algorithm is passed an <a>event</a>, as indicated in the <a>dispatch</a> algorithm.</p>

<p class="note no-backref">This exists because user agents perform certain actions for certain
{{EventTarget}} objects, e.g., the <{area}> element, in response to synthetic {{MouseEvent}}
<a>events</a> whose {{Event/type}} attribute is <code>click</code>. Web compatibility prevented it
from being removed and it is now the enshrined way of defining an activation of something. [[!HTML]]

<p>Each {{EventTarget}} object that has <a>activation behavior</a>, can additionally have both (not
either) a <dfn export for=EventTarget>legacy pre-click-dispatch steps</dfn> algorithm and a
<dfn export for=EventTarget>legacy post-canceled-click-dispatch steps</dfn> algorithm.

<p class="note no-backref">These algorithms only exist for checkbox and radio <{input}> elements and
are not to be used for anything else. [[!HTML]]

<dl class=domintro>
<dt><code><var>target</var> . <a method lt="addEventListener()">addEventListener</a>(<var>type</var>, <var>callback</var> [, <var>options</var>])</code>
<dd>
Expand Down Expand Up @@ -1204,6 +1220,12 @@ for discussion).
<li><p>Append (<var>target</var>, <var>targetOverride</var>, <var>relatedTarget</var>) to <var>event</var>'s
<a for=Event>path</a>.

<li><p>Let <var>isActivationEvent</var> be true, if <var>event</var> is a {{MouseEvent}} object and
<var>event</var>'s {{Event/type}} attribute is "<code>click</code>", and false otherwise.

<li><p>Let <var>activationTarget</var> be <var>target</var>, if <var>isActivationEvent</var> is
true and <var>target</var> has <a>activation behavior</a>, and null otherwise.

<li><p>Let <var>parent</var> be the result of invoking <var>target</var>'s <a>get the parent</a>
with <var>event</var>.

Expand All @@ -1215,22 +1237,44 @@ for discussion).
<a>relatedTarget</a> against <var>parent</var> if <var>event</var>'s <a>relatedTarget</a> is
non-null, and null otherwise.

<li><p>If <var>target</var>'s <a for=tree>root</a> is a
<a>shadow-including inclusive ancestor</a> of <var>parent</var>, then append
(<var>parent</var>, null, <var>relatedTarget</var>) to <var>event</var>'s <a for=Event>path</a>.
<li>
<p>If <var>target</var>'s <a for=tree>root</a> is a
<a>shadow-including inclusive ancestor</a> of <var>parent</var>, then:

<ol>
<li><p>If <var>isActivationEvent</var> is true, <var>event</var>'s {{Event/bubbles}} attribute
is true, <var>activationTarget</var> is null, and <var>parent</var> has
<a>activation behavior</a>, then set <var>activationTarget</var> to <var>parent</var>.

<li><p>Append (<var>parent</var>, null, <var>relatedTarget</var>) to <var>event</var>'s
<a for=Event>path</a>.
</ol>

<li><p>Otherwise, if <var>parent</var> and <var>relatedTarget</var> are identical, then set
<var>parent</var> to null.

<li><p>Otherwise, set <var>target</var> to <var>parent</var> and append (<var>parent</var>,
<var>target</var>, <var>relatedTarget</var>) to <var>event</var>'s <a for=Event>path</a>.
<li>
<p>Otherwise, set <var>target</var> to <var>parent</var> and then:

<ol>
<li><p>If <var>isActivationEvent</var> is true, <var>activationTarget</var> is null, and
<var>target</var> has <a>activation behavior</a>, then set <var>activationTarget</var> to
<var>target</var>.

<li><p>Append (<var>parent</var>, <var>target</var>, <var>relatedTarget</var>) to
<var>event</var>'s <a for=Event>path</a>.
</ol>

<li><p>If <var>parent</var> is non-null, then set <var>parent</var> to the result of invoking
<var>parent</var>'s <a>get the parent</a> with <var>event</var>.
</ol>

<li><p>Set <var>event</var>'s {{Event/eventPhase}} attribute to {{Event/CAPTURING_PHASE}}.

<li><p>If <var>activationTarget</var> is non-null and <var>activationTarget</var> has
<a>legacy pre-click-dispatch steps</a>, then run <var>activationTarget</var>'s
<a>legacy pre-click-dispatch steps</a>.

<li>
<p>For each <var>tuple</var> in <var>event</var>'s <a for=Event>path</a>, in reverse order:

Expand Down Expand Up @@ -1280,6 +1324,18 @@ for discussion).

<li><p>Set <var>event</var>'s <a for=Event>path</a> to the empty list.

<li>
<p>If <var>activationTarget</var> is non-null, then:

<ol>
<li><p>If <var>event</var>'s <a>canceled flag</a> is unset, then run
<var>activationTarget</var>'s <a>activation behavior</a> with <var>event</var>.

<li><p>Otherwise, if <var>activationTarget</var> has
<a>legacy post-canceled-click-dispatch steps</a>, then run <var>activationTarget</var>'s
<a>legacy post-canceled-click-dispatch steps</a>.
</ol>

<li><p>Return false if <var>event</var>'s <a>canceled flag</a> is set, and true otherwise.
</ol>

Expand Down
44 changes: 41 additions & 3 deletions dom.html
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,13 @@ <h3 class="heading settled" data-level="3.6" id="interface-eventtarget"><span cl
specified otherwise it returns null. </p>
<p class="note no-backref" role="note"><a data-link-type="dfn" href="#concept-node">Nodes</a>, <a data-link-type="dfn" href="#concept-shadow-root">shadow roots</a>, and <a data-link-type="dfn" href="#concept-document">documents</a> override
the <a data-link-type="dfn" href="#get-the-parent">get the parent</a> algorithm. </p>
<p>Each <code class="idl"><a data-link-type="idl" href="#eventtarget">EventTarget</a></code> object can have an associated <dfn data-dfn-for="EventTarget" data-dfn-type="dfn" data-export="" id="eventtarget-activation-behavior">activation behavior<a class="self-link" href="#eventtarget-activation-behavior"></a></dfn> algorithm. The <a data-link-type="dfn" href="#eventtarget-activation-behavior">activation behavior</a> algorithm is passed an <a data-link-type="dfn" href="#concept-event">event</a>, as indicated in the <a data-link-type="dfn" href="#concept-event-dispatch">dispatch</a> algorithm.</p>
<p class="note no-backref" role="note">This exists because user agents perform certain actions for certain <code class="idl"><a data-link-type="idl" href="#eventtarget">EventTarget</a></code> objects, e.g., the <code><a data-link-type="element" href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-area-element">area</a></code> element, in response to synthetic <code class="idl"><a data-link-type="idl" href="https://w3c.github.io/uievents/#interface-mouseevent">MouseEvent</a></code> <a data-link-type="dfn" href="#concept-event">events</a> whose <code class="idl"><a data-link-type="idl" href="#dom-event-type">type</a></code> attribute is <code>click</code>. Web compatibility prevented it
from being removed and it is now the enshrined way of defining an activation of something. <a data-link-type="biblio" href="#biblio-html">[HTML]</a> </p>
<p>Each <code class="idl"><a data-link-type="idl" href="#eventtarget">EventTarget</a></code> object that has <a data-link-type="dfn" href="#eventtarget-activation-behavior">activation behavior</a>, can additionally have both (not
either) a <dfn data-dfn-for="EventTarget" data-dfn-type="dfn" data-export="" id="eventtarget-legacy-pre-click-dispatch-steps">legacy pre-click-dispatch steps<a class="self-link" href="#eventtarget-legacy-pre-click-dispatch-steps"></a></dfn> algorithm and a <dfn data-dfn-for="EventTarget" data-dfn-type="dfn" data-export="" id="eventtarget-legacy-post-canceled-click-dispatch-steps">legacy post-canceled-click-dispatch steps<a class="self-link" href="#eventtarget-legacy-post-canceled-click-dispatch-steps"></a></dfn> algorithm. </p>
<p class="note no-backref" role="note">These algorithms only exist for checkbox and radio <code><a data-link-type="element" href="https://html.spec.whatwg.org/multipage/forms.html#the-input-element">input</a></code> elements and
are not to be used for anything else. <a data-link-type="biblio" href="#biblio-html">[HTML]</a> </p>
<dl class="domintro">
<dt><code><var>target</var> . <a class="idl-code" data-link-type="method" href="#dom-eventtarget-addeventlistener">addEventListener</a>(<var>type</var>, <var>callback</var> [, <var>options</var>])</code>
<dd>
Expand Down Expand Up @@ -882,6 +889,11 @@ <h3 class="heading settled" data-level="3.8" id="dispatching-events"><span class
non-null, and null otherwise.
<li>
<p>Append (<var>target</var>, <var>targetOverride</var>, <var>relatedTarget</var>) to <var>event</var>’s <a data-link-type="dfn" href="#event-path">path</a>. </p>
<li>
<p>Let <var>isActivationEvent</var> be true, if <var>event</var> is a <code class="idl"><a data-link-type="idl" href="https://w3c.github.io/uievents/#interface-mouseevent">MouseEvent</a></code> object and <var>event</var>’s <code class="idl"><a data-link-type="idl" href="#dom-event-type">type</a></code> attribute is "<code>click</code>", and false otherwise. </p>
<li>
<p>Let <var>activationTarget</var> be <var>target</var>, if <var>isActivationEvent</var> is
true and <var>target</var> has <a data-link-type="dfn" href="#eventtarget-activation-behavior">activation behavior</a>, and null otherwise. </p>
<li>
<p>Let <var>parent</var> be the result of invoking <var>target</var>’s <a data-link-type="dfn" href="#get-the-parent">get the parent</a> with <var>event</var>. </p>
<li>
Expand All @@ -891,17 +903,31 @@ <h3 class="heading settled" data-level="3.8" id="dispatching-events"><span class
<p>Let <var>relatedTarget</var> be the result of <a data-link-type="dfn" href="#retarget">retargeting</a> <var>event</var>’s <a data-link-type="dfn" href="#event-relatedtarget">relatedTarget</a> against <var>parent</var> if <var>event</var>’s <a data-link-type="dfn" href="#event-relatedtarget">relatedTarget</a> is
non-null, and null otherwise. </p>
<li>
<p>If <var>target</var>’s <a data-link-type="dfn" href="#concept-tree-root">root</a> is a <a data-link-type="dfn" href="#concept-shadow-including-inclusive-ancestor">shadow-including inclusive ancestor</a> of <var>parent</var>, then append
(<var>parent</var>, null, <var>relatedTarget</var>) to <var>event</var>’s <a data-link-type="dfn" href="#event-path">path</a>. </p>
<p>If <var>target</var>’s <a data-link-type="dfn" href="#concept-tree-root">root</a> is a <a data-link-type="dfn" href="#concept-shadow-including-inclusive-ancestor">shadow-including inclusive ancestor</a> of <var>parent</var>, then: </p>
<ol>
<li>
<p>If <var>isActivationEvent</var> is true, <var>event</var>’s <code class="idl"><a data-link-type="idl" href="#dom-event-bubbles">bubbles</a></code> attribute
is true, <var>activationTarget</var> is null, and <var>parent</var> has <a data-link-type="dfn" href="#eventtarget-activation-behavior">activation behavior</a>, then set <var>activationTarget</var> to <var>parent</var>. </p>
<li>
<p>Append (<var>parent</var>, null, <var>relatedTarget</var>) to <var>event</var>’s <a data-link-type="dfn" href="#event-path">path</a>. </p>
</ol>
<li>
<p>Otherwise, if <var>parent</var> and <var>relatedTarget</var> are identical, then set <var>parent</var> to null. </p>
<li>
<p>Otherwise, set <var>target</var> to <var>parent</var> and append (<var>parent</var>, <var>target</var>, <var>relatedTarget</var>) to <var>event</var>’s <a data-link-type="dfn" href="#event-path">path</a>. </p>
<p>Otherwise, set <var>target</var> to <var>parent</var> and then: </p>
<ol>
<li>
<p>If <var>isActivationEvent</var> is true, <var>activationTarget</var> is null, and <var>target</var> has <a data-link-type="dfn" href="#eventtarget-activation-behavior">activation behavior</a>, then set <var>activationTarget</var> to <var>target</var>. </p>
<li>
<p>Append (<var>parent</var>, <var>target</var>, <var>relatedTarget</var>) to <var>event</var>’s <a data-link-type="dfn" href="#event-path">path</a>. </p>
</ol>
<li>
<p>If <var>parent</var> is non-null, then set <var>parent</var> to the result of invoking <var>parent</var>’s <a data-link-type="dfn" href="#get-the-parent">get the parent</a> with <var>event</var>. </p>
</ol>
<li>
<p>Set <var>event</var>’s <code class="idl"><a data-link-type="idl" href="#dom-event-eventphase">eventPhase</a></code> attribute to <code class="idl"><a data-link-type="idl" href="#dom-event-capturing_phase">CAPTURING_PHASE</a></code>. </p>
<li>
<p>If <var>activationTarget</var> is non-null and <var>activationTarget</var> has <a data-link-type="dfn" href="#eventtarget-legacy-pre-click-dispatch-steps">legacy pre-click-dispatch steps</a>, then run <var>activationTarget</var>’s <a data-link-type="dfn" href="#eventtarget-legacy-pre-click-dispatch-steps">legacy pre-click-dispatch steps</a>. </p>
<li>
<p>For each <var>tuple</var> in <var>event</var>’s <a data-link-type="dfn" href="#event-path">path</a>, in reverse order: </p>
<ol>
Expand Down Expand Up @@ -940,6 +966,14 @@ <h3 class="heading settled" data-level="3.8" id="dispatching-events"><span class
<p>Set <var>event</var>’s <code class="idl"><a data-link-type="idl" href="#dom-event-currenttarget">currentTarget</a></code> attribute to null. </p>
<li>
<p>Set <var>event</var>’s <a data-link-type="dfn" href="#event-path">path</a> to the empty list. </p>
<li>
<p>If <var>activationTarget</var> is non-null, then: </p>
<ol>
<li>
<p>If <var>event</var>’s <a data-link-type="dfn" href="#canceled-flag">canceled flag</a> is unset, then run <var>activationTarget</var>’s <a data-link-type="dfn" href="#eventtarget-activation-behavior">activation behavior</a> with <var>event</var>. </p>
<li>
<p>Otherwise, if <var>activationTarget</var> has <a data-link-type="dfn" href="#eventtarget-legacy-post-canceled-click-dispatch-steps">legacy post-canceled-click-dispatch steps</a>, then run <var>activationTarget</var>’s <a data-link-type="dfn" href="#eventtarget-legacy-post-canceled-click-dispatch-steps">legacy post-canceled-click-dispatch steps</a>. </p>
</ol>
<li>
<p>Return false if <var>event</var>’s <a data-link-type="dfn" href="#canceled-flag">canceled flag</a> is set, and true otherwise. </p>
</ol>
Expand Down Expand Up @@ -5627,6 +5661,7 @@ <h2 class="no-num no-ref heading settled" id="index"><span class="content">Index
<h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3>
<ul class="index">
<li><a href="#dom-nodefilter-acceptnode">acceptNode(node)</a><span>, in §6.3</span>
<li><a href="#eventtarget-activation-behavior">activation behavior</a><span>, in §3.6</span>
<li><a href="#dom-domtokenlist-add">add()</a><span>, in §7.1</span>
<li><a href="#dom-mutationrecord-addednodes">addedNodes</a><span>, in §4.3.3</span>
<li><a href="#dictdef-addeventlisteneroptions">AddEventListenerOptions</a><span>, in §3.6</span>
Expand Down Expand Up @@ -6061,6 +6096,8 @@ <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="c
<li><a href="#dom-treewalker-lastchild">lastChild()</a><span>, in §6.2</span>
<li><a href="#dom-node-lastchild">lastChild</a><span>, in §4.4</span>
<li><a href="#dom-parentnode-lastelementchild">lastElementChild</a><span>, in §4.2.6</span>
<li><a href="#eventtarget-legacy-post-canceled-click-dispatch-steps">legacy post-canceled-click-dispatch steps</a><span>, in §3.6</span>
<li><a href="#eventtarget-legacy-pre-click-dispatch-steps">legacy pre-click-dispatch steps</a><span>, in §3.6</span>
<li>
length
<ul>
Expand Down Expand Up @@ -6536,6 +6573,7 @@ <h3 class="no-num no-ref heading settled" id="index-defined-elsewhere"><span cla
<li><a href="https://html.spec.whatwg.org/multipage/webstorage.html#storageevent">StorageEvent</a>
<li><a href="https://html.spec.whatwg.org/multipage/embedded-content.html#trackevent">TrackEvent</a>
<li><a href="https://html.spec.whatwg.org/multipage/browsers.html#window">Window</a>
<li><a href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-area-element">area</a>
<li><a href="https://html.spec.whatwg.org/multipage/browsers.html#concept-document-window">associated document</a>
<li><a href="https://html.spec.whatwg.org/multipage/semantics.html#the-body-element">body</a>
<li><a href="https://html.spec.whatwg.org/multipage/browsers.html#browsing-context">browsing context</a>
Expand Down

0 comments on commit cb12fd4

Please sign in to comment.