feat(EventManager): implement the EventManager

This commit is contained in:
Victor Berchet
2015-02-09 15:11:31 +01:00
parent 91fd5a69bf
commit 8844671c8d
26 changed files with 495 additions and 69 deletions

View File

@ -497,8 +497,7 @@ export class ElementInjector extends TreeNode {
if (isPresent(this._eventCallbacks)) {
var callback = MapWrapper.get(this._eventCallbacks, dep.eventEmitterName);
if (isPresent(callback)) {
var locals = MapWrapper.create();
return ProtoView.buildInnerCallback(callback, view, locals);
return ProtoView.buildInnerCallback(callback, view);
}
}
return (_) => {};

View File

@ -16,6 +16,7 @@ import {Content} from './shadow_dom_emulation/content_tag';
import {LightDom, DestinationLightDom} from './shadow_dom_emulation/light_dom';
import {ShadowDomStrategy} from './shadow_dom_strategy';
import {ViewPool} from './view_pool';
import {EventManager} from 'angular2/src/core/events/event_manager';
const NG_BINDING_CLASS = 'ng-binding';
const NG_BINDING_CLASS_SELECTOR = '.ng-binding';
@ -294,19 +295,19 @@ export class ProtoView {
}
// TODO(rado): hostElementInjector should be moved to hydrate phase.
instantiate(hostElementInjector: ElementInjector):View {
if (this._viewPool.length() == 0) this._preFillPool(hostElementInjector);
instantiate(hostElementInjector: ElementInjector, eventManager: EventManager):View {
if (this._viewPool.length() == 0) this._preFillPool(hostElementInjector, eventManager);
var view = this._viewPool.pop();
return isPresent(view) ? view : this._instantiate(hostElementInjector);
return isPresent(view) ? view : this._instantiate(hostElementInjector, eventManager);
}
_preFillPool(hostElementInjector: ElementInjector) {
_preFillPool(hostElementInjector: ElementInjector, eventManager: EventManager) {
for (var i = 0; i < VIEW_POOL_PREFILL; i++) {
this._viewPool.push(this._instantiate(hostElementInjector));
this._viewPool.push(this._instantiate(hostElementInjector, eventManager));
}
}
_instantiate(hostElementInjector: ElementInjector): View {
_instantiate(hostElementInjector: ElementInjector, eventManager: EventManager): View {
var rootElementClone = this.instantiateInPlace ? this.element : DOM.clone(this.element);
var elementsWithBindingsDynamic;
if (this.isTemplateElement) {
@ -387,7 +388,7 @@ export class ProtoView {
var bindingPropagationConfig = null;
if (isPresent(binder.componentDirective)) {
var strategy = this.shadowDomStrategy;
var childView = binder.nestedProtoView.instantiate(elementInjector);
var childView = binder.nestedProtoView.instantiate(elementInjector, eventManager);
view.changeDetector.addChild(childView.changeDetector);
lightDom = strategy.constructLightDom(view, childView, element);
@ -402,7 +403,8 @@ export class ProtoView {
var viewPort = null;
if (isPresent(binder.templateDirective)) {
var destLightDom = this._directParentElementLightDom(protoElementInjector, preBuiltObjects);
viewPort = new ViewPort(view, element, binder.nestedProtoView, elementInjector, destLightDom);
viewPort = new ViewPort(view, element, binder.nestedProtoView, elementInjector,
eventManager, destLightDom);
ListWrapper.push(viewPorts, viewPort);
}
@ -416,7 +418,8 @@ export class ProtoView {
if (isPresent(binder.events)) {
MapWrapper.forEach(binder.events, (expr, eventName) => {
if (isBlank(elementInjector) || !elementInjector.hasEventEmitter(eventName)) {
ProtoView._addNativeEventListener(element, eventName, expr, view);
var handler = ProtoView.buildInnerCallback(expr, view);
eventManager.addEventListener(element, eventName, handler);
}
});
}
@ -432,24 +435,15 @@ export class ProtoView {
this._viewPool.push(view);
}
static _addNativeEventListener(element: Element, eventName: string, expr: AST, view: View) {
static buildInnerCallback(expr:AST, view:View) {
var locals = MapWrapper.create();
var innerCallback = ProtoView.buildInnerCallback(expr, view, locals);
DOM.on(element, eventName, (event) => {
if (event.target === element) {
innerCallback(event);
}
});
}
static buildInnerCallback(expr:AST, view:View, locals: Map) {
return (event) => {
// 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.
if (view.hydrated()) {
MapWrapper.set(locals, `$event`, event);
MapWrapper.set(locals, '$event', event);
var context = new ContextWithVariableBindings(view.context, locals);
expr.eval(context);
}

View File

@ -5,6 +5,7 @@ import {BaseException} from 'angular2/src/facade/lang';
import {Injector} from 'angular2/di';
import {ElementInjector} from 'angular2/src/core/compiler/element_injector';
import {isPresent, isBlank} from 'angular2/src/facade/lang';
import {EventManager} from 'angular2/src/core/events/event_manager';
export class ViewPort {
parentView: View;
@ -12,12 +13,13 @@ export class ViewPort {
defaultProtoView: ProtoView;
_views: List<View>;
_lightDom: any;
_eventManager: EventManager;
elementInjector: ElementInjector;
appInjector: Injector;
hostElementInjector: ElementInjector;
constructor(parentView: View, templateElement: Element, defaultProtoView: ProtoView,
elementInjector: ElementInjector, lightDom = null) {
elementInjector: ElementInjector, eventManager: EventManager, lightDom = null) {
this.parentView = parentView;
this.templateElement = templateElement;
this.defaultProtoView = defaultProtoView;
@ -28,6 +30,7 @@ export class ViewPort {
this._views = [];
this.appInjector = null;
this.hostElementInjector = null;
this._eventManager = eventManager;
}
hydrate(appInjector: Injector, hostElementInjector: ElementInjector) {
@ -70,7 +73,7 @@ export class ViewPort {
if (!this.hydrated()) throw new BaseException(
'Cannot create views on a dehydrated view port');
// TODO(rado): replace with viewFactory.
var newView = this.defaultProtoView.instantiate(this.hostElementInjector);
var newView = this.defaultProtoView.instantiate(this.hostElementInjector, this._eventManager);
newView.hydrate(this.appInjector, this.hostElementInjector, this.parentView.context);
return this.insert(newView, atIndex);
}