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

Unified Diff: sky/specs/events.md

Issue 900713002: Specs: dartify events spec (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/specs/events.md
diff --git a/sky/specs/events.md b/sky/specs/events.md
index 61a8f31ebb8d76e107593c0f6c8621a467bef957..43abffcea0362358a2985370ff1afe0222c5b2d8 100644
--- a/sky/specs/events.md
+++ b/sky/specs/events.md
@@ -1,68 +1,73 @@
Sky Event Model
===============
-```javascript
- // EVENTS
+```dart
+SKY MODULE
+<!-- part of sky:core -->
- class Event {
- constructor (String type, Boolean bubbles = true, any data = null); // O(1)
- readonly attribute String type; // O(1)
- readonly attribute Boolean bubbles; // O(1)
- attribute any data; // O(1)
+<script>
+abstract class Event {
+ Event({bool bubbles}) : this._bubbles = bubbles;
- readonly attribute EventTarget target; // O(1)
- readonly attribute EventTarget currentTarget; // O(1)
- attribute Boolean handled; // O(1)
- attribute any result; // O(1)
+ bool _bubbles;
+ bool get bubbles => _bubbles;
- // TODO(ianh): do events get blocked at scope boundaries, e.g. focus events when both sides are in the scope?
- // TODO(ianh): do events get retargetted, e.g. focus when leaving a custom element?
- }
+ EventTarget _target;
+ EventTarget get target => _target;
+
+ EventTarget _currentTarget;
+ EventTarget get currentTarget => _currentTarget;
+
+ bool handled; // precise semantics depend on the event type, but in general, set this when you set result
+ dynamic result;
- // TODO(ianh): decide if we're using this generic Event class and
- // allowing any arbitrary properties to be set on it, or if we're
- // going to use subclasses (and drop "type"). If we use subclasses
- // then how will declarative event handling work in frameworks?
- // (consider that multiple modules can each have their own FooEvent
- // class with the same name...)
- //
- // The advantage of this would be the ability to enforce (or at
- // least better catch) incorrect uses of the API, e.g. to make sure
- // people don't stomp on themselves with the return value.
+ // TODO(ianh): abstract API for doing things at shadow tree boundaries
+ // TODO(ianh): do events get blocked at scope boundaries, e.g. focus events when both sides are in the scope?
+ // TODO(ianh): do events get retargetted, e.g. focus when leaving a custom element?
+}
- callback EventListener any (Event event);
- // if the return value is not undefined:
- // assign it to event.result
- // set event.handled to true
+class EventTarget {
+ EventTarget() : _eventsController = new DispatcherController<Event>();
- abstract class EventTarget {
- any dispatchEvent(Event event, any defaultResult = null); // O(N) in total number of listeners for this type in the chain
- // sets event.handled to false and event.result to defaultResult
- // makes a record of the event target chain by calling getEventDispatchChain()
- // sets event.target to this
- // invokes all the handlers on the chain in turn, at each step setting currentTarget to the EventTarget for that step
- // returns event.result
- virtual Array<EventTarget> getEventDispatchChain(); // O(1) // returns []
- void addEventListener(String type, EventListener listener); // O(1)
- void removeEventListener(String type, EventListener listener); // O(N) in event listeners with that type
- private Array<String> getRegisteredEventListenerTypes(); // O(N)
- private Array<EventListener> getRegisteredEventListenersForType(String type); // O(N)
+ Dispatcher get events => _eventsController.dispatcher;
+ EventTarget parentNode;
+
+ List<EventTarget> getEventDispatchChain() {
+ if (this.parentNode == null) {
+ return [this];
+ } else {
+ var result = this.parentNode.getEventDispatchChain();
+ result.add(this);
+ return result;
+ }
}
- class CustomEventTarget : EventTarget { // implemented in JS
- constructor (); // O(1)
- attribute EventTarget parentNode; // getter O(1), setter O(N) in height of tree, throws if this would make a loop
+ final DispatcherController _eventsController;
- virtual Array<EventTarget> getEventDispatchChain(); // O(N) in height of tree // implements EventTarget.getEventDispatchChain()
- // let result = [];
- // let node = this;
- // while (node) {
- // result.push(node);
- // node = node.parentNode;
- // }
- // return result;
+ dynamic dispatchEvent(Event event, { defaultResult: null }) { // O(N*M) where N is the length of the chain and M is the average number of listeners per link in the chain
+ // note: this will throw if any of the listeners threw
+ assert(event != null); // event must be non-null
+ event.handled = false;
+ event.result = defaultResult;
+ event._target = this;
+ var chain = this.getEventDispatchChain();
+ var exceptions = new ExceptionListException<ExceptionListException<Exception>>();
+ for (var link in chain) {
+ try {
+ link._dispatchEventLocally(event);
+ } on ExceptionListException<Exception> catch (e) {
+ exceptions.add(e);
+ }
+ }
+ if (exceptions.length > 0)
+ throw exceptions;
+ return event.result;
+ }
- // you can inherit from this to make your object into an event target
- // or you can inherit from EventTarget and implement your own getEventDispatchChain()
+ void _dispatchEventLocally(Event event) {
+ event._currentTarget = this;
+ _eventsController.add(event);
}
+}
+</script>
```
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698