2015-02-19 19:10:16 -08:00
|
|
|
import {isBlank, BaseException, isPresent, StringWrapper} from 'angular2/src/facade/lang';
|
2015-02-27 14:50:06 -08:00
|
|
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
2015-02-09 15:11:31 +01:00
|
|
|
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
|
|
|
|
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
|
|
|
|
|
|
2015-02-19 19:10:16 -08:00
|
|
|
var BUBBLE_SYMBOL = '^';
|
|
|
|
|
|
2015-02-09 15:11:31 +01:00
|
|
|
export class EventManager {
|
|
|
|
|
_plugins: List<EventManagerPlugin>;
|
|
|
|
|
_zone: VmTurnZone;
|
|
|
|
|
|
|
|
|
|
constructor(plugins: List<EventManagerPlugin>, zone: VmTurnZone) {
|
|
|
|
|
this._zone = zone;
|
|
|
|
|
this._plugins = plugins;
|
|
|
|
|
for (var i = 0; i < plugins.length; i++) {
|
|
|
|
|
plugins[i].manager = this;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 14:50:06 -08:00
|
|
|
addEventListener(element, eventName: string, handler: Function) {
|
2015-02-19 19:10:16 -08:00
|
|
|
var shouldSupportBubble = eventName[0] == BUBBLE_SYMBOL;
|
|
|
|
|
if (shouldSupportBubble) {
|
|
|
|
|
eventName = StringWrapper.substring(eventName, 1);
|
2015-02-09 15:11:31 +01:00
|
|
|
}
|
2015-02-19 19:10:16 -08:00
|
|
|
|
|
|
|
|
var plugin = this._findPluginFor(eventName);
|
|
|
|
|
plugin.addEventListener(element, eventName, handler, shouldSupportBubble);
|
2015-02-09 15:11:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getZone(): VmTurnZone {
|
|
|
|
|
return this._zone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_findPluginFor(eventName: string): EventManagerPlugin {
|
|
|
|
|
var plugins = this._plugins;
|
|
|
|
|
for (var i = 0; i < plugins.length; i++) {
|
|
|
|
|
var plugin = plugins[i];
|
|
|
|
|
if (plugin.supports(eventName)) {
|
|
|
|
|
return plugin;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-19 19:10:16 -08:00
|
|
|
throw new BaseException(`No event manager plugin found for event ${eventName}`);
|
2015-02-09 15:11:31 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class EventManagerPlugin {
|
|
|
|
|
manager: EventManager;
|
|
|
|
|
|
2015-02-19 19:10:16 -08:00
|
|
|
// We are assuming here that all plugins support bubbled and non-bubbled events.
|
|
|
|
|
// That is equivalent to having supporting $event.target
|
|
|
|
|
// The bubbling flag (currently ^) is stripped before calling the supports and
|
|
|
|
|
// addEventListener methods.
|
2015-02-09 15:11:31 +01:00
|
|
|
supports(eventName: string): boolean {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 14:50:06 -08:00
|
|
|
addEventListener(element, eventName: string, handler: Function,
|
2015-02-19 19:10:16 -08:00
|
|
|
shouldSupportBubble: boolean) {
|
2015-02-09 15:11:31 +01:00
|
|
|
throw "not implemented";
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-19 19:10:16 -08:00
|
|
|
|
|
|
|
|
export class DomEventsPlugin extends EventManagerPlugin {
|
|
|
|
|
manager: EventManager;
|
|
|
|
|
|
|
|
|
|
// This plugin should come last in the list of plugins, because it accepts all
|
|
|
|
|
// events.
|
|
|
|
|
supports(eventName: string): boolean {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-27 14:50:06 -08:00
|
|
|
addEventListener(element, eventName: string, handler: Function,
|
2015-02-19 19:10:16 -08:00
|
|
|
shouldSupportBubble: boolean) {
|
|
|
|
|
var outsideHandler = shouldSupportBubble ?
|
|
|
|
|
DomEventsPlugin.bubbleCallback(element, handler, this.manager._zone) :
|
|
|
|
|
DomEventsPlugin.sameElementCallback(element, handler, this.manager._zone);
|
|
|
|
|
|
|
|
|
|
this.manager._zone.runOutsideAngular(() => {
|
|
|
|
|
DOM.on(element, eventName, outsideHandler);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static sameElementCallback(element, handler, zone) {
|
|
|
|
|
return (event) => {
|
|
|
|
|
if (event.target === element) {
|
|
|
|
|
zone.run(() => handler(event));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bubbleCallback(element, handler, zone) {
|
|
|
|
|
return (event) => zone.run(() => handler(event));
|
|
|
|
|
}
|
|
|
|
|
}
|