Skip to content

Commit

Permalink
fix(menu): not closing on escape when opened by mouse
Browse files Browse the repository at this point in the history
Fixes `md-menu` not closing when escape is pressed, if it was opened by a mouse click. The old behavior seemed to only be targeted towards keyboard users, however the escape key can also be considered a convenience feature.
  • Loading branch information
crisbeto committed May 27, 2017
1 parent 12d6e96 commit d2e11a8
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 17 deletions.
16 changes: 3 additions & 13 deletions src/lib/menu/menu-directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {FocusKeyManager} from '../core/a11y/focus-key-manager';
import {MdMenuPanel} from './menu-panel';
import {Subscription} from 'rxjs/Subscription';
import {transformMenu, fadeInItems} from './menu-animations';
import {ESCAPE} from '../core/keyboard/keycodes';


@Component({
Expand All @@ -37,13 +36,15 @@ import {ESCAPE} from '../core/keyboard/keycodes';
exportAs: 'mdMenu'
})
export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
private _keyManager: FocusKeyManager;
private _xPosition: MenuPositionX = 'after';
private _yPosition: MenuPositionY = 'below';

/** Subscription to tab events on the menu panel */
private _tabSubscription: Subscription;

/** Manages keyboard events inside the panel. */
_keyManager: FocusKeyManager;

/** Config object to be passed into the menu's ngClass */
_classList: any = {};

Expand Down Expand Up @@ -106,17 +107,6 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
}
}

/** Handle a keyboard event from the menu, delegating to the appropriate action. */
_handleKeydown(event: KeyboardEvent) {
switch (event.keyCode) {
case ESCAPE:
this._emitCloseEvent();
return;
default:
this._keyManager.onKeydown(event);
}
}

/**
* Focus the first item in the menu. This method is used by the menu trigger
* to focus the first item when the menu is opened by the ENTER key.
Expand Down
18 changes: 17 additions & 1 deletion src/lib/menu/menu-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Optional,
Output,
ViewContainerRef,
Renderer2,
} from '@angular/core';
import {MdMenuPanel} from './menu-panel';
import {throwMdMenuMissingError} from './menu-errors';
Expand All @@ -24,6 +25,7 @@ import {
VerticalConnectionPos,
RepositionScrollStrategy,
ScrollDispatcher,
ESCAPE,
} from '../core';
import {Subscription} from 'rxjs/Subscription';
import {MenuPositionX, MenuPositionY} from './menu-positions';
Expand All @@ -50,6 +52,7 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
private _menuOpen: boolean = false;
private _backdropSubscription: Subscription;
private _positionSubscription: Subscription;
private _globalKeydownHandler: () => void;

// tracking input type is necessary so it's possible to only auto-focus
// the first item of the list when the menu is opened via the keyboard
Expand Down Expand Up @@ -81,7 +84,7 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {

constructor(private _overlay: Overlay, private _element: ElementRef,
private _viewContainerRef: ViewContainerRef, @Optional() private _dir: Dir,
private _scrollDispatcher: ScrollDispatcher) { }
private _scrollDispatcher: ScrollDispatcher, private _renderer: Renderer2) { }

ngAfterViewInit() {
this._checkMenu();
Expand All @@ -104,6 +107,14 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
this._createOverlay();
this._overlayRef.attach(this._portal);
this._subscribeToBackdrop();

this._globalKeydownHandler = this._renderer.listen('document', 'keydown',
(event: KeyboardEvent) => {
if (event.keyCode === ESCAPE) {
this.closeMenu();
}
});

this._initMenu();
}
}
Expand All @@ -114,6 +125,11 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
this._overlayRef.detach();
this._backdropSubscription.unsubscribe();
this._resetMenu();

if (this._globalKeydownHandler) {
this._globalKeydownHandler();
this._globalKeydownHandler = null;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/menu/menu.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<ng-template>
<div class="mat-menu-panel" [ngClass]="_classList" (keydown)="_handleKeydown($event)"
<div class="mat-menu-panel" [ngClass]="_classList" (keydown)="_keyManager.onKeydown($event)"
(click)="_emitCloseEvent()" [@transformMenu]="'showing'">
<div class="mat-menu-content" [@fadeInItems]="'showing'">
<ng-content></ng-content>
Expand Down
3 changes: 1 addition & 2 deletions src/lib/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ describe('MdMenu', () => {
fixture.detectChanges();
fixture.componentInstance.trigger.openMenu();

const panel = overlayContainerElement.querySelector('.mat-menu-panel');
dispatchKeyboardEvent(panel, 'keydown', ESCAPE);
dispatchKeyboardEvent(document, 'keydown', ESCAPE);
fixture.detectChanges();

expect(overlayContainerElement.textContent).toBe('');
Expand Down

0 comments on commit d2e11a8

Please sign in to comment.