80 lines
2.4 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, InjectionToken, NgZone} from '@angular/core';
import {getDOM} from '../dom_adapter';
/**
* @stable
*/
export const EVENT_MANAGER_PLUGINS =
new InjectionToken<EventManagerPlugin[]>('EventManagerPlugins');
/**
* @stable
*/
@Injectable()
export class EventManager {
private _plugins: EventManagerPlugin[];
private _eventNameToPlugin = new Map<string, EventManagerPlugin>();
constructor(@Inject(EVENT_MANAGER_PLUGINS) plugins: EventManagerPlugin[], private _zone: NgZone) {
plugins.forEach(p => p.manager = this);
this._plugins = plugins.slice().reverse();
}
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
const plugin = this._findPluginFor(eventName);
return plugin.addEventListener(element, eventName, handler);
}
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
const plugin = this._findPluginFor(eventName);
return plugin.addGlobalEventListener(target, eventName, handler);
}
getZone(): NgZone { return this._zone; }
/** @internal */
_findPluginFor(eventName: string): EventManagerPlugin {
const plugin = this._eventNameToPlugin.get(eventName);
if (plugin) {
return plugin;
}
const plugins = this._plugins;
for (let i = 0; i < plugins.length; i++) {
const plugin = plugins[i];
if (plugin.supports(eventName)) {
this._eventNameToPlugin.set(eventName, plugin);
return plugin;
}
}
throw new Error(`No event manager plugin found for event ${eventName}`);
}
}
export abstract class EventManagerPlugin {
constructor(private _doc: any) {}
manager: EventManager;
abstract supports(eventName: string): boolean;
abstract addEventListener(element: HTMLElement, eventName: string, handler: Function): Function;
addGlobalEventListener(element: string, eventName: string, handler: Function): Function {
const target: HTMLElement = getDOM().getGlobalEventTarget(this._doc, element);
if (!target) {
throw new Error(`Unsupported event target ${target} for event ${eventName}`);
}
return this.addEventListener(target, eventName, handler);
};
}