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

Commit 1897440

Browse files
Matthew Hillvicb
authored andcommitted
feat(lib/core): add/removeEventListener hooks
1 parent 4bbb0c6 commit 1897440

4 files changed

Lines changed: 122 additions & 8 deletions

File tree

README.md

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ Transforms a function to run within the given zone.
179179
### `zone.fork`
180180

181181
```javascript
182-
zone.fork({
182+
var myZone = zone.fork({
183183
onZoneCreated: function () {},
184184
beforeTask: function () {},
185185
afterTask: function () {},
@@ -190,7 +190,6 @@ zone.fork({
190190
setInterval: function () {},
191191
alert: function () {},
192192
prompt: function () {},
193-
addEventListener: function () {}
194193
});
195194
myZone.run(function () {
196195
// woo!
@@ -242,7 +241,51 @@ growing the stack size on each recursive call.
242241

243242
### `zone.addEventListener`
244243

245-
This hook allows you to intercept calls to `EventTarget.addEventListener`.
244+
This hook allows you to intercept calls to `EventTarget#addEventListener`.
245+
246+
````javascript
247+
var clickListenerCount = 0;
248+
249+
zone.fork(
250+
$addEventListener: function(parentAddEventListener) {
251+
return function (type, listener) {
252+
if (type === 'click') clickListenerCount++;
253+
return parentAddEventListener.apply(this, arguments);
254+
};
255+
}
256+
);
257+
258+
zone.run(function() {
259+
myElement.addEventListener('click', listener);
260+
myOtherElement.addEventListener('click', listener);
261+
262+
console.log(clickListenerCount); // 2
263+
});
264+
````
265+
266+
### `zone.removeEventListener`
267+
268+
This hook allows you to intercept calls to `EventTarget#removeEventListener`.
269+
270+
````javascript
271+
var clickListenerCount = 0;
272+
273+
zone.fork(
274+
$removeEventListener: function(parentRemoveEventListener) {
275+
return function (type, listener) {
276+
if (type === 'click') clickListenerCount--;
277+
return parentRemoveEventListener.apply(this, arguments);
278+
};
279+
}
280+
);
281+
282+
zone.run(function() {
283+
myElement.addEventListener('click', listener);
284+
myElement.removeEventListener('click', listener);
285+
286+
console.log(clickListenerCount); // 0
287+
});
288+
````
246289

247290

248291
## Status

lib/core.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,13 @@ Zone.prototype = {
119119
onZoneCreated: function () {},
120120
afterTask: function () {},
121121
enqueueTask: function () {},
122-
dequeueTask: function () {}
122+
dequeueTask: function () {},
123+
addEventListener: function () {
124+
return this._addEventListener.apply(this, arguments);
125+
},
126+
removeEventListener: function () {
127+
return this._removeEventListener.apply(this, arguments);
128+
}
123129
};
124130

125131
// Root zone ID === 1

lib/utils.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ function patchProperties(obj, properties) {
8989
};
9090

9191
function patchEventTargetMethods(obj) {
92-
var addDelegate = obj.addEventListener;
92+
// This is required for the addEventListener hook on the root zone.
93+
obj._addEventListener = obj.addEventListener;
9394
obj.addEventListener = function (eventName, handler) {
9495
var fn;
9596
//Ignore special listeners of IE11 & Edge dev tools, see https://github.com/angular/zone.js/issues/150
@@ -110,18 +111,19 @@ function patchEventTargetMethods(obj) {
110111
handler._bound = handler._bound || {};
111112
arguments[1] = handler._bound[eventName] = zone.bind(fn);
112113
}
113-
return addDelegate.apply(this, arguments);
114+
return global.zone.addEventListener.apply(this, arguments);
114115
};
115116

116-
var removeDelegate = obj.removeEventListener;
117+
// This is required for the removeEventListener hook on the root zone.
118+
obj._removeEventListener = obj.removeEventListener;
117119
obj.removeEventListener = function (eventName, handler) {
118120
if(handler._bound && handler._bound[eventName]) {
119121
var _bound = handler._bound;
120122

121123
arguments[1] = _bound[eventName];
122124
delete _bound[eventName];
123125
}
124-
var result = removeDelegate.apply(this, arguments);
126+
var result = global.zone.removeEventListener.apply(this, arguments);
125127
global.zone.dequeueTask(handler._fn);
126128
return result;
127129
};

test/zone.spec.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,69 @@ describe('Zone', function () {
105105

106106
expect(spy).toHaveBeenCalled();
107107
});
108+
109+
describe('eventListener hooks', function () {
110+
var button;
111+
var clickEvent;
112+
113+
beforeEach(function () {
114+
button = document.createElement('button');
115+
clickEvent = document.createEvent('Event');
116+
clickEvent.initEvent('click', true, true);
117+
document.body.appendChild(button);
118+
});
119+
120+
afterEach(function () {
121+
document.body.removeChild(button);
122+
});
123+
124+
it('should support addEventListener', function () {
125+
var hookSpy = jasmine.createSpy();
126+
var eventListenerSpy = jasmine.createSpy();
127+
var zone = rootZone.fork({
128+
$addEventListener: function(parentAddEventListener) {
129+
return function (type, listener) {
130+
return parentAddEventListener.call(this, type, function() {
131+
hookSpy();
132+
listener.apply(this, arguments);
133+
});
134+
}
135+
}
136+
});
137+
138+
zone.run(function() {
139+
button.addEventListener('click', eventListenerSpy);
140+
});
141+
142+
button.dispatchEvent(clickEvent);
143+
144+
expect(hookSpy).toHaveBeenCalled();
145+
expect(eventListenerSpy).toHaveBeenCalled();
146+
});
147+
148+
it('should support removeEventListener', function () {
149+
var hookSpy = jasmine.createSpy();
150+
var eventListenerSpy = jasmine.createSpy();
151+
var zone = rootZone.fork({
152+
$removeEventListener: function(parentRemoveEventListener) {
153+
return function (type, listener) {
154+
hookSpy();
155+
return parentRemoveEventListener.call(this, type, listener);
156+
}
157+
}
158+
});
159+
160+
zone.run(function() {
161+
button.addEventListener('click', eventListenerSpy);
162+
button.removeEventListener('click', eventListenerSpy);
163+
});
164+
165+
button.dispatchEvent(clickEvent);
166+
167+
expect(hookSpy).toHaveBeenCalled();
168+
expect(eventListenerSpy).not.toHaveBeenCalled();
169+
});
170+
});
108171
});
109172

110173

0 commit comments

Comments
 (0)