Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of html; | |
| 6 | |
| 7 /** | |
| 8 * Adapter for exposing DOM events as Dart streams. | |
| 9 */ | |
| 10 class _EventStream<T extends Event> extends Stream<T> { | |
| 11 final EventTarget _target; | |
| 12 final String _eventType; | |
| 13 final bool _useCapture; | |
| 14 | |
| 15 _EventStream(this._target, this._eventType, this._useCapture); | |
| 16 | |
| 17 StreamSubscription<T> listen(void onData(T event), | |
| 18 { void onError(AsyncError error), | |
| 19 void onDone(), | |
| 20 bool unsubscribeOnError}) { | |
| 21 | |
| 22 if (onError != null) { | |
| 23 throw new ArgumentError('onError is not supported by DOM events'); | |
|
floitsch
2013/01/12 00:49:33
I would just discard it. It is supported, but the
blois
2013/01/12 01:42:52
Done.
Old compatibility habits- always throw exce
| |
| 24 } | |
| 25 if (onDone != null) { | |
|
floitsch
2013/01/12 00:49:33
ditto.
blois
2013/01/12 01:42:52
Done.
| |
| 26 throw new ArgumentError('onError is not supported by DOM events'); | |
| 27 } | |
| 28 if (unsubscribeOnError != null) { | |
|
floitsch
2013/01/12 00:49:33
ditto.
blois
2013/01/12 01:42:52
Done.
| |
| 29 throw new ArgumentError( | |
| 30 'unsubscribeOnError is not supported by DOM events'); | |
| 31 } | |
| 32 | |
| 33 return new _EventStreamSubscription<T>( | |
| 34 this._target, this._eventType, onData, this._useCapture); | |
| 35 } | |
| 36 } | |
| 37 | |
| 38 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { | |
|
floitsch
2013/01/12 00:49:33
This is pretty much what I was looking for.
I don
Jennifer Messerly
2013/01/12 01:11:25
+1, this is so nice
| |
| 39 int _pauseCount = 0; | |
| 40 EventTarget _target; | |
| 41 final String _eventType; | |
| 42 var _onData; | |
| 43 final bool _useCapture; | |
| 44 | |
| 45 _EventStreamSubscription(this._target, this._eventType, this._onData, | |
| 46 this._useCapture) { | |
| 47 _tryResume(); | |
| 48 } | |
| 49 | |
| 50 void cancel() { | |
| 51 if (_canceled) { | |
| 52 throw new StateError("Subscription has been canceled."); | |
| 53 } | |
| 54 | |
| 55 _unlisten(); | |
| 56 // Clear out the target to indicate this is complete. | |
|
Jennifer Messerly
2013/01/12 01:11:25
also has the nice side effect of releasing memory
blois
2013/01/12 01:42:52
Done.
| |
| 57 _target = null; | |
| 58 } | |
| 59 | |
| 60 bool get _canceled => _target == null; | |
| 61 | |
| 62 void onData(void handleData(T event)) { | |
| 63 if (_canceled) { | |
| 64 throw new StateError("Subscription has been canceled."); | |
| 65 } | |
| 66 // Remove current event listener. | |
| 67 _unlisten(); | |
| 68 | |
| 69 _onData = handleData; | |
|
Jennifer Messerly
2013/01/12 01:11:25
is this allowed to be null? I see some checks for
blois
2013/01/12 01:42:52
onData can be null from the listen call and I beli
| |
| 70 _tryResume(); | |
| 71 } | |
| 72 | |
| 73 void onError(void handleError(AsyncError error)) { | |
| 74 throw new UnsupportedError('Not supported by DOM events'); | |
|
floitsch
2013/01/12 00:49:33
ditto: just ignore it.
blois
2013/01/12 01:42:52
Done.
| |
| 75 } | |
| 76 | |
| 77 void onDone(void handleDone()) { | |
| 78 throw new UnsupportedError('Not supported by DOM events'); | |
| 79 } | |
| 80 | |
| 81 void pause([Future resumeSignal]) { | |
| 82 if (_canceled) { | |
| 83 throw new StateError("Subscription has been canceled."); | |
| 84 } | |
| 85 ++_pauseCount; | |
| 86 _unlisten(); | |
| 87 | |
| 88 if (resumeSignal != null) { | |
| 89 resumeSignal.whenComplete(resume); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 void resume() { | |
|
Jennifer Messerly
2013/01/12 01:11:25
this should probably check if paused. The _StreamS
blois
2013/01/12 01:42:52
Done.
| |
| 94 if (_canceled) { | |
| 95 throw new StateError("Subscription has been canceled."); | |
| 96 } | |
| 97 if (_pauseCount == 0) { | |
| 98 throw new StateError("Subscription is not paused."); | |
| 99 } | |
| 100 --_pauseCount; | |
| 101 _tryResume(); | |
| 102 } | |
| 103 | |
| 104 void _tryResume() { | |
| 105 if (_onData != null && _pauseCount == 0) { | |
| 106 _target.$dom_addEventListener(_eventType, _onData, _useCapture); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 void _unlisten() { | |
| 111 if (_onData != null) { | |
| 112 _target.$dom_removeEventListener(_eventType, _onData, _useCapture); | |
|
Jennifer Messerly
2013/01/12 01:11:25
should this set _onData to null after unregisterin
blois
2013/01/12 01:42:52
We unlisten when it's paused, but can resume later
| |
| 113 } | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 | |
| 118 /** | |
| 119 * A factory to expose DOM events as Streams. | |
| 120 */ | |
| 121 class EventStreamProvider<T extends Event> { | |
| 122 final String _eventType; | |
| 123 | |
| 124 const EventStreamProvider(this._eventType); | |
| 125 | |
| 126 /** | |
| 127 * Gets a [Stream] for this event type, on the specified target. | |
| 128 * | |
| 129 * This may be used to capture DOM events: | |
| 130 * | |
| 131 * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...); | |
| 132 * | |
| 133 * Or for listening to an event which will bubble through the DOM tree: | |
| 134 * | |
| 135 * MediaElement.pauseEvent.forTarget(document.body).listen(...); | |
| 136 * | |
| 137 * See also: | |
| 138 * | |
| 139 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener) | |
| 140 */ | |
| 141 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) { | |
| 142 return new _EventStream(e, _eventType, useCapture); | |
| 143 } | |
| 144 } | |
| OLD | NEW |