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

Commit dd2e1bf

Browse files
Matthew Hillvicb
Matthew Hill
authored andcommitted
fix(lib/utils): adds compliant handling of useCapturing param for EventTarget methods
1 parent f8a2be5 commit dd2e1bf

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

lib/utils.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ var boundFnsKey = keys.create('boundFns');
9696
function patchEventTargetMethods(obj) {
9797
// This is required for the addEventListener hook on the root zone.
9898
obj[keys.common.addEventListener] = obj.addEventListener;
99-
obj.addEventListener = function (eventName, handler) {
99+
obj.addEventListener = function (eventName, handler, useCapturing) {
100+
var eventType = eventName + (useCapturing ? '$capturing' : '$bubbling');
100101
var fn;
101102
//Ignore special listeners of IE11 & Edge dev tools, see https://github.com/angular/zone.js/issues/150
102103
if (handler.toString() !== "[object FunctionWrapper]") {
@@ -114,19 +115,20 @@ function patchEventTargetMethods(obj) {
114115

115116
handler[originalFnKey] = fn;
116117
handler[boundFnsKey] = handler[boundFnsKey] || {};
117-
arguments[1] = handler[boundFnsKey][eventName] = zone.bind(fn);
118+
arguments[1] = handler[boundFnsKey][eventType] = zone.bind(fn);
118119
}
119120
return global.zone.addEventListener.apply(this, arguments);
120121
};
121122

122123
// This is required for the removeEventListener hook on the root zone.
123124
obj[keys.common.removeEventListener] = obj.removeEventListener;
124-
obj.removeEventListener = function (eventName, handler) {
125-
if(handler[boundFnsKey] && handler[boundFnsKey][eventName]) {
125+
obj.removeEventListener = function (eventName, handler, useCapturing) {
126+
var eventType = eventName + (useCapturing ? '$capturing' : '$bubbling');
127+
if (handler[boundFnsKey] && handler[boundFnsKey][eventType]) {
126128
var _bound = handler[boundFnsKey];
127129

128-
arguments[1] = _bound[eventName];
129-
delete _bound[eventName];
130+
arguments[1] = _bound[eventType];
131+
delete _bound[eventType];
130132
}
131133
var result = global.zone.removeEventListener.apply(this, arguments);
132134
global.zone.dequeueTask(handler[originalFnKey]);

test/patch/element.spec.js

+50
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,56 @@ describe('element', function () {
8484
expect(eventListener.handleEvent).not.toHaveBeenCalled();
8585
});
8686

87+
it('should correctly handle capturing versus nonCapturing eventListeners', function () {
88+
var log = [];
89+
var clickEvent = document.createEvent('Event');
90+
91+
function capturingListener () {
92+
log.push('capturingListener');
93+
}
94+
95+
function bubblingListener () {
96+
log.push('bubblingListener');
97+
}
98+
99+
clickEvent.initEvent('click', true, true);
100+
101+
document.body.addEventListener('click', capturingListener, true);
102+
document.body.addEventListener('click', bubblingListener);
103+
104+
button.dispatchEvent(clickEvent);
105+
106+
expect(log).toEqual([
107+
'capturingListener',
108+
'bubblingListener'
109+
]);
110+
});
111+
112+
it('should correctly handle a listener that is both capturing and nonCapturing', function () {
113+
var log = [];
114+
var clickEvent = document.createEvent('Event');
115+
116+
function listener () {
117+
log.push('listener');
118+
}
119+
120+
clickEvent.initEvent('click', true, true);
121+
122+
document.body.addEventListener('click', listener, true);
123+
document.body.addEventListener('click', listener);
124+
125+
button.dispatchEvent(clickEvent);
126+
127+
document.body.removeEventListener('click', listener, true);
128+
document.body.removeEventListener('click', listener);
129+
130+
button.dispatchEvent(clickEvent);
131+
132+
expect(log).toEqual([
133+
'listener',
134+
'listener'
135+
]);
136+
});
87137

88138
describe('onclick', function() {
89139

0 commit comments

Comments
 (0)