From 2d9b9db4e1e88cde8072c36d08268fd13e6b0c50 Mon Sep 17 00:00:00 2001 From: Hayato Ito Date: Thu, 4 Feb 2016 14:11:39 +0900 Subject: [PATCH] [Fix #330 #372 #374] Reorganize the "5. Events" section --- spec/shadow/index.html | 752 ++++++++++++++++++++++------------------- 1 file changed, 397 insertions(+), 355 deletions(-) diff --git a/spec/shadow/index.html b/spec/shadow/index.html index 1a276ba4..5a7c954a 100644 --- a/spec/shadow/index.html +++ b/spec/shadow/index.html @@ -650,279 +650,429 @@

Composition Example

Events

-

In each algorithm in this section, the Window must be considered as if it were the parent node of the Document so that the Window also receives an event.

- -

When an event is dispatched in a shadow tree, its path either crosses the shadow trees or is terminated at the shadow root. One exception are the mutation events. The mutation event types must never be dispatched in a shadow tree.

- -
-

Events that are not leaked into ancestor trees

- -

For the following events, scoped flag is initialized to true by default if the events are dispatched by the user agent:

-
    -
  • abort
  • -
  • error
  • -
  • select
  • -
  • change
  • -
  • load
  • -
  • reset
  • -
  • resize
  • -
  • scroll
  • -
  • selectstart
  • -
- -

- Upstream this section into relevant specs, instead of having a fixed list here. -

- -
+

+ In each algorithm in this section, the Window must be considered as if it were the parent node of the Document so that the Window also receives an event. +

Event Paths

-

The event path calculation algorithm must be used to determine event path and must be equivalent to processing the following steps:

+
+

scoped flag

-
-
-
Input
-
NODE, a node
-
EVENT, an event
-
Output
-
PATH, an event path, a ordered list of an event target
-
-
    -
  1. Let PATH be the empty ordered list of nodes
  2. -
  3. Let CURRENT be NODE
  4. -
  5. - Repeat while CURRENT exists: -
      -
    1. Append CURRENT to PATH
    2. -
    3. - If all of the following conditions are satisfied, stop this algorithm: -
        -
      1. CURRENT is a shadow root
      2. -
      3. CURRENT is the root node of NODE
      4. -
      5. EVENT's scoped flag is set
      6. -
      -
    4. -
    5. - If CURRENT is assigned to a slot SLOT: -
        -
      1. Let CURRENT be SLOT
      2. -
      -
    6. -
    7. - Otherwise: -
        -
      1. Let CURRENT be the deep parent of CURRENT
      2. -
      -
    8. -
    -
  6. -
-
+

+ A trusted event's scoped flag must be initialized to true + if the event is one of the following events: abort, error, select, change, load, reset, + resize, scroll and selectstart. +

+
-

- For a trusted event that has a relatedTarget attribute, the event path would be trimmed. See the event path trimming algorithm, which is specified later. -

+
+

relatedTargetScoped flag

-
+

+ A trusted event's relatedTargetScoped flag must be initialized to true + if the event has a relatedTarget property [[!DOM-Level-3-Events]]. +

+
-
-

Event Paths Example

+
+

Event Paths

-

- Let's re-use the same tree of trees used in the composition example section. Suppose that an event is dispatched on node I. The event path will be: -

-

- [I, H, O, T, S, R, N, J, C, A] (Window is omitted) -

+

+ The event path calculation algorithm must be used to determine event path and must be equivalent to processing the following steps: +

-

- It's worth pointing out that if we exclude all nodes which don't participate in the composed tree from the event path, - the result would be equivalent to the inclusive ancestors of the node I in the composed tree. -

+
+
+
Input
+
NODE, a node
+
EVENT, an event
+
Output
+
PATH, an event path, a ordered list of an event target
+
+
    +
  1. + Let PATH be the result of the composed event path calculation algorithm with NODE and EVENT as input +
  2. +
  3. + If EVENT's relatedTargetScoped flag is set and EVENT has a relatedTarget property: +
      +
    1. Let PATH be the result of the event path trimming algorithm with PATH as input
    2. +
    +
  4. +
+
-
- -
- The relationship between the composed tree and an event path. - If we exclude O, T, R and J, that don't participate in the composed tree, from the event path, - the result would be equivalent to the inclusive ancestors of the node, I, in the composed tree. -
-
+

The composed event path calculation algorithm must be equivalent to processing the following steps:

-

- Note that the event path calculation algorithm is designed to achieve the following goals: -

+
+
+
Input
+
NODE, a node
+
EVENT, an event
+
Output
+
PATH, an event path, a ordered list of an event target
+
+
    +
  1. Let PATH be the empty ordered list of nodes
  2. +
  3. Let CURRENT be NODE
  4. +
  5. + Repeat while CURRENT exists: +
      +
    1. Append CURRENT to PATH
    2. +
    3. + If all of the following conditions are satisfied, stop this algorithm: +
        +
      1. CURRENT is a shadow root
      2. +
      3. CURRENT is the root node of NODE
      4. +
      5. EVENT's scoped flag is set
      6. +
      +
    4. +
    5. + If CURRENT is assigned to a slot SLOT: +
        +
      1. Let CURRENT be SLOT
      2. +
      +
    6. +
    7. + Otherwise: +
        +
      1. Let CURRENT be the deep parent of CURRENT
      2. +
      +
    8. +
    +
  6. +
+
-
    -
  1. - If there is a node, CHILD, in the event path and CHILD has a parent node, PARENT, in the component tree, the event path always includes PARENT. - PARENT always appears somewhere after CHILD in the event path. -
  2. -
  3. - Nodes in the event path form a linear ancestor chain in each component tree. There are no branch points in each component tree. -
  4. -
+

+ The event path trimming algorithm must be equivalent to processing the following steps: +

-
- > -
- The relationship between an event path and component trees. In the figure, a number shown in a right-side of each node represents a zero-based position of each node in the event path. - A parent node always has a larger number than that of its child node in each component tree. -
-
+
+
+
Input
+
EVENT-PATH, the event path, which is the result of the composed event path calculation algorithm
+
Output
+
EVENT-PATH is trimmed
+
+
    +
  1. + For each object, A, in EVENT-PATH: +
      +
    1. Let RELATIVE-TARGET be the relative target for A
    2. +
    3. Let RELATIVE-RELATED-TARGET be the relative related target for A
    4. +
    5. If RELATIVE-TARGET and RELATIVE-RELATED-TARGET are the same, remove A from EVENT-PATH.
    6. +
    +
  2. +
+
-

A local event path for each component tree would be seen as: -

+

+ The definitions of relative target and relative related target are specified later. +

- - - - - - - - - - - - - - - - - - - - - -
component treeLocal Event Path
document tree 1[I, H, C, A]
shadow tree 1[O, N, J]
shadow tree 2[T, S, R]
+
+

+ The motivation of the event path trimming algorithm is to avoid the appearance of spurious events, such as mouseover or mouseout events, firing at the node in ancestor trees + in cases where both relatedTarget and target are part of the same shadow tree, +

+
-

- That means, if your concern is only one component tree, you can forget all other component trees. - The event path would be seen as if the event happened only on the component tree you are focusing on. - This is an important aspect in a sense that hosting a shadow tree doesn't have any effect to the local event path - as long as the event is not stopped somewhere in the descendant trees. -

-

- If you are a web author and your concern is only a document tree, this might be a good news because an event listener that is registered somewhere on the document tree - would continue to work even when you attach a shadow root to an element in the document tree to enhance the element. - At the same time, an author of a shadow tree also can receive an event which will happen on a node in the document tree, if the node, or its ancestor, is assigned to a slot in the shadow tree. -

+
-
+
+

Event Paths Example

-
-

Event Retargeting

+

+ Let's re-use the same tree of trees used in the composition example section. Suppose that an event is dispatched on node I. The event path will be: +

+

+ [I, H, O, T, S, R, N, J, C, A] (Window is omitted) +

-

In the cases where event path is across multiple component trees, the event's information about the target of the event is adjusted in order to maintain encapsulation. Event retargeting is a process of computing relative targets for each ancestor of the node at which the event is dispatched. A relative target is a node that most accurately represents the target of a dispatched event at a given ancestor while maintaining the encapsulation.

+

+ It's worth pointing out that if we exclude all nodes which don't participate in the composed tree from the event path, + the result would be equivalent to the inclusive ancestors of the node I in the composed tree. +

-

The retargeting algorithm is used to determine relative targets and must be equivalent to processing the following steps:

+
+ +
+ The relationship between the composed tree and an event path. + If we exclude O, T, R and J, that don't participate in the composed tree, from the event path, + the result would be equivalent to the inclusive ancestors of the node, I, in the composed tree. +
+
+ +

+ Note that the event path calculation algorithm is designed to achieve the following goals: +

-
-
-
Input
-
BASE, a base node for which a target node should be adjusted
-
TARGET, a target node which should be adjusted
-
Output
-
RELATIVE-TARGET, a relative target, the result of adjusting TARGET for BASE
-
    -
  1. Let BASE-TREE be the component tree which BASE participates in
  2. -
  3. Let TARGET-TREE be the component tree which TARGET participates in
  4. -
  5. If BASE-TREE and TARGET-TREE participate in the same tree of trees: -
      -
    1. Let COMMON-ANCESTOR-TREE be the lowest common inclusive ancestor tree of BASE-TREE and TARGET-TREE
    2. -
    -
  6. -
  7. Otherwise: -
      -
    1. Let COMMON-ANCESTOR-TREE be the root tree of TARGET-TREE
    2. -
    +
  8. + If there is a node, CHILD, in the event path and CHILD has a parent node, PARENT, in the component tree, the event path always includes PARENT. + PARENT always appears somewhere after CHILD in the event path.
  9. - For each node, ANCETOR, in an inclusive deep ancestor nodes of TARGET, from descendants to ancestors: -
      -
    1. - If ANCESTOR participates in COMMON-ANCESTOR-TREE: -
        -
      1. Let RELATIVE-TARGET be ANCESTOR
      2. -
      3. Stop this algorithm
      4. -
      -
    2. -
    + Nodes in the event path form a linear ancestor chain in each component tree. There are no branch points in each component tree.
-
-

The value of the Event object's target attribute must be the result of the retargeting algorithm with the event's currentTarget and target as input.

-

The event target retargeting process must occur prior to dispatch of an event.

-
+
+ > +
+ The relationship between an event path and component trees. In the figure, a number shown in a right-side of each node represents a zero-based position of each node in the event path. + A parent node always has a larger number than that of its child node in each component tree. +
+
-
-

Retargeting relatedTarget

+

A local event path for each component tree would be seen as: +

-

Some events have a relatedTarget [[!DOM-Level-3-Events]] property, which holds a node that's not the event's target, but is related to the event.

+ + + + + + + + + + + + + + + + + + + + + +
component treeLocal Event Path
document tree 1[I, H, C, A]
shadow tree 1[O, N, J]
shadow tree 2[T, S, R]
-

- For instance, a mouseover event's relatedTarget may hold the node from which the mouse has moved to event's target. In the case where relatedTarget is in a shadow tree, the conforming UAs must not leak its actual value outside of this tree. -

-

- The value of the Event object's relatedTarget attribute must be the result of the retargeting algorithm with the event's currentTarget and relatedTarget as input. The result is called a relative related target. -

-

- The event relatedTarget retargeting process must occur prior to dispatch of an event. -

+

+ That means, if your concern is only one component tree, you can forget all other component trees. + The event path would be seen as if the event happened only on the component tree you are focusing on. + This is an important aspect in a sense that hosting a shadow tree doesn't have any effect to the local event path + as long as the event is not stopped somewhere in the descendant trees. +

+

+ If you are a web author and your concern is only a document tree, this might be a good news because an event listener that is registered somewhere on the document tree + would continue to work even when you attach a shadow root to an element in the document tree to enhance the element. + At the same time, an author of a shadow tree also can receive an event which will happen on a node in the document tree, if the node, or its ancestor, is assigned to a slot in the shadow tree. +

+ +
-

Retargeting Touch Events

+

Event Retargeting

-

The Touch target [[!TOUCH-EVENTS]] attribute must be adjusted in the same way as an event with a relatedTarget. Each Touch target in the TouchList returned from TouchEvent touches(), changedTouches() and targetTouches() must be the result of the retargeting algorithm with a current target and Touch target as input.

-
+
+

Event target Retargeting

-
-

Retargeting Focus Events

+

The value of the Event object's target attribute must be the result of the retargeting algorithm with the event's currentTarget and original target value, before adjusted, as input. The result is called a relative target. +

-

The focus, focusin, blur, and focusout events must be treated in the same way as events with a relatedTarget, where the corresponding node that is losing focus as a result of target gaining focus or the node that is gaining focus, and thus causing the blurring of target acts as the related target.

-
+

The retargeting algorithm must be equivalent to processing the following steps:

-
-

Event Path Trimming

+
+
+
Input
+
BASE, a base node for which a target node should be adjusted
+
TARGET, a target node which should be adjusted
+
Output
+
RELATIVE-TARGET, a relative target, the result of adjusting TARGET for BASE
+
+
    +
  1. Let BASE-TREE be the component tree which BASE participates in
  2. +
  3. Let TARGET-TREE be the component tree which TARGET participates in
  4. +
  5. If BASE-TREE and TARGET-TREE participate in the same tree of trees: +
      +
    1. Let COMMON-ANCESTOR-TREE be the lowest common inclusive ancestor tree of BASE-TREE and TARGET-TREE
    2. +
    +
  6. +
  7. Otherwise: +
      +
    1. Let COMMON-ANCESTOR-TREE be the root tree of TARGET-TREE
    2. +
    +
  8. +
  9. + For each node, ANCETOR, in an inclusive deep ancestor nodes of TARGET, from descendants to ancestors: +
      +
    1. + If ANCESTOR participates in COMMON-ANCESTOR-TREE: +
        +
      1. Let RELATIVE-TARGET be ANCESTOR
      2. +
      3. Stop this algorithm
      4. +
      +
    2. +
    +
  10. +
+
-

- In cases where both relatedTarget and target of a trusted event are part of the same shadow tree, the conforming UAs must stop events at the shadow root to avoid the appearance of spurious mouseover and mouseout events firing from the same node. -

-

- Thus, event listeners for trusted events must not be invoked on a node for which the target and relatedTarget are the same. -

+

+ Event retargeting is a process of computing relative targets for each ancestor of the node at which the event is dispatched. + The event target retargeting process must occur prior to dispatch of an event. + In other words, any DOM mutation occurred in an event listener does not have any affect on the result of retargeting process. +

+ +

+ The motivation of retargeting is to maintain an encapsulation in the cases where event path is across multiple component trees. + The event's target might not be an unclosed node at some of nodes in the event path without retargeting. + A relative target is a unclosed node that most accurately represents the target of a dispatched event at each node in the event path. +

+
+ +
+

Event relatedTarget Retargeting

+ +

Some events have a relatedTarget property, which holds a node that's not the event's target, but is related to the event.

+ +

+ The value of the Event object's relatedTarget attribute must be the result of the retargeting algorithm with the event's currentTarget and relatedTarget as input. + The result is called a relative related target. +

+ +

+ The event relatedTarget retargeting process must occur prior to dispatch of an event. +

+
+ +
+

Touch Events Retargeting

+ +

The Touch target [[!TOUCH-EVENTS]] attribute must be adjusted in the same way as an event with a relatedTarget. Each Touch target in the TouchList returned from TouchEvent touches(), changedTouches() and targetTouches() must be the result of the retargeting algorithm with a current target and Touch target as input.

+
+ +
+

Event Retargeting Example

+ +

Suppose we have a user interface for a media controller, represented by this tree, composed of both document tree and the shadow trees. In this example, we will assume that selectors are allowed to cross the shadow boundaries and we will use these selectors to identify the elements. Also, we will invent a fictional shadow-root element to demarcate the shadow boundaries and represent shadow roots:

+
+  <div id="player">
+      <shadow-root id="player-shadow-root">
+          <div id="controls">
+              <button id="play-button">PLAY</button>
+              <input type="range" id="timeline">
+                  <shadow-root id="timeline-shadow-root">
+                      <div id="slider-thumb" id="timeline-slider-thumb"></div>
+                  </shadow-root>
+              </input>
+              <div id="volume-slider-container">
+                  <input type="range" id="volume-slider">
+                      <shadow-root id="volume-shadow-root">
+                          <div id="slider-thumb" id="volume-slider-thumb"></div>
+                      </shadow-root>
+                  </input>
+              </div>
+          </div>
+      </shadow-root>
+  </div>
+          
+ +

Let's have a user position their pointing device over the volume slider's thumb (#volume-slider-thumb), thus triggering a mouseover event on that node. For this event, let's pretend it has no associated relatedTarget.

+ +

Per the retargeting algorithm, we should have the following set of ancestors and relative targets:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AncestorRelative Target
#player#player
#player-shadow-root#volume-slider
#controls#volume-slider
#volume-slider-container#volume-slider
#volume-slider#volume-slider
#volume-shadow-root#volume-slider-thumb
#volume-slider-thumb#volume-slider-thumb
+ +

After we dispatch the mouseover event using these newly computed relative targets, the user decides to move their pointing device over the thumb of the timeline + (#timeline-slider-thumb). This triggers both a mouseout event for the volume slider thumb and the mouseover event for the timeline thumb.

+ +

Let's see how the relatedTarget value of the volume thumb's mouseout event is affected. For this event, the relatedTarget is the timeline thumb (#timeline-slider-thumb). Per the relatedTarget retargeting, we should have the following set of ancestors and adjusted related targets:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AncestorRelative TargetRelative Related Target
#player#player#player
#player-shadow-root#volume-slider#timeline
#controls#volume-slider#timeline
#volume-slider-container#volume-slider#timeline
#volume-slider#volume-slider#timeline
#volume-shadow-root#volume-slider-thumb#timeline
#volume-slider-thumb#volume-slider-thumb#timeline
+ +

The node, #player, has both target and relatedTarget being the same value (#player), which means that we do not dispatch the event on this node and its ancestors.

+
-

- The event path trimming algorithm must be used to trim the event path for a trusted event that has a relatedTarget attribute and - must be equivalent to processing the following steps: -

-
-
-
Input
-
EVENT-PATH, the event path, which is the result of the event path calculation algorithm
-
Output
-
EVENT-PATH is trimmed so that event listeners aren't invoked on a node for which the target and relatedTarget are the same.
-
-
    -
  1. - For each object, A, in EVENT-PATH: -
      -
    1. Let RELATIVE-TARGET be the relative target for A
    2. -
    3. Let RELATIVE-RELATED-TARGET be the relative related target for A
    4. -
    5. If RELATIVE-TARGET and RELATIVE-RELATED-TARGET are the same, remove A from EVENT-PATH.
    6. -
    -
  2. -
-
-

- For an untrusted event, the event path trimming algorithm is not used. -

@@ -941,130 +1091,12 @@

Event Dispatch

-

Upon completion of the event dispatch, the Event object's target and relatedTarget must be to the highest ancestor's relative target. Since it is possible for a script to hold on to the Event object past the scope of event dispatch, this step is necessary to avoid revealing the nodes in shadow trees.

-
+

Upon completion of the event dispatch, the Event object's target and relatedTarget must be to the highest ancestor's relative target and relative related target, respectively. Since it is possible for a script to hold on to the Event object past the scope of event dispatch, this step is necessary to avoid revealing the nodes in shadow trees.

-
-

Event Retargeting Example

- -

Suppose we have a user interface for a media controller, represented by this tree, composed of both document tree and the shadow trees. In this example, we will assume that selectors are allowed to cross the shadow boundaries and we will use these selectors to identify the elements. Also, we will invent a fictional shadow-root element to demarcate the shadow boundaries and represent shadow roots:

-
-<div id="player">
-    <shadow-root id="player-shadow-root">
-        <div id="controls">
-            <button id="play-button">PLAY</button>
-            <input type="range" id="timeline">
-                <shadow-root id="timeline-shadow-root">
-                    <div id="slider-thumb" id="timeline-slider-thumb"></div>
-                </shadow-root>
-            </input>
-            <div id="volume-slider-container">
-                <input type="range" id="volume-slider">
-                    <shadow-root id="volume-shadow-root">
-                        <div id="slider-thumb" id="volume-slider-thumb"></div>
-                    </shadow-root>
-                </input>
-            </div>
-        </div>
-    </shadow-root>
-</div>
-        
- -

Let's have a user position their pointing device over the volume slider's thumb (#volume-slider-thumb), thus triggering a mouseover event on that node. For this event, let's pretend it has no associated relatedTarget.

- -

Per the retargeting algorithm, we should have the following set of ancestors and relative targets:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AncestorRelative Target
#player#player
#player-shadow-root#volume-slider
#controls#volume-slider
#volume-slider-container#volume-slider
#volume-slider#volume-slider
#volume-shadow-root#volume-slider-thumb
#volume-slider-thumb#volume-slider-thumb
- -

After we dispatch the mouseover event using these newly computed relative targets, the user decides to move their pointing device over the thumb of the timeline - (#timeline-slider-thumb). This triggers both a mouseout event for the volume slider thumb and the mouseover event for the timeline thumb.

- -

Let's see how the relatedTarget value of the volume thumb's mouseout event is affected. For this event, the relatedTarget is the timeline thumb (#timeline-slider-thumb). Per the relatedTarget retargeting, we should have the following set of ancestors and adjusted related targets:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AncestorRelative TargetAdjusted related Target
#player#player#player
#player-shadow-root#volume-slider#timeline
#controls#volume-slider#timeline
#volume-slider-container#volume-slider#timeline
#volume-slider#volume-slider#timeline
#volume-shadow-root#volume-slider-thumb#timeline
#volume-slider-thumb#volume-slider-thumb#timeline
+

+ The mutation event types must never be dispatched in a shadow tree. +

-

The node, #player, has both target and relatedTarget being the same value (#player), which means that we do not dispatch the event on this node and its ancestors.

@@ -1537,6 +1569,10 @@

Extensions to EventInit Dictionary

Specifies the scoped flag of Event

+
boolean relatedTargetScoped = false
+
+

Specifies the relatedTargetScoped flag of Event

+
@@ -1587,6 +1623,12 @@

Extensions to Event Interface

Returns the scoped flag.

+
readonly attribute boolean relatedTargetScoped
+
+

+ Returns the relatedTargetScoped flag. +

+