| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 19:16:25 -07:00
										 |  |  | import {ɵgetDOM as getDOM} from '@angular/common'; | 
					
						
							| 
									
										
										
										
											2016-04-28 17:50:03 -07:00
										 |  |  | import {NgZone} from '@angular/core/src/zone/ng_zone'; | 
					
						
							| 
									
										
										
										
											2017-03-02 12:12:46 -08:00
										 |  |  | import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal'; | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  | import {DomEventsPlugin} from '@angular/platform-browser/src/dom/events/dom_events'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | import {EventManager, EventManagerPlugin} from '@angular/platform-browser/src/dom/events/event_manager'; | 
					
						
							| 
									
										
										
										
											2019-08-27 16:21:39 -07:00
										 |  |  | import {createMouseEvent, el} from '../../../testing/src/browser_util'; | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 22:18:50 -08:00
										 |  |  | (function() { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | if (isNode) return; | 
					
						
							|  |  |  | let domEventPlugin: DomEventsPlugin; | 
					
						
							|  |  |  | let doc: any; | 
					
						
							|  |  |  | let zone: NgZone; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('EventManager', () => { | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							|  |  |  |     doc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument(); | 
					
						
							|  |  |  |     zone = new NgZone({}); | 
					
						
							|  |  |  |     domEventPlugin = new DomEventsPlugin(doc); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-02-10 16:54:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should delegate event bindings to plugins that are passed in from the most generic one to the most specific one', | 
					
						
							|  |  |  |      () => { | 
					
						
							|  |  |  |        const element = el('<div></div>'); | 
					
						
							|  |  |  |        const handler = (e: any /** TODO #9100 */) => e; | 
					
						
							|  |  |  |        const plugin = new FakeEventManagerPlugin(doc, ['click']); | 
					
						
							|  |  |  |        const manager = new EventManager([domEventPlugin, plugin], new FakeNgZone()); | 
					
						
							|  |  |  |        manager.addEventListener(element, 'click', handler); | 
					
						
							|  |  |  |        expect(plugin.eventHandler['click']).toBe(handler); | 
					
						
							|  |  |  |      }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should delegate event bindings to the first plugin supporting the event', () => { | 
					
						
							|  |  |  |     const element = el('<div></div>'); | 
					
						
							|  |  |  |     const clickHandler = (e: any /** TODO #9100 */) => e; | 
					
						
							|  |  |  |     const dblClickHandler = (e: any /** TODO #9100 */) => e; | 
					
						
							|  |  |  |     const plugin1 = new FakeEventManagerPlugin(doc, ['dblclick']); | 
					
						
							|  |  |  |     const plugin2 = new FakeEventManagerPlugin(doc, ['click', 'dblclick']); | 
					
						
							|  |  |  |     const manager = new EventManager([plugin2, plugin1], new FakeNgZone()); | 
					
						
							|  |  |  |     manager.addEventListener(element, 'click', clickHandler); | 
					
						
							|  |  |  |     manager.addEventListener(element, 'dblclick', dblClickHandler); | 
					
						
							|  |  |  |     expect(plugin2.eventHandler['click']).toBe(clickHandler); | 
					
						
							|  |  |  |     expect(plugin1.eventHandler['dblclick']).toBe(dblClickHandler); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should throw when no plugin can handle the event', () => { | 
					
						
							|  |  |  |     const element = el('<div></div>'); | 
					
						
							|  |  |  |     const plugin = new FakeEventManagerPlugin(doc, ['dblclick']); | 
					
						
							|  |  |  |     const manager = new EventManager([plugin], new FakeNgZone()); | 
					
						
							|  |  |  |     expect(() => manager.addEventListener(element, 'click', null!)) | 
					
						
							|  |  |  |         .toThrowError('No event manager plugin found for event click'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('events are caught when fired from a child', () => { | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     // Workaround for https://bugs.webkit.org/show_bug.cgi?id=122755
 | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const child = element.firstChild as Element; | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvent: any /** TODO #9100 */ = null; | 
					
						
							|  |  |  |     const handler = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvent = e; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  |     manager.addEventListener(element, 'click', handler); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(child, dispatchedEvent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(receivedEvent).toBe(dispatchedEvent); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should add and remove global event listeners', () => { | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvent: any /** TODO #9100 */ = null; | 
					
						
							|  |  |  |     const handler = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvent = e; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const remover = manager.addGlobalEventListener('document', 'click', handler); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvent).toBe(dispatchedEvent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvent = null; | 
					
						
							|  |  |  |     remover(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvent).toBe(null); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-02-19 19:10:16 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should keep zone when addEventListener', () => { | 
					
						
							|  |  |  |     const Zone = (window as any)['Zone']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvent: any /** TODO #9100 */ = null; | 
					
						
							|  |  |  |     let receivedZone: any = null; | 
					
						
							|  |  |  |     const handler = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvent = e; | 
					
						
							|  |  |  |       receivedZone = Zone.current; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let remover: any = null; | 
					
						
							|  |  |  |     Zone.root.run(() => { | 
					
						
							|  |  |  |       remover = manager.addEventListener(element, 'click', handler); | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvent).toBe(dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedZone.name).toBe(Zone.root.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvent = null; | 
					
						
							|  |  |  |     remover && remover(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvent).toBe(null); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should keep zone when addEventListener multiple times', () => { | 
					
						
							|  |  |  |     const Zone = (window as any)['Zone']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvents: any[] /** TODO #9100 */ = []; | 
					
						
							|  |  |  |     let receivedZones: any[] = []; | 
					
						
							|  |  |  |     const handler1 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const handler2 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let remover1: any = null; | 
					
						
							|  |  |  |     let remover2: any = null; | 
					
						
							|  |  |  |     Zone.root.run(() => { | 
					
						
							|  |  |  |       remover1 = manager.addEventListener(element, 'click', handler1); | 
					
						
							| 
									
										
										
										
											2015-04-02 15:56:58 +02:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     Zone.root.fork({name: 'test'}).run(() => { | 
					
						
							|  |  |  |       remover2 = manager.addEventListener(element, 'click', handler2); | 
					
						
							| 
									
										
										
										
											2017-09-02 02:30:37 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([dispatchedEvent, dispatchedEvent]); | 
					
						
							|  |  |  |     expect(receivedZones).toEqual([Zone.root.name, 'test']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvents = []; | 
					
						
							|  |  |  |     remover1 && remover1(); | 
					
						
							|  |  |  |     remover2 && remover2(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-09-02 02:30:37 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should support event.stopImmediatePropagation', () => { | 
					
						
							|  |  |  |     const Zone = (window as any)['Zone']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvents: any[] /** TODO #9100 */ = []; | 
					
						
							|  |  |  |     let receivedZones: any[] = []; | 
					
						
							|  |  |  |     const handler1 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |       e.stopImmediatePropagation(); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const handler2 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let remover1: any = null; | 
					
						
							|  |  |  |     let remover2: any = null; | 
					
						
							|  |  |  |     Zone.root.run(() => { | 
					
						
							|  |  |  |       remover1 = manager.addEventListener(element, 'click', handler1); | 
					
						
							| 
									
										
										
										
											2017-09-02 02:30:37 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     Zone.root.fork({name: 'test'}).run(() => { | 
					
						
							|  |  |  |       remover2 = manager.addEventListener(element, 'click', handler2); | 
					
						
							| 
									
										
										
										
											2017-11-16 11:43:53 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([dispatchedEvent]); | 
					
						
							|  |  |  |     expect(receivedZones).toEqual([Zone.root.name]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvents = []; | 
					
						
							|  |  |  |     remover1 && remover1(); | 
					
						
							|  |  |  |     remover2 && remover2(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-11-16 11:43:53 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should handle event correctly when one handler remove itself ', () => { | 
					
						
							|  |  |  |     const Zone = (window as any)['Zone']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvents: any[] /** TODO #9100 */ = []; | 
					
						
							|  |  |  |     let receivedZones: any[] = []; | 
					
						
							|  |  |  |     let remover1: any = null; | 
					
						
							|  |  |  |     let remover2: any = null; | 
					
						
							|  |  |  |     const handler1 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							| 
									
										
										
										
											2017-09-02 02:30:37 +09:00
										 |  |  |       remover1 && remover1(); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     }; | 
					
						
							|  |  |  |     const handler2 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Zone.root.run(() => { | 
					
						
							|  |  |  |       remover1 = manager.addEventListener(element, 'click', handler1); | 
					
						
							| 
									
										
										
										
											2017-09-02 02:30:37 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     Zone.root.fork({name: 'test'}).run(() => { | 
					
						
							|  |  |  |       remover2 = manager.addEventListener(element, 'click', handler2); | 
					
						
							| 
									
										
										
										
											2017-09-02 02:30:37 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([dispatchedEvent, dispatchedEvent]); | 
					
						
							|  |  |  |     expect(receivedZones).toEqual([Zone.root.name, 'test']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvents = []; | 
					
						
							|  |  |  |     remover1 && remover1(); | 
					
						
							|  |  |  |     remover2 && remover2(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-09-02 02:30:37 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should only add same callback once when addEventListener', () => { | 
					
						
							|  |  |  |     const Zone = (window as any)['Zone']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvents: any[] /** TODO #9100 */ = []; | 
					
						
							|  |  |  |     let receivedZones: any[] = []; | 
					
						
							|  |  |  |     const handler = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let remover1: any = null; | 
					
						
							|  |  |  |     let remover2: any = null; | 
					
						
							|  |  |  |     Zone.root.run(() => { | 
					
						
							|  |  |  |       remover1 = manager.addEventListener(element, 'click', handler); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     Zone.root.fork({name: 'test'}).run(() => { | 
					
						
							|  |  |  |       remover2 = manager.addEventListener(element, 'click', handler); | 
					
						
							| 
									
										
										
										
											2017-11-20 16:33:37 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([dispatchedEvent]); | 
					
						
							|  |  |  |     expect(receivedZones).toEqual([Zone.root.name]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvents = []; | 
					
						
							|  |  |  |     remover1 && remover1(); | 
					
						
							|  |  |  |     remover2 && remover2(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-11-20 16:33:37 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should be able to remove event listener which was added inside of ngZone', () => { | 
					
						
							|  |  |  |     const Zone = (window as any)['Zone']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvents: any[] /** TODO #9100 */ = []; | 
					
						
							|  |  |  |     let receivedZones: any[] = []; | 
					
						
							|  |  |  |     const handler1 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const handler2 = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |       receivedZones.push(Zone.current.name); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let remover1: any = null; | 
					
						
							|  |  |  |     let remover2: any = null; | 
					
						
							|  |  |  |     // handler1 is added in root zone
 | 
					
						
							|  |  |  |     Zone.root.run(() => { | 
					
						
							|  |  |  |       remover1 = manager.addEventListener(element, 'click', handler1); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     // handler2 is added in 'angular' zone
 | 
					
						
							|  |  |  |     Zone.root.fork({name: 'fakeAngularZone', properties: {isAngularZone: true}}).run(() => { | 
					
						
							|  |  |  |       remover2 = manager.addEventListener(element, 'click', handler2); | 
					
						
							| 
									
										
										
										
											2017-08-31 15:52:51 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([dispatchedEvent, dispatchedEvent]); | 
					
						
							|  |  |  |     expect(receivedZones).toEqual([Zone.root.name, 'fakeAngularZone']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvents = []; | 
					
						
							|  |  |  |     remover1 && remover1(); | 
					
						
							|  |  |  |     remover2 && remover2(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     // handler1 and handler2 are added in different zone
 | 
					
						
							|  |  |  |     // one is angular zone, the other is not
 | 
					
						
							|  |  |  |     // should still be able to remove them correctly
 | 
					
						
							|  |  |  |     expect(receivedEvents).toEqual([]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should run blackListedEvents handler outside of ngZone', () => { | 
					
						
							|  |  |  |     const Zone = (window as any)['Zone']; | 
					
						
							|  |  |  |     const element = el('<div><div></div></div>'); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('scroll'); | 
					
						
							|  |  |  |     let receivedEvent: any /** TODO #9100 */ = null; | 
					
						
							|  |  |  |     let receivedZone: any = null; | 
					
						
							|  |  |  |     const handler = (e: any /** TODO #9100 */) => { | 
					
						
							|  |  |  |       receivedEvent = e; | 
					
						
							|  |  |  |       receivedZone = Zone.current; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], new FakeNgZone()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let remover = manager.addEventListener(element, 'scroll', handler); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvent).toBe(dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedZone.name).not.toEqual('angular'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     receivedEvent = null; | 
					
						
							|  |  |  |     remover && remover(); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(element, dispatchedEvent); | 
					
						
							|  |  |  |     expect(receivedEvent).toBe(null); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2019-05-17 20:50:02 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should only trigger one Change detection when bubbling', (done: DoneFn) => { | 
					
						
							|  |  |  |     doc = getDOM().supportsDOMEvents() ? document : getDOM().createHtmlDocument(); | 
					
						
							|  |  |  |     zone = new NgZone({shouldCoalesceEventChangeDetection: true}); | 
					
						
							|  |  |  |     domEventPlugin = new DomEventsPlugin(doc); | 
					
						
							|  |  |  |     const element = el('<div></div>'); | 
					
						
							|  |  |  |     const child = el('<div></div>'); | 
					
						
							|  |  |  |     element.appendChild(child); | 
					
						
							|  |  |  |     doc.body.appendChild(element); | 
					
						
							|  |  |  |     const dispatchedEvent = createMouseEvent('click'); | 
					
						
							|  |  |  |     let receivedEvents: any = []; | 
					
						
							|  |  |  |     let stables: any = []; | 
					
						
							|  |  |  |     const handler = (e: any) => { | 
					
						
							|  |  |  |       receivedEvents.push(e); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const manager = new EventManager([domEventPlugin], zone); | 
					
						
							|  |  |  |     let removerChild: any; | 
					
						
							|  |  |  |     let removerParent: any; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     zone.run(() => { | 
					
						
							|  |  |  |       removerChild = manager.addEventListener(child, 'click', handler); | 
					
						
							|  |  |  |       removerParent = manager.addEventListener(element, 'click', handler); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     zone.onStable.subscribe((isStable: any) => { | 
					
						
							|  |  |  |       stables.push(isStable); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     getDOM().dispatchEvent(child, dispatchedEvent); | 
					
						
							|  |  |  |     requestAnimationFrame(() => { | 
					
						
							|  |  |  |       expect(receivedEvents.length).toBe(2); | 
					
						
							|  |  |  |       expect(stables.length).toBe(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       removerChild && removerChild(); | 
					
						
							|  |  |  |       removerParent && removerParent(); | 
					
						
							|  |  |  |       done(); | 
					
						
							| 
									
										
										
										
											2019-05-17 20:50:02 +09:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2017-12-17 22:18:50 -08:00
										 |  |  | })(); | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:15:57 -07:00
										 |  |  | /** @internal */ | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | class FakeEventManagerPlugin extends EventManagerPlugin { | 
					
						
							| 
									
										
										
										
											2016-09-19 17:15:57 -07:00
										 |  |  |   eventHandler: {[event: string]: Function} = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   constructor(doc: any, public supportedEvents: string[]) { | 
					
						
							|  |  |  |     super(doc); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   supports(eventName: string): boolean { | 
					
						
							|  |  |  |     return this.supportedEvents.indexOf(eventName) > -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:15:57 -07:00
										 |  |  |   addEventListener(element: any, eventName: string, handler: Function) { | 
					
						
							|  |  |  |     this.eventHandler[eventName] = handler; | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     return () => { | 
					
						
							|  |  |  |       delete this.eventHandler[eventName]; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-08 13:33:22 -07:00
										 |  |  | class FakeNgZone extends NgZone { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   constructor() { | 
					
						
							|  |  |  |     super({enableLongStackTrace: false, shouldCoalesceEventChangeDetection: true}); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   run<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T { | 
					
						
							|  |  |  |     return fn(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   runOutsideAngular(fn: Function) { | 
					
						
							|  |  |  |     return fn(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-09 15:11:31 +01:00
										 |  |  | } |