feat(events): add support for global events

Fixes #1098
Closes #1255
This commit is contained in:
Marc Laval
2015-04-02 15:56:58 +02:00
parent 7c95cea3a8
commit b96e560c8d
27 changed files with 414 additions and 103 deletions
+9 -3
View File
@@ -367,6 +367,8 @@ export class Directive extends Injectable {
* - `event1`: the DOM event that the directive listens to.
* - `statement`: the statement to execute when the event occurs.
*
* To listen to global events, a target must be added to the event name.
* The target can be `window`, `document` or `body`.
*
* When writing a directive event binding, you can also refer to the following local variables:
* - `$event`: Current event object which triggered the event.
@@ -380,6 +382,7 @@ export class Directive extends Injectable {
* @Directive({
* hostListeners: {
* 'event1': 'onMethod1(arguments)',
* 'target:event2': 'onMethod2(arguments)',
* ...
* }
* }
@@ -387,19 +390,22 @@ export class Directive extends Injectable {
*
* ## Basic Event Binding:
*
* Suppose you want to write a directive that triggers on `change` hostListeners in the DOM. You would define the event
* binding as follows:
* Suppose you want to write a directive that triggers on `change` events in the DOM and on `resize` events in window.
* You would define the event binding as follows:
*
* ```
* @Decorator({
* selector: 'input',
* hostListeners: {
* 'change': 'onChange($event)'
* 'change': 'onChange($event)',
* 'window:resize': 'onResize($event)'
* }
* })
* class InputDecorator {
* onChange(event:Event) {
* }
* onResize(event:Event) {
* }
* }
* ```
*
+2 -6
View File
@@ -118,9 +118,7 @@ export class ProtoViewFactory {
protoView.bindElementProperty(astWithSource.ast, propertyName);
});
// events
MapWrapper.forEach(renderElementBinder.eventBindings, (astWithSource, eventName) => {
protoView.bindEvent(eventName, astWithSource.ast, -1);
});
protoView.bindEvent(renderElementBinder.eventBindings, -1);
// variables
// The view's locals needs to have a full set of variable names at construction time
// in order to prevent new variables from being set later in the lifecycle. Since we don't want
@@ -143,9 +141,7 @@ export class ProtoViewFactory {
protoView.bindDirectiveProperty(i, astWithSource.ast, propertyName, setter);
});
// directive events
MapWrapper.forEach(renderDirectiveMetadata.eventBindings, (astWithSource, eventName) => {
protoView.bindEvent(eventName, astWithSource.ast, i);
});
protoView.bindEvent(renderDirectiveMetadata.eventBindings, i);
}
}
+11 -7
View File
@@ -272,7 +272,7 @@ export class AppView {
var elBinder = this.proto.elementBinders[elementIndex];
if (isBlank(elBinder.hostListeners)) return;
var eventMap = elBinder.hostListeners[eventName];
if (isBlank(eventName)) return;
if (isBlank(eventMap)) return;
MapWrapper.forEach(eventMap, (expr, directiveIndex) => {
var context;
if (directiveIndex === -1) {
@@ -407,19 +407,23 @@ export class AppProtoView {
* @param {int} directiveIndex The directive index in the binder or -1 when the event is not bound
* to a directive
*/
bindEvent(eventName:string, expression:AST, directiveIndex: int = -1) {
bindEvent(eventBindings: List<renderApi.EventBinding>, directiveIndex: int = -1) {
var elBinder = this.elementBinders[this.elementBinders.length - 1];
var events = elBinder.hostListeners;
if (isBlank(events)) {
events = StringMapWrapper.create();
elBinder.hostListeners = events;
}
var event = StringMapWrapper.get(events, eventName);
if (isBlank(event)) {
event = MapWrapper.create();
StringMapWrapper.set(events, eventName, event);
for (var i = 0; i < eventBindings.length; i++) {
var eventBinding = eventBindings[i];
var eventName = eventBinding.fullName;
var event = StringMapWrapper.get(events, eventName);
if (isBlank(event)) {
event = MapWrapper.create();
StringMapWrapper.set(events, eventName, event);
}
MapWrapper.set(event, directiveIndex, eventBinding.source);
}
MapWrapper.set(event, directiveIndex, expression);
}
/**