fix(overlay): OverlayKeyboardDispatcher not dispatching events when propagation is stopped (#9546)

Uses event capturing to ensure that we can dispatch events to the overlays even if bubbling was interrupted.
This commit is contained in:
Kristiyan Kostadinov
2018-02-01 23:18:49 +01:00
committed by tinayuangao
parent 085d8056ae
commit e30852aa4c
2 changed files with 20 additions and 3 deletions
@@ -69,6 +69,23 @@ describe('OverlayKeyboardDispatcher', () => {
expect(overlayTwoSpy).toHaveBeenCalled();
});
it('should dispatch keyboard events when propagation is stopped', () => {
const overlayRef = overlay.create();
const spy = jasmine.createSpy('keyboard event spy');
const button = document.createElement('button');
document.body.appendChild(button);
button.addEventListener('keydown', event => event.stopPropagation());
overlayRef.keydownEvents().subscribe(spy);
keyboardDispatcher.add(overlayRef);
dispatchKeyboardEvent(button, 'keydown', ESCAPE);
expect(spy).toHaveBeenCalled();
button.parentNode!.removeChild(button);
});
it('should dispatch targeted keyboard events to the overlay containing that target', () => {
const overlayOne = overlay.create();
const overlayTwo = overlay.create();
@@ -61,12 +61,12 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
* events to the appropriate overlay.
*/
private _subscribeToKeydownEvents(): void {
const bodyKeydownEvents = fromEvent<KeyboardEvent>(this._document.body, 'keydown');
const bodyKeydownEvents = fromEvent<KeyboardEvent>(this._document.body, 'keydown', true);
this._keydownEventSubscription = bodyKeydownEvents.pipe(
filter(() => !!this._attachedOverlays.length)
).subscribe(event => {
// Dispatch keydown event to correct overlay reference
// Dispatch keydown event to the correct overlay.
this._selectOverlayFromEvent(event)._keydownEvents.next(event);
});
}
@@ -87,7 +87,7 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
overlay.overlayElement.contains(event.target as HTMLElement);
});
// Use that overlay if it exists, otherwise choose the most recently attached one
// Use the overlay if it exists, otherwise choose the most recently attached one
return targetedOverlay || this._attachedOverlays[this._attachedOverlays.length - 1];
}