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 |