From 3e6cc7719ae4708f74b8cd6ea1fae5f0b6d231c7 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 25 Oct 2018 17:15:35 +0200 Subject: [PATCH] fix(expansion-panel): don't handle enter/space if modifier is pressed (#13790) Doesn't `preventDefault` and handle the enter and space key presses if the user is pressing any of the modifier keys. Fixes #13783. --- src/cdk/testing/event-objects.ts | 9 ++++++--- src/lib/expansion/expansion-panel-header.ts | 7 +++++-- src/lib/expansion/expansion.spec.ts | 20 +++++++++++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/cdk/testing/event-objects.ts b/src/cdk/testing/event-objects.ts index 8806e5b5adc3..4f57a121d6d8 100644 --- a/src/cdk/testing/event-objects.ts +++ b/src/cdk/testing/event-objects.ts @@ -56,11 +56,14 @@ export function createTouchEvent(type: string, pageX = 0, pageY = 0) { /** Dispatches a keydown event from an element. */ export function createKeyboardEvent(type: string, keyCode: number, target?: Element, key?: string) { let event = document.createEvent('KeyboardEvent') as any; - // Firefox does not support `initKeyboardEvent`, but supports `initKeyEvent`. - let initEventFn = (event.initKeyEvent || event.initKeyboardEvent).bind(event); let originalPreventDefault = event.preventDefault; - initEventFn(type, true, true, window, 0, 0, 0, 0, 0, keyCode); + // Firefox does not support `initKeyboardEvent`, but supports `initKeyEvent`. + if (event.initKeyEvent) { + event.initKeyEvent(type, true, true, window, 0, 0, 0, 0, 0, keyCode); + } else { + event.initKeyboardEvent(type, true, true, window, 0, key, 0, '', false); + } // Webkit Browsers don't set the keyCode when calling the init function. // See related bug https://bugs.webkit.org/show_bug.cgi?id=16735 diff --git a/src/lib/expansion/expansion-panel-header.ts b/src/lib/expansion/expansion-panel-header.ts index 387725bb1249..26a3665f4509 100644 --- a/src/lib/expansion/expansion-panel-header.ts +++ b/src/lib/expansion/expansion-panel-header.ts @@ -140,8 +140,11 @@ export class MatExpansionPanelHeader implements OnDestroy, FocusableOption { // Toggle for space and enter keys. case SPACE: case ENTER: - event.preventDefault(); - this._toggle(); + if (!event.altKey && !event.metaKey && !event.shiftKey && !event.ctrlKey) { + event.preventDefault(); + this._toggle(); + } + break; default: if (this.panel.accordion) { diff --git a/src/lib/expansion/expansion.spec.ts b/src/lib/expansion/expansion.spec.ts index c80c0aad92da..5bd804c60336 100644 --- a/src/lib/expansion/expansion.spec.ts +++ b/src/lib/expansion/expansion.spec.ts @@ -4,7 +4,7 @@ import {By} from '@angular/platform-browser'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {MatExpansionModule, MatExpansionPanel} from './index'; import {SPACE, ENTER} from '@angular/cdk/keycodes'; -import {dispatchKeyboardEvent} from '@angular/cdk/testing'; +import {dispatchKeyboardEvent, createKeyboardEvent, dispatchEvent} from '@angular/cdk/testing'; describe('MatExpansionPanel', () => { @@ -139,6 +139,24 @@ describe('MatExpansionPanel', () => { expect(event.defaultPrevented).toBe(true); }); + it('should not toggle if a modifier key is pressed', () => { + const fixture = TestBed.createComponent(PanelWithContent); + const headerEl = fixture.nativeElement.querySelector('.mat-expansion-panel-header'); + + spyOn(fixture.componentInstance.panel, 'toggle'); + + ['altKey', 'metaKey', 'shiftKey', 'ctrlKey'].forEach(modifier => { + const event = createKeyboardEvent('keydown', ENTER); + Object.defineProperty(event, modifier, {get: () => true}); + + dispatchEvent(headerEl, event); + fixture.detectChanges(); + + expect(fixture.componentInstance.panel.toggle).not.toHaveBeenCalled(); + expect(event.defaultPrevented).toBe(false); + }); + }); + it('should not be able to focus content while closed', fakeAsync(() => { const fixture = TestBed.createComponent(PanelWithContent); fixture.componentInstance.expanded = true;