Skip to content

Commit

Permalink
fix(overlays): update keyboard focus management
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Mar 6, 2016
1 parent 4922fc6 commit e639457
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 36 deletions.
39 changes: 21 additions & 18 deletions ionic/components/action-sheet/action-sheet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Component, Renderer, ElementRef} from 'angular2/core';
import {Component, Renderer, ElementRef, HostListener} from 'angular2/core';
import {NgFor, NgIf} from 'angular2/common';

import {Animation} from '../../animations/animation';
Expand Down Expand Up @@ -188,19 +188,18 @@ export class ActionSheet extends ViewController {
})
class ActionSheetCmp {
private d: any;
private keyUp: EventListener;

constructor(
private _viewCtrl: ViewController,
private _config: Config,
elementRef: ElementRef,
private _elementRef: ElementRef,
params: NavParams,
renderer: Renderer
) {
this.d = params.data;

if (this.d.cssClass) {
renderer.setElementClass(elementRef.nativeElement, this.d.cssClass, true);
renderer.setElementClass(_elementRef.nativeElement, this.d.cssClass, true);
}
}

Expand Down Expand Up @@ -234,16 +233,28 @@ class ActionSheetCmp {
});

this.d.buttons = buttons;
}

onPageDidEnter() {
let activeElement: any = document.activeElement;
if (document.activeElement) {
activeElement.blur();
}

let focusableEle = this._elementRef.nativeElement.querySelector('button');
if (focusableEle) {
focusableEle.focus();
}
}

let self = this;
self.keyUp = function(ev: KeyboardEvent) {
@HostListener('body:keyup', ['$event'])
private _keyUp(ev: KeyboardEvent) {
if (this._viewCtrl.isLast()) {
if (ev.keyCode === 27) {
console.debug('actionsheet escape');
self.bdClick();
this.bdClick();
}
};

document.addEventListener('keyup', this.keyUp);
}
}

click(button, dismissDelay?) {
Expand Down Expand Up @@ -278,14 +289,6 @@ class ActionSheetCmp {
dismiss(role): Promise<any> {
return this._viewCtrl.dismiss(null, role);
}

onPageWillLeave() {
document.removeEventListener('keyup', this.keyUp);
}

ngOnDestroy() {
document.removeEventListener('keyup', this.keyUp);
}
}

export interface ActionSheetOptions {
Expand Down
26 changes: 13 additions & 13 deletions ionic/components/alert/alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,14 +345,16 @@ class AlertCmp {

@HostListener('body:keyup', ['$event'])
private _keyUp(ev: KeyboardEvent) {
if (ev.keyCode === 13) {
console.debug('alert, enter button');
let button = this.d.buttons[this.d.buttons.length - 1];
this.btnClick(button);

} else if (ev.keyCode === 27) {
console.debug('alert, escape button');
this.bdClick();
if (this._viewCtrl.isLast()) {
if (ev.keyCode === 13) {
console.debug('alert, enter button');
let button = this.d.buttons[this.d.buttons.length - 1];
this.btnClick(button);

} else if (ev.keyCode === 27) {
console.debug('alert, escape button');
this.bdClick();
}
}
}

Expand All @@ -362,11 +364,9 @@ class AlertCmp {
activeElement.blur();
}

if (this.d.inputs.length) {
let firstInput = this._elementRef.nativeElement.querySelector('input');
if (firstInput) {
firstInput.focus();
}
let focusableEle = this._elementRef.nativeElement.querySelector('input,button');
if (focusableEle) {
focusableEle.focus();
}
}

Expand Down
4 changes: 2 additions & 2 deletions ionic/components/menu/menu-toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ export class MenuToggle {
*/
get isHidden() {
if (this._inNavbar && this._viewCtrl) {
if (this._viewCtrl.isRoot()) {
// this is the root view, so it should always show
if (this._viewCtrl.isFirst()) {
// this is the first view, so it should always show
return false;
}

Expand Down
14 changes: 14 additions & 0 deletions ionic/components/nav/test/nav-controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,21 +1077,35 @@ export function run() {
it('should get first()', () => {
expect(nav.first()).toBe(null);
let view1 = new ViewController(Page1);
view1.setNav(nav);
let view2 = new ViewController(Page2);
view2.setNav(nav);
nav._views = [view1];

expect(nav.first()).toBe(view1);
expect(view1.isFirst()).toBe(true);

nav._views = [view1, view2];
expect(nav.first()).toBe(view1);
expect(view1.isFirst()).toBe(true);
expect(view2.isFirst()).toBe(false);
});

it('should get last()', () => {
expect(nav.last()).toBe(null);
let view1 = new ViewController(Page1);
view1.setNav(nav);
let view2 = new ViewController(Page2);
view2.setNav(nav);
nav._views = [view1];

expect(nav.last()).toBe(view1);
expect(view1.isLast()).toBe(true);

nav._views = [view1, view2];
expect(nav.last()).toBe(view2);
expect(view1.isLast()).toBe(false);
expect(view2.isLast()).toBe(true);
});

it('should get indexOf()', () => {
Expand Down
22 changes: 19 additions & 3 deletions ionic/components/nav/view-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,26 @@ export class ViewController {
}

/**
* @returns {boolean} Returns if this Page is the root page of the NavController.
* @private
*/
private isRoot(): boolean {
// deprecated warning
console.warn('ViewController isRoot() has been renamed to isFirst()');
return this.isFirst();
}

/**
* @returns {boolean} Returns if this Page is the first in the stack of pages within its NavController.
*/
isFirst(): boolean {
return (this._nav ? this._nav.first() === this : false);
}

/**
* @returns {boolean} Returns if this Page is the last in the stack of pages within its NavController.
*/
isRoot(): boolean {
return (this.index === 0);
isLast(): boolean {
return (this._nav ? this._nav.last() === this : false);
}

/**
Expand Down

0 comments on commit e639457

Please sign in to comment.