Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Side by Side Diff: tools/dom/src/EventStreamProvider.dart

Issue 1894713002: Strong html (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: ptal Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/dom/src/CssRectangle.dart ('k') | tools/dom/src/KeyboardEventStream.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of html; 5 part of html;
6 6
7 /** 7 /**
8 * A factory to expose DOM events as Streams. 8 * A factory to expose DOM events as Streams.
9 */ 9 */
10 class EventStreamProvider<T extends Event> { 10 class EventStreamProvider<T extends Event> {
(...skipping 16 matching lines...) Expand all
27 * 27 *
28 * Or for listening to an event which will bubble through the DOM tree: 28 * Or for listening to an event which will bubble through the DOM tree:
29 * 29 *
30 * MediaElement.pauseEvent.forTarget(document.body).listen(...); 30 * MediaElement.pauseEvent.forTarget(document.body).listen(...);
31 * 31 *
32 * See also: 32 * See also:
33 * 33 *
34 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener) 34 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
35 */ 35 */
36 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) => 36 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
37 new _EventStream(e, _eventType, useCapture); 37 new _EventStream<T>(e, _eventType, useCapture);
38 38
39 /** 39 /**
40 * Gets an [ElementEventStream] for this event type, on the specified element. 40 * Gets an [ElementEventStream] for this event type, on the specified element.
41 * 41 *
42 * This will always return a broadcast stream so multiple listeners can be 42 * This will always return a broadcast stream so multiple listeners can be
43 * used simultaneously. 43 * used simultaneously.
44 * 44 *
45 * This may be used to capture DOM events: 45 * This may be used to capture DOM events:
46 * 46 *
47 * Element.keyDownEvent.forElement(element, useCapture: true).listen(...); 47 * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
48 * 48 *
49 * // Alternate method: 49 * // Alternate method:
50 * Element.keyDownEvent.forElement(element).capture(...); 50 * Element.keyDownEvent.forElement(element).capture(...);
51 * 51 *
52 * Or for listening to an event which will bubble through the DOM tree: 52 * Or for listening to an event which will bubble through the DOM tree:
53 * 53 *
54 * MediaElement.pauseEvent.forElement(document.body).listen(...); 54 * MediaElement.pauseEvent.forElement(document.body).listen(...);
55 * 55 *
56 * See also: 56 * See also:
57 * 57 *
58 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener) 58 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
59 */ 59 */
60 ElementStream<T> forElement(Element e, {bool useCapture: false}) { 60 ElementStream<T> forElement(Element e, {bool useCapture: false}) {
61 return new _ElementEventStreamImpl(e, _eventType, useCapture); 61 return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
62 } 62 }
63 63
64 /** 64 /**
65 * Gets an [ElementEventStream] for this event type, on the list of elements. 65 * Gets an [ElementEventStream] for this event type, on the list of elements.
66 * 66 *
67 * This will always return a broadcast stream so multiple listeners can be 67 * This will always return a broadcast stream so multiple listeners can be
68 * used simultaneously. 68 * used simultaneously.
69 * 69 *
70 * This may be used to capture DOM events: 70 * This may be used to capture DOM events:
71 * 71 *
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 * Adapter for exposing DOM events as Dart streams. 122 * Adapter for exposing DOM events as Dart streams.
123 */ 123 */
124 class _EventStream<T extends Event> extends Stream<T> { 124 class _EventStream<T extends Event> extends Stream<T> {
125 final EventTarget _target; 125 final EventTarget _target;
126 final String _eventType; 126 final String _eventType;
127 final bool _useCapture; 127 final bool _useCapture;
128 128
129 _EventStream(this._target, this._eventType, this._useCapture); 129 _EventStream(this._target, this._eventType, this._useCapture);
130 130
131 // DOM events are inherently multi-subscribers. 131 // DOM events are inherently multi-subscribers.
132 Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription), 132 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) ,
133 void onCancel(StreamSubscription subscription)}) 133 void onCancel(StreamSubscription<T> subscription) })
134 => this; 134 => this;
135 bool get isBroadcast => true; 135 bool get isBroadcast => true;
136 136
137 StreamSubscription<T> listen(void onData(T event), 137 StreamSubscription<T> listen(void onData(T event),
138 { Function onError, 138 { Function onError,
139 void onDone(), 139 void onDone(),
140 bool cancelOnError}) { 140 bool cancelOnError}) {
141 141
142 return new _EventStreamSubscription<T>( 142 return new _EventStreamSubscription<T>(
143 this._target, this._eventType, onData, this._useCapture); 143 this._target, this._eventType, onData, this._useCapture);
144 } 144 }
145 } 145 }
146 146
147 bool _matchesWithAncestors(Event event, String selector) {
148 var target = event.target;
149 return target is Element ? target.matchesWithAncestors(selector) : false;
150 }
151
147 /** 152 /**
148 * Adapter for exposing DOM Element events as streams, while also allowing 153 * Adapter for exposing DOM Element events as streams, while also allowing
149 * event delegation. 154 * event delegation.
150 */ 155 */
151 class _ElementEventStreamImpl<T extends Event> extends _EventStream<T> 156 class _ElementEventStreamImpl<T extends Event> extends _EventStream<T>
152 implements ElementStream<T> { 157 implements ElementStream<T> {
153 _ElementEventStreamImpl(target, eventType, useCapture) : 158 _ElementEventStreamImpl(target, eventType, useCapture) :
154 super(target, eventType, useCapture); 159 super(target, eventType, useCapture);
155 160
156 Stream<T> matches(String selector) => this.where( 161 Stream<T> matches(String selector) => this.where(
157 (event) => event.target.matchesWithAncestors(selector)).map((e) { 162 (event) => _matchesWithAncestors(event, selector)).map((e) {
158 e._selector = selector; 163 e._selector = selector;
159 return e; 164 return e;
160 }); 165 });
161 166
162 StreamSubscription<T> capture(void onData(T event)) => 167 StreamSubscription<T> capture(void onData(T event)) =>
163 new _EventStreamSubscription<T>( 168 new _EventStreamSubscription<T>(
164 this._target, this._eventType, onData, true); 169 this._target, this._eventType, onData, true);
165 } 170 }
166 171
167 /** 172 /**
168 * Adapter for exposing events on a collection of DOM Elements as streams, 173 * Adapter for exposing events on a collection of DOM Elements as streams,
169 * while also allowing event delegation. 174 * while also allowing event delegation.
170 */ 175 */
171 class _ElementListEventStreamImpl<T extends Event> extends Stream<T> 176 class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
172 implements ElementStream<T> { 177 implements ElementStream<T> {
173 final Iterable<Element> _targetList; 178 final Iterable<Element> _targetList;
174 final bool _useCapture; 179 final bool _useCapture;
175 final String _eventType; 180 final String _eventType;
176 181
177 _ElementListEventStreamImpl( 182 _ElementListEventStreamImpl(
178 this._targetList, this._eventType, this._useCapture); 183 this._targetList, this._eventType, this._useCapture);
179 184
180 Stream<T> matches(String selector) => this.where( 185 Stream<T> matches(String selector) => this.where(
181 (event) => event.target.matchesWithAncestors(selector)).map((e) { 186 (event) => _matchesWithAncestors(event, selector)).map((e) {
182 e._selector = selector; 187 e._selector = selector;
183 return e; 188 return e;
184 }); 189 });
185 190
186 // Delegate all regular Stream behavior to a wrapped Stream. 191 // Delegate all regular Stream behavior to a wrapped Stream.
187 StreamSubscription<T> listen(void onData(T event), 192 StreamSubscription<T> listen(void onData(T event),
188 { Function onError, 193 { Function onError,
189 void onDone(), 194 void onDone(),
190 bool cancelOnError}) { 195 bool cancelOnError}) {
191 var pool = new _StreamPool.broadcast(); 196 var pool = new _StreamPool<T>.broadcast();
192 for (var target in _targetList) { 197 for (var target in _targetList) {
193 pool.add(new _EventStream(target, _eventType, _useCapture)); 198 pool.add(new _EventStream<T>(target, _eventType, _useCapture));
194 } 199 }
195 return pool.stream.listen(onData, onError: onError, onDone: onDone, 200 return pool.stream.listen(onData, onError: onError, onDone: onDone,
196 cancelOnError: cancelOnError); 201 cancelOnError: cancelOnError);
197 } 202 }
198 203
199 StreamSubscription<T> capture(void onData(T event)) { 204 StreamSubscription<T> capture(void onData(T event)) {
200 var pool = new _StreamPool.broadcast(); 205 var pool = new _StreamPool<T>.broadcast();
201 for (var target in _targetList) { 206 for (var target in _targetList) {
202 pool.add(new _EventStream(target, _eventType, true)); 207 pool.add(new _EventStream<T>(target, _eventType, true));
203 } 208 }
204 return pool.stream.listen(onData); 209 return pool.stream.listen(onData);
205 } 210 }
206 211
207 Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription), 212 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) ,
208 void onCancel(StreamSubscription subscription)}) 213 void onCancel(StreamSubscription<T> subscription) })
209 => this; 214 => this;
210 bool get isBroadcast => true; 215 bool get isBroadcast => true;
211 } 216 }
212 217
218 // We would like this to just be EventListener<T> but that typdef cannot
219 // use generics until dartbug/26276 is fixed.
220 typedef _EventListener<T extends Event>(T event);
221
213 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { 222 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
214 int _pauseCount = 0; 223 int _pauseCount = 0;
215 EventTarget _target; 224 EventTarget _target;
216 final String _eventType; 225 final String _eventType;
217 var _onData; 226 EventListener _onData;
218 final bool _useCapture; 227 final bool _useCapture;
219 228
220 _EventStreamSubscription(this._target, this._eventType, onData, 229 // TODO(jacobr): for full strong mode correctness we should write
221 this._useCapture) : _onData = _wrapZone(onData) { 230 // _onData = onData == null ? null : _wrapZone/*<Event, dynamic>*/((e) => onDa ta(e as T))
231 // but that breaks 114 co19 tests as well as multiple html tests as it is reas onable
232 // to pass the wrong type of event object to an event listener as part of a
233 // test.
234 _EventStreamSubscription(this._target, this._eventType, void onData(T event),
235 this._useCapture) : _onData = _wrapZone/*<Event, dynamic>*/(onData) {
222 _tryResume(); 236 _tryResume();
223 } 237 }
224 238
225 Future cancel() { 239 Future cancel() {
226 if (_canceled) return null; 240 if (_canceled) return null;
227 241
228 _unlisten(); 242 _unlisten();
229 // Clear out the target to indicate this is complete. 243 // Clear out the target to indicate this is complete.
230 _target = null; 244 _target = null;
231 _onData = null; 245 _onData = null;
232 return null; 246 return null;
233 } 247 }
234 248
235 bool get _canceled => _target == null; 249 bool get _canceled => _target == null;
236 250
237 void onData(void handleData(T event)) { 251 void onData(void handleData(T event)) {
238 if (_canceled) { 252 if (_canceled) {
239 throw new StateError("Subscription has been canceled."); 253 throw new StateError("Subscription has been canceled.");
240 } 254 }
241 // Remove current event listener. 255 // Remove current event listener.
242 _unlisten(); 256 _unlisten();
243 257 _onData = _wrapZone/*<Event, dynamic>*/(handleData);
244 _onData = _wrapZone(handleData);
245 _tryResume(); 258 _tryResume();
246 } 259 }
247 260
248 /// Has no effect. 261 /// Has no effect.
249 void onError(Function handleError) {} 262 void onError(Function handleError) {}
250 263
251 /// Has no effect. 264 /// Has no effect.
252 void onDone(void handleDone()) {} 265 void onDone(void handleDone()) {}
253 266
254 void pause([Future resumeSignal]) { 267 void pause([Future resumeSignal]) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 326
314 // Delegate all regular Stream behavior to our wrapped Stream. 327 // Delegate all regular Stream behavior to our wrapped Stream.
315 StreamSubscription<T> listen(void onData(T event), 328 StreamSubscription<T> listen(void onData(T event),
316 { Function onError, 329 { Function onError,
317 void onDone(), 330 void onDone(),
318 bool cancelOnError}) { 331 bool cancelOnError}) {
319 return _streamController.stream.listen(onData, onError: onError, 332 return _streamController.stream.listen(onData, onError: onError,
320 onDone: onDone, cancelOnError: cancelOnError); 333 onDone: onDone, cancelOnError: cancelOnError);
321 } 334 }
322 335
323 Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription), 336 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) ,
324 void onCancel(StreamSubscription subscription)}) 337 void onCancel(StreamSubscription<T> subscription) })
325 => _streamController.stream; 338 => _streamController.stream;
326 339
327 bool get isBroadcast => true; 340 bool get isBroadcast => true;
328 341
329 void add(T event) { 342 void add(T event) {
330 if (event.type == _type) _streamController.add(event); 343 if (event.type == _type) _streamController.add(event);
331 } 344 }
332 } 345 }
333 346
334 class _CustomKeyEventStreamImpl extends _CustomEventStreamImpl<KeyEvent> 347 class _CustomKeyEventStreamImpl extends _CustomEventStreamImpl<KeyEvent>
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 * A factory to expose DOM events as streams, where the DOM event name has to 418 * A factory to expose DOM events as streams, where the DOM event name has to
406 * be determined on the fly (for example, mouse wheel events). 419 * be determined on the fly (for example, mouse wheel events).
407 */ 420 */
408 class _CustomEventStreamProvider<T extends Event> 421 class _CustomEventStreamProvider<T extends Event>
409 implements EventStreamProvider<T> { 422 implements EventStreamProvider<T> {
410 423
411 final _eventTypeGetter; 424 final _eventTypeGetter;
412 const _CustomEventStreamProvider(this._eventTypeGetter); 425 const _CustomEventStreamProvider(this._eventTypeGetter);
413 426
414 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) { 427 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
415 return new _EventStream(e, _eventTypeGetter(e), useCapture); 428 return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
416 } 429 }
417 430
418 ElementStream<T> forElement(Element e, {bool useCapture: false}) { 431 ElementStream<T> forElement(Element e, {bool useCapture: false}) {
419 return new _ElementEventStreamImpl(e, _eventTypeGetter(e), useCapture); 432 return new _ElementEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
420 } 433 }
421 434
422 ElementStream<T> _forElementList(ElementList e, 435 ElementStream<T> _forElementList(ElementList e,
423 {bool useCapture: false}) { 436 {bool useCapture: false}) {
424 return new _ElementListEventStreamImpl(e, _eventTypeGetter(e), useCapture); 437 return new _ElementListEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture );
425 } 438 }
426 439
427 String getEventType(EventTarget target) { 440 String getEventType(EventTarget target) {
428 return _eventTypeGetter(target); 441 return _eventTypeGetter(target);
429 } 442 }
430 443
431 String get _eventType => 444 String get _eventType =>
432 throw new UnsupportedError('Access type through getEventType method.'); 445 throw new UnsupportedError('Access type through getEventType method.');
433 } 446 }
OLDNEW
« no previous file with comments | « tools/dom/src/CssRectangle.dart ('k') | tools/dom/src/KeyboardEventStream.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698