feat(events): support preventdefault

Fixes #1039
Closes #1397
This commit is contained in:
Marc Laval
2015-04-16 18:03:15 +02:00
parent aabe83cf63
commit 883e1c1541
5 changed files with 61 additions and 9 deletions

View File

@ -391,6 +391,7 @@ export class Directive extends Injectable {
*
* - `event1`: the DOM event that the directive listens to.
* - `statement`: the statement to execute when the event occurs.
* If the evalutation of the statement returns `false`, then `preventDefault`is applied on the DOM event.
*
* To listen to global events, a target must be added to the event name.
* The target can be `window`, `document` or `body`.

View File

@ -131,17 +131,17 @@ export class AppView {
}
// implementation of EventDispatcher#dispatchEvent
dispatchEvent(
elementIndex:number, eventName:string, locals:Map<string, any>
):void {
// returns false if preventDefault must be applied to the DOM event
dispatchEvent(elementIndex:number, eventName:string, locals:Map<string, any>): boolean {
// Most of the time the event will be fired only when the view is in the live document.
// However, in a rare circumstance the view might get dehydrated, in between the event
// queuing up and firing.
var allowDefaultBehavior = true;
if (this.hydrated()) {
var elBinder = this.proto.elementBinders[elementIndex];
if (isBlank(elBinder.hostListeners)) return;
if (isBlank(elBinder.hostListeners)) return allowDefaultBehavior;
var eventMap = elBinder.hostListeners[eventName];
if (isBlank(eventMap)) return;
if (isBlank(eventMap)) return allowDefaultBehavior;
MapWrapper.forEach(eventMap, (expr, directiveIndex) => {
var context;
if (directiveIndex === -1) {
@ -149,9 +149,13 @@ export class AppView {
} else {
context = this.elementInjectors[elementIndex].getDirectiveAtIndex(directiveIndex);
}
expr.eval(context, new Locals(this.locals, locals));
var result = expr.eval(context, new Locals(this.locals, locals));
if (isPresent(result)) {
allowDefaultBehavior = allowDefaultBehavior && result;
}
});
}
return allowDefaultBehavior;
}
}

View File

@ -84,7 +84,8 @@ export class RenderView {
this._eventDispatcher = dispatcher;
}
dispatchEvent(elementIndex, eventName, event) {
dispatchEvent(elementIndex, eventName, event): boolean {
var allowDefaultBehavior = true;
if (isPresent(this._eventDispatcher)) {
var evalLocals = MapWrapper.create();
MapWrapper.set(evalLocals, '$event', event);
@ -92,7 +93,11 @@ export class RenderView {
// out of action expressions
// var localValues = this.proto.elementBinders[elementIndex].eventLocals.eval(null, new Locals(null, evalLocals));
// this._eventDispatcher.dispatchEvent(elementIndex, eventName, localValues);
this._eventDispatcher.dispatchEvent(elementIndex, eventName, evalLocals);
allowDefaultBehavior = this._eventDispatcher.dispatchEvent(elementIndex, eventName, evalLocals);
if (!allowDefaultBehavior) {
event.preventDefault();
}
}
return allowDefaultBehavior;
}
}