diff --git a/dom.bs b/dom.bs index d22cdefd1..1a25571ad 100644 --- a/dom.bs +++ b/dom.bs @@ -104,6 +104,8 @@ urlPrefix: https://html.spec.whatwg.org/multipage/ text: effective script origin text: origin alias; url: #concept-origin-alias text: Unicode serialization of an origin; url: #unicode-serialisation-of-an-origin + urlPrefix: infrastructure.html + text: in parallel urlPrefix: https://w3c.github.io/webcomponents/spec/shadow/ type: dfn; urlPrefix: #dfn- text: shadow root @@ -613,7 +615,7 @@ Lets look at an example of how events work in a tree: function test(e) { debug(e.target, e.currentTarget, e.eventPhase) } - document.addEventListener("hey", test, true) + document.addEventListener("hey", test, {capture: true}) document.body.addEventListener("hey", test) var ev = new Event("hey", {bubbles:true}) document.getElementById("x").dispatchEvent(ev) @@ -727,17 +729,13 @@ inherits from the {{Event}} interface. {{Event/preventDefault()}} method.
event . preventDefault()
- event . {{Event/defaultPrevented}}
- event . {{Event/isTrusted}}
preventDefault()
method, when invoked, must set the
+canceled flag if the {{Event/cancelable}} attribute value is true and the
+in passive listener flag is unset.
+
+This means there are scenarios where invoking {{preventDefault()}} has no +effect. User agents are encouraged to log the precise cause in a developer console, to aid +debugging. The defaultPrevented @@ -972,14 +974,19 @@ for historical reasons.
[Exposed=(Window,Worker)] interface EventTarget { - void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false); - void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false); + void addEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); + void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); boolean dispatchEvent(Event event); }; callback interface EventListener { void handleEvent(Event event); }; + +dictionary EventListenerOptions { + boolean capture; + boolean passive; +};{{EventTarget}} is an object to which an @@ -991,34 +998,45 @@ occurred. Each {{EventTarget}} has an associated list of
An event listener can be used to observe a specific event. -
An event listener consists of a type, callback, and capture. An -event listener also has an associated removed flag, which is initially unset. +
An event listener consists of a type, callback, capture and +passive. An event listener also has an associated removed flag, which is +initially unset.
The callback is named {{EventListener}} for historical reasons. As can be seen from the definition above, an event listener is a more broad concept.
target . addEventListener(type, callback [, capture = false])
+ target . addEventListener(type, callback [, options])
target . removeEventListener(type, callback [, capture = false])
+ be invoked when the event is dispatched.
+
+ The options argument sets listener-specific options. For compatibility this can be just
+ a boolean, in which case the method behaves exactly as if the value was specified as
+ options' capture
member.
+
+ When set to true, options' capture
member prevents callback from
+ being invoked when the event's {{Event/eventPhase}} attribute value is
+ {{Event/BUBBLING_PHASE}}. When false (or not present), callback will not be invoked when
+ event's {{Event/eventPhase}} attribute value is {{Event/CAPTURING_PHASE}}. Either way,
+ callback will be invoked if event's {{Event/eventPhase}} attribute value is
+ {{Event/AT_TARGET}}.
+
+ When set to true, options' passive
member indicates that the
+ callback will not cancel the event by invoking {{preventDefault()}}. This is used to enable
+ performance optimizations described in [[#observing-event-listeners]].
+
+ The event listener is appended to target's list of event listeners and is
+ not appended if it is a duplicate, i.e., having the same type, callback,
+ capture and passive values.
+
+ target . removeEventListener(type, callback [, options])
target . dispatchEvent(event)
To flatten options run these steps: + +
Let capture and passive be false. + +
If options is a boolean, set capture to options. + +
If options is a dictionary and {{EventListenerOptions/capture}}
is
+ present in options with value true, then set capture to true.
+
+
If options is a dictionary and {{EventListenerOptions/passive}}
is
+ present in options with value true, then set passive to true.
+
+
Return capture and passive. +
The
-addEventListener(type, callback, capture)
+addEventListener(type, callback, options)
method, when invoked, must run these steps:
If callback is null, terminate these steps. +
Let capture and passive be the result of flattening + options. +
Append an event listener to the associated list of event listeners with - type set to type, callback set to callback, and capture - set to capture, unless there already is an event listener in that list with the - same type, callback, and capture. + type set to type, callback set to callback, capture + set to capture, and passive set to passive unless there already is an + event listener in that list with the same type, callback, capture, and + passive.
The
-removeEventListener(type, callback, capture)
-method, when invoked, must, if there is an event listener in the associated list of
-event listeners whose type is type, callback is callback,
-and capture is capture, set that event listener's removed flag and
-remove it from the associated list of event listeners.
+removeEventListener(type, callback, options)
+method, when invoked, must, run these steps
+
+
Let capture and passive be the result of flattening + options. + +
If there is an event listener in the associated list of event listeners whose + type is type, callback is callback, capture is + capture, and passive is passive then set that event listener's + removed flag and remove it from the associated list of event listeners. +
The dispatchEvent(event)
method, when
invoked, must run these steps:
@@ -1059,6 +1104,30 @@ invoked, must run these steps:
+
In general, developers do not expect the presence of an event listener to be observable. +The impact of an event listener is determined by its callback. That is, a developer +adding a no-op event listener would not expect it to have any side effects. + +
Unfortunately, some event APIs have been designed such that implementing them efficiently +requires observing event listeners. This can make the presence of listeners observable in +that even empty listeners can have a dramatic performance impact on the behavior of the application. +For example, touch and wheel events which can be used to block asynchronous scrolling. In some cases +this problem can be mitigated by specifying the event to be {{Event/cancelable}} only when there is +at least one non-{{EventListenerOptions/passive}} listener. For example, +non-{{EventListenerOptions/passive}} {{TouchEvent}} listeners must block scrolling, but if all +listeners are {{EventListenerOptions/passive}} then scrolling can be allowed to start +in parallel by making the {{TouchEvent}} uncancelable (so that calls to +{{Event/preventDefault()}} are ignored). So code dispatching an event is able to observe the absence +of non-{{EventListenerOptions/passive}} listeners, and use that to clear the {{Event/cancelable}} +property of the event being dispatched. + +
Ideally, any new event APIs are defined such that they do not need this property (use +public-scrip-coord@w3.org +for discussion). + +
To dispatch an event to a @@ -1139,9 +1208,14 @@ invoked, must run these steps: listener's capture is true, terminate these substeps (and run them for the next event listener). +
If listener's passive is true, set event's + in passive listener flag. +
Call listener's callback's {{EventListener/handleEvent()}}, with event as argument and event's {{Event/currentTarget}} attribute value as callback this value. If this throws any exception, report the exception. + +
Clear event's in passive listener flag. @@ -9076,6 +9150,7 @@ Peter Sharpe, Philip Jägenstedt, Philippe Le Hégaret, Rafael Weinstein, +Rick Byers, Rick Waldron, Robbert Broersma, Robin Berjon, diff --git a/dom.html b/dom.html index cedad1e75..237e2c032 100644 --- a/dom.html +++ b/dom.html @@ -69,7 +69,7 @@
EventTarget
- preventDefault()
method.
event . preventDefault()
- cancelable
attribute value is true,
- signals to the operation that caused event to be dispatched that it needs to be
- canceled.
+ cancelable
attribute value is true, and while executing a
+ listener for the event with passive
set to false, signals to
+ the operation that caused event to be dispatched that it needs to be canceled.
event . defaultPrevented
- preventDefault()
was invoked
- while the cancelable
attribute
- value is true, and false otherwise.
+ preventDefault()
was invoked successfully to indicate cancellation,
+ and false otherwise.
event . isTrusted
The stopPropagation() method must set the stop propagation flag.
The stopImmediatePropagation() method must set both the stop propagation flag and stop immediate propagation flag.
The bubbles and cancelable attributes must return the values they were initialized to.
-The preventDefault() method must set the canceled flag if the cancelable
attribute value is true.
The preventDefault()
method, when invoked, must set the canceled flag if the cancelable
attribute value is true and the in passive listener flag is unset.
This means there are scenarios where invoking preventDefault()
has no
+effect. User agents are encouraged to log the precise cause in a developer console, to aid
+debugging.
The defaultPrevented attribute must return true if the canceled flag is set and false otherwise.
EventTarget
[Exposed=(Window,Worker)] interface EventTarget { - void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false); - void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false); + void addEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); + void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options); boolean dispatchEvent(Event event); }; callback interface EventListener { void handleEvent(Event event); }; + +dictionary EventListenerOptions { + boolean capture; + boolean passive; +};
EventTarget
is an object to which an event is dispatched when something has
occurred. Each EventTarget
has an associated list of event listeners.
An event listener can be used to observe a specific event.
-An event listener consists of a type, callback, and capture. An event listener also has an associated removed flag, which is initially unset.
+An event listener consists of a type, callback, capture and passive. An event listener also has an associated removed flag, which is +initially unset.
The callback is named EventListener
for historical reasons. As can be
seen from the definition above, an event listener is a more broad concept.
target . addEventListener(type, callback [, capture = false])
+ target . addEventListener(type, callback [, options])
type
attribute value
is type. The callback argument sets the callback that will
- be invoked when the event is dispatched. When set to true,
- the capture argument prevents callback from being invoked when
- the event’s eventPhase
attribute value is BUBBLING_PHASE
.
- When false, callback will not be invoked when event’s eventPhase
attribute value is CAPTURING_PHASE
. Either way, callback will be
- invoked if event’s eventPhase
attribute value is AT_TARGET
.
- The event listener is appended to target’s list of event listeners and is not appended if it is a duplicate, i.e., having the same type, callback, and capture values.
-target . removeEventListener(type, callback [, capture = false])
- The options argument sets listener-specific options. For compatibility this can be just
+ a boolean, in which case the method behaves exactly as if the value was specified as options’ capture
member.
When set to true, options’ capture
member prevents callback from
+ being invoked when the event’s eventPhase
attribute value is BUBBLING_PHASE
. When false (or not present), callback will not be invoked when event’s eventPhase
attribute value is CAPTURING_PHASE
. Either way, callback will be invoked if event’s eventPhase
attribute value is AT_TARGET
.
When set to true, options’ passive
member indicates that the callback will not cancel the event by invoking preventDefault()
. This is used to enable
+ performance optimizations described in §3.7 Observing event listeners.
The event listener is appended to target’s list of event listeners and is + not appended if it is a duplicate, i.e., having the same type, callback, capture and passive values.
+target . removeEventListener(type, callback [, options])
+ target . dispatchEvent(event)
cancelable
attribute value is false or its preventDefault()
method was not invoked, and false otherwise.
The addEventListener(type, callback, capture)
method, when invoked, must run these steps:
To flatten options run these steps:
+Let capture and passive be false.
+If options is a boolean, set capture to options.
+If options is a dictionary and
is
+ present in options with value true, then set capture to true. capture
If options is a dictionary and
is
+ present in options with value true, then set passive to true. passive
Return capture and passive.
+The addEventListener(type, callback, options)
method, when invoked, must run these steps:
If callback is null, terminate these steps.
Append an event listener to the associated list of event listeners with type set to type, callback set to callback, and capture set to capture, unless there already is an event listener in that list with the - same type, callback, and capture.
+Let capture and passive be the result of flattening options.
+Append an event listener to the associated list of event listeners with type set to type, callback set to callback, capture set to capture, and passive set to passive unless there already is an event listener in that list with the same type, callback, capture, and passive.
+The removeEventListener(type, callback, options)
method, when invoked, must, run these steps
Let capture and passive be the result of flattening options.
+If there is an event listener in the associated list of event listeners whose type is type, callback is callback, capture is capture, and passive is passive then set that event listener’s removed flag and remove it from the associated list of event listeners.
The removeEventListener(type, callback, capture)
method, when invoked, must, if there is an event listener in the associated list of event listeners whose type is type, callback is callback,
-and capture is capture, set that event listener’s removed flag and
-remove it from the associated list of event listeners.
The dispatchEvent(event)
method, when
invoked, must run these steps:
Dispatch the event and return the value that returns.
In general, developers do not expect the presence of an event listener to be observable. +The impact of an event listener is determined by its callback. That is, a developer +adding a no-op event listener would not expect it to have any side effects.
+Unfortunately, some event APIs have been designed such that implementing them efficiently
+requires observing event listeners. This can make the presence of listeners observable in
+that even empty listeners can have a dramatic performance impact on the behavior of the application.
+For example, touch and wheel events which can be used to block asynchronous scrolling. In some cases
+this problem can be mitigated by specifying the event to be cancelable
only when there is
+at least one non-passive
listener. For example,
+non-passive
TouchEvent
listeners must block scrolling, but if all
+listeners are passive
then scrolling can be allowed to start in parallel by making the TouchEvent
uncancelable (so that calls to preventDefault()
are ignored). So code dispatching an event is able to observe the absence
+of non-passive
listeners, and use that to clear the cancelable
property of the event being dispatched.
Ideally, any new event APIs are defined such that they do not need this property (use public-scrip-coord@w3.org for discussion).
+To dispatch an event to a target, with an optional target override, run these steps:
If event’s eventPhase
attribute value is BUBBLING_PHASE
and listener’s capture is true, terminate these substeps (and run them for the next event listener).
If listener’s passive is true, set event’s in passive listener flag.
Call listener’s callback’s handleEvent()
, with event as argument and event’s currentTarget
attribute value as callback this value. If this throws any exception, report the exception.
Clear event’s in passive listener flag.
To fire an event named e means that a new event using the Event
interface, with its type
attribute initialized to e, and its isTrusted
attribute initialized to true
, is to be dispatched to the given object.
Fire in the context of DOM is short for creating, initializing,
and dispatching an event. Fire an event makes that process easier to write
down. If the event needs its bubbles
or cancelable
attribute initialized, one could write
"fire an event named submit
with its cancelable
attribute
initialized to true".
An event signifies an occurrence, not an action. Phrased differently, it
represents a notification from an algorithm and can be used to influence the future course
of that algorithm (e.g., through invoking preventDefault()
). Events must not be
@@ -4513,6 +4564,7 @@