Skip to content

Commit e639457

Browse files
committed
fix(overlays): update keyboard focus management
1 parent 4922fc6 commit e639457

File tree

5 files changed

+69
-36
lines changed

5 files changed

+69
-36
lines changed

ionic/components/action-sheet/action-sheet.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, Renderer, ElementRef} from 'angular2/core';
1+
import {Component, Renderer, ElementRef, HostListener} from 'angular2/core';
22
import {NgFor, NgIf} from 'angular2/common';
33

44
import {Animation} from '../../animations/animation';
@@ -188,19 +188,18 @@ export class ActionSheet extends ViewController {
188188
})
189189
class ActionSheetCmp {
190190
private d: any;
191-
private keyUp: EventListener;
192191

193192
constructor(
194193
private _viewCtrl: ViewController,
195194
private _config: Config,
196-
elementRef: ElementRef,
195+
private _elementRef: ElementRef,
197196
params: NavParams,
198197
renderer: Renderer
199198
) {
200199
this.d = params.data;
201200

202201
if (this.d.cssClass) {
203-
renderer.setElementClass(elementRef.nativeElement, this.d.cssClass, true);
202+
renderer.setElementClass(_elementRef.nativeElement, this.d.cssClass, true);
204203
}
205204
}
206205

@@ -234,16 +233,28 @@ class ActionSheetCmp {
234233
});
235234

236235
this.d.buttons = buttons;
236+
}
237+
238+
onPageDidEnter() {
239+
let activeElement: any = document.activeElement;
240+
if (document.activeElement) {
241+
activeElement.blur();
242+
}
243+
244+
let focusableEle = this._elementRef.nativeElement.querySelector('button');
245+
if (focusableEle) {
246+
focusableEle.focus();
247+
}
248+
}
237249

238-
let self = this;
239-
self.keyUp = function(ev: KeyboardEvent) {
250+
@HostListener('body:keyup', ['$event'])
251+
private _keyUp(ev: KeyboardEvent) {
252+
if (this._viewCtrl.isLast()) {
240253
if (ev.keyCode === 27) {
241254
console.debug('actionsheet escape');
242-
self.bdClick();
255+
this.bdClick();
243256
}
244-
};
245-
246-
document.addEventListener('keyup', this.keyUp);
257+
}
247258
}
248259

249260
click(button, dismissDelay?) {
@@ -278,14 +289,6 @@ class ActionSheetCmp {
278289
dismiss(role): Promise<any> {
279290
return this._viewCtrl.dismiss(null, role);
280291
}
281-
282-
onPageWillLeave() {
283-
document.removeEventListener('keyup', this.keyUp);
284-
}
285-
286-
ngOnDestroy() {
287-
document.removeEventListener('keyup', this.keyUp);
288-
}
289292
}
290293

291294
export interface ActionSheetOptions {

ionic/components/alert/alert.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -345,14 +345,16 @@ class AlertCmp {
345345

346346
@HostListener('body:keyup', ['$event'])
347347
private _keyUp(ev: KeyboardEvent) {
348-
if (ev.keyCode === 13) {
349-
console.debug('alert, enter button');
350-
let button = this.d.buttons[this.d.buttons.length - 1];
351-
this.btnClick(button);
352-
353-
} else if (ev.keyCode === 27) {
354-
console.debug('alert, escape button');
355-
this.bdClick();
348+
if (this._viewCtrl.isLast()) {
349+
if (ev.keyCode === 13) {
350+
console.debug('alert, enter button');
351+
let button = this.d.buttons[this.d.buttons.length - 1];
352+
this.btnClick(button);
353+
354+
} else if (ev.keyCode === 27) {
355+
console.debug('alert, escape button');
356+
this.bdClick();
357+
}
356358
}
357359
}
358360

@@ -362,11 +364,9 @@ class AlertCmp {
362364
activeElement.blur();
363365
}
364366

365-
if (this.d.inputs.length) {
366-
let firstInput = this._elementRef.nativeElement.querySelector('input');
367-
if (firstInput) {
368-
firstInput.focus();
369-
}
367+
let focusableEle = this._elementRef.nativeElement.querySelector('input,button');
368+
if (focusableEle) {
369+
focusableEle.focus();
370370
}
371371
}
372372

ionic/components/menu/menu-toggle.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ export class MenuToggle {
6868
*/
6969
get isHidden() {
7070
if (this._inNavbar && this._viewCtrl) {
71-
if (this._viewCtrl.isRoot()) {
72-
// this is the root view, so it should always show
71+
if (this._viewCtrl.isFirst()) {
72+
// this is the first view, so it should always show
7373
return false;
7474
}
7575

ionic/components/nav/test/nav-controller.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,21 +1077,35 @@ export function run() {
10771077
it('should get first()', () => {
10781078
expect(nav.first()).toBe(null);
10791079
let view1 = new ViewController(Page1);
1080+
view1.setNav(nav);
10801081
let view2 = new ViewController(Page2);
1082+
view2.setNav(nav);
10811083
nav._views = [view1];
1084+
10821085
expect(nav.first()).toBe(view1);
1086+
expect(view1.isFirst()).toBe(true);
1087+
10831088
nav._views = [view1, view2];
10841089
expect(nav.first()).toBe(view1);
1090+
expect(view1.isFirst()).toBe(true);
1091+
expect(view2.isFirst()).toBe(false);
10851092
});
10861093

10871094
it('should get last()', () => {
10881095
expect(nav.last()).toBe(null);
10891096
let view1 = new ViewController(Page1);
1097+
view1.setNav(nav);
10901098
let view2 = new ViewController(Page2);
1099+
view2.setNav(nav);
10911100
nav._views = [view1];
1101+
10921102
expect(nav.last()).toBe(view1);
1103+
expect(view1.isLast()).toBe(true);
1104+
10931105
nav._views = [view1, view2];
10941106
expect(nav.last()).toBe(view2);
1107+
expect(view1.isLast()).toBe(false);
1108+
expect(view2.isLast()).toBe(true);
10951109
});
10961110

10971111
it('should get indexOf()', () => {

ionic/components/nav/view-controller.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,26 @@ export class ViewController {
189189
}
190190

191191
/**
192-
* @returns {boolean} Returns if this Page is the root page of the NavController.
192+
* @private
193+
*/
194+
private isRoot(): boolean {
195+
// deprecated warning
196+
console.warn('ViewController isRoot() has been renamed to isFirst()');
197+
return this.isFirst();
198+
}
199+
200+
/**
201+
* @returns {boolean} Returns if this Page is the first in the stack of pages within its NavController.
202+
*/
203+
isFirst(): boolean {
204+
return (this._nav ? this._nav.first() === this : false);
205+
}
206+
207+
/**
208+
* @returns {boolean} Returns if this Page is the last in the stack of pages within its NavController.
193209
*/
194-
isRoot(): boolean {
195-
return (this.index === 0);
210+
isLast(): boolean {
211+
return (this._nav ? this._nav.last() === this : false);
196212
}
197213

198214
/**

0 commit comments

Comments
 (0)