Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
fix(utils): event listener patches break when passed an object implem…
Browse files Browse the repository at this point in the history
…enting EventListener
  • Loading branch information
Matthew Hill authored and vicb committed Jul 13, 2015
1 parent da5f265 commit af88ff8
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 11 deletions.
30 changes: 23 additions & 7 deletions lib/utils.js
Expand Up @@ -86,21 +86,37 @@ function patchProperties(obj, properties) {

function patchEventTargetMethods(obj) {
var addDelegate = obj.addEventListener;
obj.addEventListener = function (eventName, fn) {
fn._bound = fn._bound || {};
arguments[1] = fn._bound[eventName] = zone.bind(fn);
obj.addEventListener = function (eventName, handler) {
var fn;

if (handler.handleEvent) {
// Have to pass in 'handler' reference as an argument here, otherwise it gets clobbered in
// IE9 by the arguments[1] assignment at end of this function.
fn = (function(handler) {
return function() {
handler.handleEvent.apply(handler, arguments);
};
})(handler);
} else {
fn = handler;
}

handler._fn = fn;
handler._bound = handler._bound || {};
arguments[1] = handler._bound[eventName] = zone.bind(fn);
return addDelegate.apply(this, arguments);
};

var removeDelegate = obj.removeEventListener;
obj.removeEventListener = function (eventName, fn) {
if(arguments[1]._bound && arguments[1]._bound[eventName]) {
var _bound = arguments[1]._bound;
obj.removeEventListener = function (eventName, handler) {
if(handler._bound && handler._bound[eventName]) {
var _bound = handler._bound;

arguments[1] = _bound[eventName];
delete _bound[eventName];
}
var result = removeDelegate.apply(this, arguments);
global.zone.dequeueTask(fn);
global.zone.dequeueTask(handler._fn);
return result;
};
};
Expand Down
48 changes: 44 additions & 4 deletions test/patch/element.spec.js
Expand Up @@ -14,17 +14,43 @@ describe('element', function () {
document.body.removeChild(button);
});

it('should work with addEventListener', function () {
it('should work with addEventListener when called with a function listener', function () {
var clickEvent = document.createEvent('Event');
clickEvent.initEvent('click', true, true);

testZone.run(function() {
button.addEventListener('click', function () {
button.addEventListener('click', function (event) {
expect(zone).toBeDirectChildOf(testZone);
expect(event).toBe(clickEvent)
});
});

button.click();
button.dispatchEvent(clickEvent);
});

it('should respect removeEventListener', function () {
it('should work with addEventListener when called with an EventListener-implementing listener', function () {
var eventListener = {
x: 5,
handleEvent: function(event) {
// Test that context is preserved
expect(this.x).toBe(5);

expect(event).toBe(clickEvent);
expect(zone).toBeDirectChildOf(testZone);
}
};

var clickEvent = document.createEvent('Event');
clickEvent.initEvent('click', true, true);

testZone.run(function() {
button.addEventListener('click', eventListener);
});

button.dispatchEvent(clickEvent);
});

it('should respect removeEventListener when called with a function listener', function () {
var log = '';
var logFunction = function logFunction () {
log += 'a';
Expand All @@ -44,6 +70,20 @@ describe('element', function () {
expect(log).toEqual('aa');
});

it('should respect removeEventListener with an EventListener-implementing listener', function () {
var eventListener = {
x: 5,
handleEvent: jasmine.createSpy('handleEvent')
};

button.addEventListener('click', eventListener);
button.removeEventListener('click', eventListener);

button.click();

expect(eventListener.handleEvent).not.toHaveBeenCalled();
});


describe('onclick', function() {

Expand Down

0 comments on commit af88ff8

Please sign in to comment.