feat(events): adds support for bubbling native events (^event).

Refactor - move DomEventManager into its own plugin.
This commit is contained in:
Rado Kirov
2015-02-19 19:10:16 -08:00
parent 2f015cc336
commit 6ad2c18277
6 changed files with 117 additions and 43 deletions

View File

@ -1,19 +1,34 @@
import {describe, ddescribe, it, iit, xit, xdescribe, expect, beforeEach, el} from 'angular2/test_lib';
import {EventManager, EventManagerPlugin} from 'angular2/src/core/events/event_manager';
import {EventManager, EventManagerPlugin, DomEventsPlugin} from 'angular2/src/core/events/event_manager';
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
import {DOM, Element} from 'angular2/src/facade/dom';
import {DOM, Element, document} from 'angular2/src/facade/dom';
export function main() {
var domEventPlugin;
beforeEach(() => {
domEventPlugin = new DomEventsPlugin();
});
describe('EventManager', () => {
it('should delegate event bindings to plugins', () => {
var element = el('<div></div>');
var handler = (e) => e;
var plugin = new FakeEventManagerPlugin(['click']);
var manager = new EventManager([plugin], new FakeVmTurnZone());
var manager = new EventManager([plugin, domEventPlugin], new FakeVmTurnZone());
manager.addEventListener(element, 'click', handler);
expect(MapWrapper.get(plugin._eventHandlers, 'click')).toBe(handler);
expect(MapWrapper.get(plugin._nonBubbleEventHandlers, 'click')).toBe(handler);
});
it('should delegate bubbling events to plugins', () => {
var element = el('<div></div>');
var handler = (e) => e;
var plugin = new FakeEventManagerPlugin(['click']);
var manager = new EventManager([plugin, domEventPlugin], new FakeVmTurnZone());
manager.addEventListener(element, '^click', handler);
expect(MapWrapper.get(plugin._bubbleEventHandlers, 'click')).toBe(handler);
});
it('should delegate event bindings to the first plugin supporting the event', () => {
@ -25,21 +40,46 @@ export function main() {
var manager = new EventManager([plugin1, plugin2], new FakeVmTurnZone());
manager.addEventListener(element, 'click', clickHandler);
manager.addEventListener(element, 'dblclick', dblClickHandler);
expect(MapWrapper.contains(plugin1._eventHandlers, 'click')).toBe(false);
expect(MapWrapper.get(plugin2._eventHandlers, 'click')).toBe(clickHandler);
expect(MapWrapper.contains(plugin2._eventHandlers, 'dblclick')).toBe(false);
expect(MapWrapper.get(plugin1._eventHandlers, 'dblclick')).toBe(dblClickHandler);
expect(MapWrapper.contains(plugin1._nonBubbleEventHandlers, 'click')).toBe(false);
expect(MapWrapper.get(plugin2._nonBubbleEventHandlers, 'click')).toBe(clickHandler);
expect(MapWrapper.contains(plugin2._nonBubbleEventHandlers, 'dblclick')).toBe(false);
expect(MapWrapper.get(plugin1._nonBubbleEventHandlers, 'dblclick')).toBe(dblClickHandler);
});
it('should fall back to native events when no plugin can handle the event', () => {
it('should throw when no plugin can handle the event', () => {
var element = el('<div></div>');
var plugin = new FakeEventManagerPlugin(['dblclick']);
var manager = new EventManager([plugin], new FakeVmTurnZone());
expect(() => manager.addEventListener(element, 'click', null))
.toThrowError('No event manager plugin found for event click');
});
it('by default events are only caught on same element', () => {
var element = el('<div><div></div></div>');
var child = DOM.firstChild(element);
var dispatchedEvent = DOM.createMouseEvent('click');
var receivedEvent = null;
var handler = (e) => { receivedEvent = e; };
var plugin = new FakeEventManagerPlugin(['dblclick']);
var manager = new EventManager([plugin], new FakeVmTurnZone());
var manager = new EventManager([domEventPlugin], new FakeVmTurnZone());
manager.addEventListener(element, 'click', handler);
DOM.dispatchEvent(element, dispatchedEvent);
DOM.dispatchEvent(child, dispatchedEvent);
expect(receivedEvent).toBe(null);
});
it('bubbled events are caught when fired from a child', () => {
var element = el('<div><div></div></div>');
// Workaround for https://bugs.webkit.org/show_bug.cgi?id=122755
DOM.appendChild(document.body, element);
var child = DOM.firstChild(element);
var dispatchedEvent = DOM.createMouseEvent('click');
var receivedEvent = null;
var handler = (e) => { receivedEvent = e; };
var manager = new EventManager([domEventPlugin], new FakeVmTurnZone());
manager.addEventListener(element, '^click', handler);
DOM.dispatchEvent(child, dispatchedEvent);
expect(receivedEvent).toBe(dispatchedEvent);
});
});
@ -47,19 +87,22 @@ export function main() {
class FakeEventManagerPlugin extends EventManagerPlugin {
_supports: List<string>;
_eventHandlers: Map;
_nonBubbleEventHandlers: Map;
_bubbleEventHandlers: Map;
constructor(supports: List<string>) {
super();
this._supports = supports;
this._eventHandlers = MapWrapper.create();
this._nonBubbleEventHandlers = MapWrapper.create();
this._bubbleEventHandlers = MapWrapper.create();
}
supports(eventName: string): boolean {
return ListWrapper.contains(this._supports, eventName);
}
addEventListener(element: Element, eventName: string, handler: Function) {
MapWrapper.set(this._eventHandlers, eventName, handler);
addEventListener(element: Element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
MapWrapper.set(shouldSupportBubble ? this._bubbleEventHandlers : this._nonBubbleEventHandlers,
eventName, handler);
}
}