@@ -104,6 +104,8 @@ urlPrefix: https://html.spec.whatwg.org/multipage/
104
104
text: effective script origin
105
105
text: origin alias; url: #concept-origin-alias
106
106
text: Unicode serialization of an origin; url: #unicode-serialisation-of-an-origin
107
+ urlPrefix: infrastructure.html
108
+ text: in parallel
107
109
urlPrefix: https://w3c.github.io/webcomponents/spec/shadow/
108
110
type: dfn; urlPrefix: #dfn-
109
111
text: shadow root
@@ -613,7 +615,7 @@ Lets look at an example of how <a>events</a> work in a <a>tree</a>:
613
615
function test(e) {
614
616
debug(e.target, e.currentTarget, e.eventPhase)
615
617
}
616
- document.addEventListener("hey", test, true)
618
+ document.addEventListener("hey", test, {capture: true} )
617
619
document.body.addEventListener("hey", test)
618
620
var ev = new Event("hey", {bubbles:true})
619
621
document.getElementById("x").dispatchEvent(ev)
@@ -727,17 +729,13 @@ inherits from the {{Event}} interface.
727
729
{{Event/preventDefault()}} method.
728
730
729
731
<dt><code><var> event</var> . <a method for=Event lt="preventDefault()">preventDefault</a> ()</code>
730
- <dd> If invoked when the
731
- {{Event/cancelable}} attribute value is true,
732
- signals to the operation that caused <var> event</var> to be
733
- <a>dispatched</a> that it needs to be
734
- canceled.
732
+ <dd> If invoked when the {{Event/cancelable}} attribute value is true, and while executing a
733
+ listener for the <var> event</var> with {{EventListenerOptions/passive}} set to false, signals to
734
+ the operation that caused <var> event</var> to be <a>dispatched</a> that it needs to be canceled.
735
735
736
736
<dt><code><var> event</var> . {{Event/defaultPrevented}} </code>
737
- <dd> Returns true if
738
- {{Event/preventDefault()}} was invoked
739
- while the {{Event/cancelable}} attribute
740
- value is true, and false otherwise.
737
+ <dd> Returns true if {{Event/preventDefault()}} was invoked successfully to indicate cancellation,
738
+ and false otherwise.
741
739
742
740
<dt><code><var> event</var> . {{Event/isTrusted}} </code>
743
741
<dd> Returns true if <var> event</var> was
@@ -799,6 +797,7 @@ flags that are all initially unset:
799
797
<li> <dfn export for=Event>canceled flag</dfn>
800
798
<li> <dfn export for=Event>initialized flag</dfn>
801
799
<li> <dfn export for=Event>dispatch flag</dfn>
800
+ <li> <dfn export for=Event>in passive listener flag</dfn>
802
801
</ul>
803
802
804
803
The
@@ -816,8 +815,13 @@ must return the values they were initialized to.
816
815
817
816
The
818
817
<dfn method for=Event>preventDefault()</dfn>
819
- method must set the <a>canceled flag</a> if the
820
- {{Event/cancelable}} attribute value is true.
818
+ method must set the <a>canceled flag</a> if the {{Event/cancelable}} attribute value is true and
819
+ the <a>in passive listener flag</a> is unset.
820
+
821
+ <p class="note no-backref">
822
+ This means there are scenarios where invoking {{preventDefault()}} has no effect. User agents are
823
+ encouraged to log the precise cause in a developer console, to aid debugging.
824
+ </p>
821
825
822
826
The
823
827
<dfn attribute for=Event>defaultPrevented</dfn>
@@ -972,14 +976,19 @@ for historical reasons.
972
976
<pre class=idl>
973
977
[Exposed=(Window,Worker)]
974
978
interface EventTarget {
975
- void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false );
976
- void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false );
979
+ void addEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options );
980
+ void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options );
977
981
boolean dispatchEvent(Event event);
978
982
};
979
983
980
984
callback interface EventListener {
981
985
void handleEvent(Event event);
982
986
};
987
+
988
+ dictionary EventListenerOptions {
989
+ boolean capture;
990
+ boolean passive;
991
+ };
983
992
</pre>
984
993
985
994
{{EventTarget}} is an object to which an
@@ -991,60 +1000,98 @@ occurred. Each {{EventTarget}} has an associated list of
991
1000
<p> An <dfn export id=concept-event-listener>event listener</dfn> can be used to observe a specific
992
1001
<a>event</a> .
993
1002
994
- <p> An <a>event listener</a> consists of a <b> type</b> , <b> callback</b> , and <b> capture</b> . An
995
- <a>event listener</a> also has an associated <b> removed flag</b> , which is initially unset.
1003
+ <p> An <a>event listener</a> consists of a <b> type</b> , <b> callback</b> , <b> capture</b> and
1004
+ <b> passive</b> . An <a>event listener</a> also has an associated <b> removed flag</b> , which is
1005
+ initially unset.
996
1006
997
1007
<p class="note no-backref"> The callback is named {{EventListener}} for historical reasons. As can be
998
1008
seen from the definition above, an <a>event listener</a> is a more broad concept.
999
1009
1000
1010
<dl class=domintro>
1001
- <dt><code><var> target</var> . <a method lt="addEventListener()">addEventListener</a> (<var> type</var> , <var> callback</var> [, <var>capture </var> = false ] )</code>
1011
+ <dt><code><var> target</var> . <a method lt="addEventListener()">addEventListener</a> (<var> type</var> , <var> callback</var> [, <var>options </var>] )</code>
1002
1012
<dd>
1003
1013
Appends an <a>event listener</a> for <a>events</a> whose {{Event/type}} attribute value
1004
1014
is <var> type</var> . The <var> callback</var> argument sets the <b> callback</b> that will
1005
- be invoked when the <a>event</a> is <a>dispatched</a> . When set to true,
1006
- the <var> capture</var> argument prevents <b> callback</b> from being invoked when
1007
- the <a>event</a> 's {{Event/eventPhase}} attribute value is {{Event/BUBBLING_PHASE}} .
1008
- When false, <b> callback</b> will not be invoked when <a>event</a> 's {{Event/eventPhase}}
1009
- attribute value is {{Event/CAPTURING_PHASE}} . Either way, <b> callback</b> will be
1010
- invoked if <a>event</a> 's {{Event/eventPhase}} attribute value is {{Event/AT_TARGET}} .
1011
-
1012
- The <a>event listener</a> is appended to <var> target</var> 's list of
1013
- <a>event listeners</a> and is not appended if it is a duplicate, i.e., having the same
1014
- <b> type</b> , <b> callback</b> , and <b> capture</b> values.
1015
-
1016
- <dt><code><var> target</var> . <a method lt="removeEventListener()">removeEventListener</a> (<var> type</var> , <var> callback</var> [, <var>capture</var> = false] )</code>
1015
+ be invoked when the <a>event</a> is <a>dispatched</a> .
1016
+
1017
+ The <var> options</var> argument sets listener-specific options. For compatibility this can be just
1018
+ a boolean, in which case the method behaves exactly as if the value was specified as
1019
+ <var> options</var> ' <code> capture</code> member.
1020
+
1021
+ When set to true, <var> options</var> ' <code> capture</code> member prevents <b> callback</b> from
1022
+ being invoked when the <a>event</a> 's {{Event/eventPhase}} attribute value is
1023
+ {{Event/BUBBLING_PHASE}} . When false (or not present), <b> callback</b> will not be invoked when
1024
+ <a>event</a> 's {{Event/eventPhase}} attribute value is {{Event/CAPTURING_PHASE}} . Either way,
1025
+ <b> callback</b> will be invoked if <a>event</a> 's {{Event/eventPhase}} attribute value is
1026
+ {{Event/AT_TARGET}} .
1027
+
1028
+ When set to true, <var> options</var> ' <code> passive</code> member indicates that the
1029
+ <b> callback</b> will not cancel the event by invoking {{preventDefault()}} . This is used to enable
1030
+ performance optimizations described in [[#observing-event-listeners]] .
1031
+
1032
+ The <a>event listener</a> is appended to <var> target</var> 's list of <a>event listeners</a> and is
1033
+ not appended if it is a duplicate, i.e., having the same <b> type</b> , <b> callback</b> ,
1034
+ <b> capture</b> and <b> passive</b> values.
1035
+
1036
+ <dt><code><var> target</var> . <a method lt="removeEventListener()">removeEventListener</a> (<var> type</var> , <var> callback</var> [, <var>options</var>] )</code>
1017
1037
<dd> Remove the <a>event listener</a>
1018
1038
in <var> target</var> 's list of
1019
1039
<a>event listeners</a> with the same
1020
1040
<var> type</var> , <var> callback</var> , and
1021
- <var> capture </var> .
1041
+ <var> options </var> .
1022
1042
1023
1043
<dt><code><var> target</var> . <a method lt="dispatchEvent()">dispatchEvent</a> (<var> event</var> )</code>
1024
1044
<dd> <a>Dispatches</a> a synthetic event <var> event</var> to <var> target</var> and returns
1025
1045
true if either <var> event</var> 's {{Event/cancelable}} attribute value is false or its
1026
1046
{{Event/preventDefault()}} method was not invoked, and false otherwise.
1027
1047
</dl>
1028
1048
1049
+ <p> To <dfn export for=Event id=concept-flatten-options>flatten</dfn> <var> options</var> run these steps:
1050
+
1051
+ <ol>
1052
+ <li> Let <var> capture</var> and <var> passive</var> be false.
1053
+
1054
+ <li> If <var> options</var> is a boolean, set <var> capture</var> to
1055
+ <var> options</var> .
1056
+
1057
+ <li> If <var> options</var> is a dictionary and <code> {{EventListenerOptions/capture}} </code> is
1058
+ present in <var> options</var> with value true, then set <var> capture</var> to true.
1059
+
1060
+ <li> If <var> options</var> is a dictionary and <code> {{EventListenerOptions/passive}} </code> is
1061
+ present in <var> options</var> with value true, then set <var> passive</var> to true.
1062
+
1063
+ <li> Return <var> capture</var> and <var> passive</var> .
1064
+ </ol>
1065
+
1029
1066
<p> The
1030
- <dfn method for=EventTarget><code>addEventListener(<var>type</var>, <var>callback</var>, <var>capture </var>)</code></dfn>
1067
+ <dfn method for=EventTarget><code>addEventListener(<var>type</var>, <var>callback</var>, <var>options </var>)</code></dfn>
1031
1068
method, when invoked, must run these steps:
1032
1069
1033
1070
<ol>
1034
1071
<li><p> If <var> callback</var> is null, terminate these steps.
1035
1072
1073
+ <li> Let <var> capture</var> and <var> passive</var> be the result of <a>flattening</a>
1074
+ <var> options</var> .
1075
+
1036
1076
<li><p> Append an <a>event listener</a> to the associated list of <a>event listeners</a> with
1037
- <b> type</b> set to <var> type</var> , <b> callback</b> set to <var> callback</var> , and <b> capture</b>
1038
- set to <var> capture</var> , unless there already is an <a>event listener</a> in that list with the
1039
- same <b> type</b> , <b> callback</b> , and <b> capture</b> .
1077
+ <b> type</b> set to <var> type</var> , <b> callback</b> set to <var> callback</var> , <b> capture</b>
1078
+ set to <var> capture</var> , and <b> passive</b> set to <var> passive</var> unless there already is an
1079
+ <a>event listener</a> in that list with the same <b> type</b> , <b> callback</b> , <b> capture</b> , and
1080
+ <b> passive</b> .
1040
1081
</ol>
1041
1082
1042
1083
<p> The
1043
- <dfn method for=EventTarget><code>removeEventListener(<var>type</var>, <var>callback</var>, <var>capture</var>)</code></dfn>
1044
- method, when invoked, must, if there is an <a>event listener</a> in the associated list of
1045
- <a>event listeners</a> whose <b> type</b> is <var> type</var> , <b> callback</b> is <var> callback</var> ,
1046
- and <b> capture</b> is <var> capture</var> , set that <a>event listener</a> 's <b> removed flag</b> and
1047
- remove it from the associated list of <a>event listeners</a> .
1084
+ <dfn method for=EventTarget><code>removeEventListener(<var>type</var>, <var>callback</var>, <var>options</var>)</code></dfn>
1085
+ method, when invoked, must, run these steps
1086
+
1087
+ <ol>
1088
+ <li> Let <var> capture</var> and <var> passive</var> be the result of <a>flattening</a> <var> options</var> .
1089
+
1090
+ <li> If there is an <a>event listener</a> in the associated list of <a>event listeners</a> whose
1091
+ <b> type</b> is <var> type</var> , <b> callback</b> is <var> callback</var> , <b> capture</b> is
1092
+ <var> capture</var> , and <b> passive</b> is <var> passive</var> then set that <a>event listener</a> 's
1093
+ <b> removed flag</b> and remove it from the associated list of <a>event listeners</a> .
1094
+ </ol>
1048
1095
1049
1096
<p> The <dfn method for=EventTarget><code>dispatchEvent(<var>event</var>)</code></dfn> method, when
1050
1097
invoked, must run these steps:
@@ -1059,6 +1106,30 @@ invoked, must run these steps:
1059
1106
</ol>
1060
1107
1061
1108
1109
+ <h3 id=observing-event-listeners>Observing event listeners</h3>
1110
+
1111
+ <p> In general, developers do not expect the presence of an <a>event listener</a> to be observable.
1112
+ The impact of an <a>event listener</a> is determined by its <b> callback</b> . That is, a developer
1113
+ adding a no-op <a>event listener</a> would not expect it to have any side effects.
1114
+
1115
+ <p> Unfortunately, some event APIs have been designed such that implementing them efficiently
1116
+ requires observing <a>event listeners</a> . This can make the presence of listeners observable in
1117
+ that even empty listeners can have a dramatic performance impact on the behavior of the
1118
+ application. For example, touch and wheel events which can be used to block asynchronous scrolling.
1119
+ In some cases this problem can be mitigated by specifying the event to be {{Event/cancelable}} only
1120
+ when there is at least one non-{{EventListenerOptions/passive}} listener. For example,
1121
+ non-{{EventListenerOptions/passive}} {{TouchEvent}} listeners must block scrolling, but if all
1122
+ listeners are {{EventListenerOptions/passive}} then scrolling can be allowed to start
1123
+ <a>in parallel</a> by making the {{TouchEvent}} uncancelable (so that calls to
1124
+ {{Event/preventDefault()}} are ignored). So code dispatching an event is able to observe the
1125
+ absence of non-{{EventListenerOptions/passive}} listeners, and use that to clear the
1126
+ {{Event/cancelable}} property of the event being dispatched.
1127
+
1128
+ <p> Ideally, any new event APIs are defined such that they do not need this property (use
1129
+ <a href="https://lists.w3.org/Archives/Public/public-script-coord/">[email protected] </a>
1130
+ for discussion).
1131
+
1132
+
1062
1133
<h3 id=dispatching-events>Dispatching events</h3>
1063
1134
1064
1135
<p> To <dfn export for=Event id=concept-event-dispatch>dispatch</dfn> an <var> event</var> to a
@@ -1139,9 +1210,15 @@ invoked, must run these steps:
1139
1210
<var> listener</var> 's <b> capture</b> is true, terminate these substeps (and run them for the next
1140
1211
<a>event listener</a> ).
1141
1212
1213
+ <li> If <var> listener</var> 's <b>passive</b> is true, set <var>event</var>' s <a>in passive
1214
+ listener flag</a> .
1215
+
1142
1216
<li><p> Call <var> listener</var> 's <b>callback</b>' s {{EventListener/handleEvent()}} , with
1143
1217
<var> event</var> as argument and <var> event</var> 's {{Event/currentTarget}} attribute value as
1144
1218
<a>callback this value</a> . If this throws any exception, <a>report the exception</a> .
1219
+
1220
+ <li> Clear <var> event</var> 's <a>in passive listener flag</a> .
1221
+
1145
1222
</ol>
1146
1223
</ol>
1147
1224
@@ -9073,6 +9150,7 @@ Peter Sharpe,
9073
9150
Philip Jägenstedt,
9074
9151
Philippe Le Hégaret,
9075
9152
Rafael Weinstein,
9153
+ Rick Byers,
9076
9154
Rick Waldron,
9077
9155
Robbert Broersma,
9078
9156
Robin Berjon,
0 commit comments