From 855cb16cc7819d27300f8d62285075f19b9d19dd Mon Sep 17 00:00:00 2001 From: vsavkin Date: Fri, 4 Sep 2015 14:23:13 -0700 Subject: [PATCH] refactor(event_manager): use multi bindings to configure EventManager Closes #3978 --- .../angular2/src/core/application_common.ts | 18 +++++------ .../core/render/dom/events/event_manager.ts | 32 +++++++++++++------ .../render/dom/events/hammer_gestures.dart | 2 ++ .../core/render/dom/events/hammer_gestures.ts | 4 +-- .../src/core/render/dom/events/key_events.ts | 2 ++ .../angular2/src/test_lib/test_injector.ts | 17 ++++------ .../src/web_workers/ui/di_bindings.ts | 18 +++++------ .../render/dom/events/event_manager_spec.ts | 19 +++++------ 8 files changed, 64 insertions(+), 48 deletions(-) diff --git a/modules/angular2/src/core/application_common.ts b/modules/angular2/src/core/application_common.ts index 199a442c30..c4597e03bb 100644 --- a/modules/angular2/src/core/application_common.ts +++ b/modules/angular2/src/core/application_common.ts @@ -39,7 +39,11 @@ import {NgZone} from 'angular2/src/core/zone/ng_zone'; import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle'; import {XHR} from 'angular2/src/core/render/xhr'; import {XHRImpl} from 'angular2/src/core/render/xhr_impl'; -import {EventManager, DomEventsPlugin} from 'angular2/src/core/render/dom/events/event_manager'; +import { + EventManager, + DomEventsPlugin, + EVENT_MANAGER_PLUGINS +} from 'angular2/src/core/render/dom/events/event_manager'; import {KeyEventsPlugin} from 'angular2/src/core/render/dom/events/key_events'; import {HammerGesturesPlugin} from 'angular2/src/core/render/dom/events/hammer_gestures'; import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper'; @@ -111,14 +115,10 @@ function _injectorBindings(appComponentType): Array { .toFactory((p: Promise) => p.then(ref => ref.instance), [APP_COMPONENT_REF_PROMISE]), bind(LifeCycle).toFactory((exceptionHandler) => new LifeCycle(null, assertionsEnabled()), [ExceptionHandler]), - bind(EventManager) - .toFactory( - (ngZone) => { - var plugins = - [new HammerGesturesPlugin(), new KeyEventsPlugin(), new DomEventsPlugin()]; - return new EventManager(plugins, ngZone); - }, - [NgZone]), + EventManager, + new Binding(EVENT_MANAGER_PLUGINS, {toClass: DomEventsPlugin, multi: true}), + new Binding(EVENT_MANAGER_PLUGINS, {toClass: KeyEventsPlugin, multi: true}), + new Binding(EVENT_MANAGER_PLUGINS, {toClass: HammerGesturesPlugin, multi: true}), DomRenderer, bind(Renderer).toAlias(DomRenderer), APP_ID_RANDOM_BINDING, diff --git a/modules/angular2/src/core/render/dom/events/event_manager.ts b/modules/angular2/src/core/render/dom/events/event_manager.ts index a0c7a75b2e..7ef193a646 100644 --- a/modules/angular2/src/core/render/dom/events/event_manager.ts +++ b/modules/angular2/src/core/render/dom/events/event_manager.ts @@ -1,12 +1,25 @@ -import {isBlank, BaseException, isPresent, StringWrapper} from 'angular2/src/core/facade/lang'; +import { + isBlank, + BaseException, + isPresent, + StringWrapper, + CONST_EXPR +} from 'angular2/src/core/facade/lang'; +import {ListWrapper} from 'angular2/src/core/facade/collection'; import {DOM} from 'angular2/src/core/dom/dom_adapter'; import {NgZone} from 'angular2/src/core/zone/ng_zone'; +import {Injectable, Inject, OpaqueToken} from 'angular2/di'; +export const EVENT_MANAGER_PLUGINS: OpaqueToken = + CONST_EXPR(new OpaqueToken("EventManagerPlugins")); + +@Injectable() export class EventManager { - constructor(public _plugins: EventManagerPlugin[], public _zone: NgZone) { - for (var i = 0; i < _plugins.length; i++) { - _plugins[i].manager = this; - } + private _plugins: EventManagerPlugin[]; + + constructor(@Inject(EVENT_MANAGER_PLUGINS) plugins: EventManagerPlugin[], private _zone: NgZone) { + plugins.forEach(p => p.manager = this); + this._plugins = ListWrapper.reversed(plugins); } addEventListener(element: HTMLElement, eventName: string, handler: Function) { @@ -48,6 +61,7 @@ export class EventManagerPlugin { } } +@Injectable() export class DomEventsPlugin extends EventManagerPlugin { manager: EventManager; @@ -56,16 +70,16 @@ export class DomEventsPlugin extends EventManagerPlugin { supports(eventName: string): boolean { return true; } addEventListener(element: HTMLElement, eventName: string, handler: Function) { - var zone = this.manager._zone; + var zone = this.manager.getZone(); var outsideHandler = (event) => zone.run(() => handler(event)); - this.manager._zone.runOutsideAngular(() => { DOM.on(element, eventName, outsideHandler); }); + this.manager.getZone().runOutsideAngular(() => { DOM.on(element, eventName, outsideHandler); }); } addGlobalEventListener(target: string, eventName: string, handler: Function): Function { var element = DOM.getGlobalEventTarget(target); - var zone = this.manager._zone; + var zone = this.manager.getZone(); var outsideHandler = (event) => zone.run(() => handler(event)); - return this.manager._zone.runOutsideAngular( + return this.manager.getZone().runOutsideAngular( () => { return DOM.onAndCancel(element, eventName, outsideHandler); }); } } diff --git a/modules/angular2/src/core/render/dom/events/hammer_gestures.dart b/modules/angular2/src/core/render/dom/events/hammer_gestures.dart index 7b05b5e131..bddddd3a5e 100644 --- a/modules/angular2/src/core/render/dom/events/hammer_gestures.dart +++ b/modules/angular2/src/core/render/dom/events/hammer_gestures.dart @@ -3,9 +3,11 @@ library angular.events; import 'dart:html'; import './hammer_common.dart'; import 'package:angular2/src/core/facade/lang.dart' show BaseException; +import "package:angular2/di.dart" show Injectable; import 'dart:js' as js; +@Injectable() class HammerGesturesPlugin extends HammerGesturesPluginCommon { bool supports(String eventName) { if (!super.supports(eventName)) return false; diff --git a/modules/angular2/src/core/render/dom/events/hammer_gestures.ts b/modules/angular2/src/core/render/dom/events/hammer_gestures.ts index 656630b397..fabcc145b2 100644 --- a/modules/angular2/src/core/render/dom/events/hammer_gestures.ts +++ b/modules/angular2/src/core/render/dom/events/hammer_gestures.ts @@ -2,10 +2,10 @@ import {HammerGesturesPluginCommon} from './hammer_common'; import {isPresent, BaseException} from 'angular2/src/core/facade/lang'; +import {Injectable} from 'angular2/di'; +@Injectable() export class HammerGesturesPlugin extends HammerGesturesPluginCommon { - constructor() { super(); } - supports(eventName: string): boolean { if (!super.supports(eventName)) return false; diff --git a/modules/angular2/src/core/render/dom/events/key_events.ts b/modules/angular2/src/core/render/dom/events/key_events.ts index 7642bdefff..2492df3627 100644 --- a/modules/angular2/src/core/render/dom/events/key_events.ts +++ b/modules/angular2/src/core/render/dom/events/key_events.ts @@ -10,6 +10,7 @@ import { import {StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection'; import {EventManagerPlugin} from './event_manager'; import {NgZone} from 'angular2/src/core/zone/ng_zone'; +import {Injectable} from 'angular2/di'; var modifierKeys = ['alt', 'control', 'meta', 'shift']; var modifierKeyGetters: StringMap = { @@ -19,6 +20,7 @@ var modifierKeyGetters: StringMap = { 'shift': (event) => event.shiftKey }; +@Injectable() export class KeyEventsPlugin extends EventManagerPlugin { constructor() { super(); } diff --git a/modules/angular2/src/test_lib/test_injector.ts b/modules/angular2/src/test_lib/test_injector.ts index 0cfa69bee3..8f3b31d3e9 100644 --- a/modules/angular2/src/test_lib/test_injector.ts +++ b/modules/angular2/src/test_lib/test_injector.ts @@ -30,7 +30,11 @@ import {NgZone} from 'angular2/src/core/zone/ng_zone'; import {DOM} from 'angular2/src/core/dom/dom_adapter'; -import {EventManager, DomEventsPlugin} from 'angular2/src/core/render/dom/events/event_manager'; +import { + EventManager, + DomEventsPlugin, + EVENT_MANAGER_PLUGINS +} from 'angular2/src/core/render/dom/events/event_manager'; import {MockViewResolver} from 'angular2/src/mock/view_resolver_mock'; import {MockXHR} from 'angular2/src/core/render/xhr_mock'; @@ -144,15 +148,8 @@ function _getAppBindings() { StyleInliner, TestComponentBuilder, bind(NgZone).toClass(MockNgZone), - bind(EventManager) - .toFactory( - (zone) => { - var plugins = [ - new DomEventsPlugin(), - ]; - return new EventManager(plugins, zone); - }, - [NgZone]), + EventManager, + new Binding(EVENT_MANAGER_PLUGINS, {toClass: DomEventsPlugin, multi: true}) ]; } diff --git a/modules/angular2/src/web_workers/ui/di_bindings.ts b/modules/angular2/src/web_workers/ui/di_bindings.ts index 13d1a5fe59..576857def6 100644 --- a/modules/angular2/src/web_workers/ui/di_bindings.ts +++ b/modules/angular2/src/web_workers/ui/di_bindings.ts @@ -11,7 +11,11 @@ import { PreGeneratedChangeDetection } from 'angular2/src/core/change_detection/change_detection'; import {DEFAULT_PIPES} from 'angular2/pipes'; -import {EventManager, DomEventsPlugin} from 'angular2/src/core/render/dom/events/event_manager'; +import { + EventManager, + DomEventsPlugin, + EVENT_MANAGER_PLUGINS +} from 'angular2/src/core/render/dom/events/event_manager'; import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler'; import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter'; import {KeyEventsPlugin} from 'angular2/src/core/render/dom/events/key_events'; @@ -87,14 +91,10 @@ function _injectorBindings(): any[] { return [ bind(DOCUMENT) .toValue(DOM.defaultDoc()), - bind(EventManager) - .toFactory( - (ngZone) => { - var plugins = - [new HammerGesturesPlugin(), new KeyEventsPlugin(), new DomEventsPlugin()]; - return new EventManager(plugins, ngZone); - }, - [NgZone]), + EventManager, + new Binding(EVENT_MANAGER_PLUGINS, {toClass: DomEventsPlugin, multi: true}), + new Binding(EVENT_MANAGER_PLUGINS, {toClass: KeyEventsPlugin, multi: true}), + new Binding(EVENT_MANAGER_PLUGINS, {toClass: HammerGesturesPlugin, multi: true}), DomRenderer, bind(Renderer).toAlias(DomRenderer), APP_ID_RANDOM_BINDING, diff --git a/modules/angular2/test/core/render/dom/events/event_manager_spec.ts b/modules/angular2/test/core/render/dom/events/event_manager_spec.ts index a397148152..84b282b2f3 100644 --- a/modules/angular2/test/core/render/dom/events/event_manager_spec.ts +++ b/modules/angular2/test/core/render/dom/events/event_manager_spec.ts @@ -25,14 +25,15 @@ export function main() { describe('EventManager', () => { - it('should delegate event bindings to plugins', () => { - var element = el('
'); - var handler = (e) => e; - var plugin = new FakeEventManagerPlugin(['click']); - var manager = new EventManager([plugin, domEventPlugin], new FakeNgZone()); - manager.addEventListener(element, 'click', handler); - expect(plugin._eventHandler.get('click')).toBe(handler); - }); + it('should delegate event bindings to plugins that are passed in from the most generic one to the most specific one', + () => { + var element = el('
'); + var handler = (e) => e; + var plugin = new FakeEventManagerPlugin(['click']); + var manager = new EventManager([domEventPlugin, plugin], new FakeNgZone()); + manager.addEventListener(element, 'click', handler); + expect(plugin._eventHandler.get('click')).toBe(handler); + }); it('should delegate event bindings to the first plugin supporting the event', () => { var element = el('
'); @@ -40,7 +41,7 @@ export function main() { var dblClickHandler = (e) => e; var plugin1 = new FakeEventManagerPlugin(['dblclick']); var plugin2 = new FakeEventManagerPlugin(['click', 'dblclick']); - var manager = new EventManager([plugin1, plugin2], new FakeNgZone()); + var manager = new EventManager([plugin2, plugin1], new FakeNgZone()); manager.addEventListener(element, 'click', clickHandler); manager.addEventListener(element, 'dblclick', dblClickHandler); expect(plugin1._eventHandler.has('click')).toBe(false);