mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-21 04:53:58 +08:00
fix(overlays): update keyboard focus management
This commit is contained in:
@ -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 {NgFor, NgIf} from 'angular2/common';
|
||||||
|
|
||||||
import {Animation} from '../../animations/animation';
|
import {Animation} from '../../animations/animation';
|
||||||
@ -188,19 +188,18 @@ export class ActionSheet extends ViewController {
|
|||||||
})
|
})
|
||||||
class ActionSheetCmp {
|
class ActionSheetCmp {
|
||||||
private d: any;
|
private d: any;
|
||||||
private keyUp: EventListener;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _viewCtrl: ViewController,
|
private _viewCtrl: ViewController,
|
||||||
private _config: Config,
|
private _config: Config,
|
||||||
elementRef: ElementRef,
|
private _elementRef: ElementRef,
|
||||||
params: NavParams,
|
params: NavParams,
|
||||||
renderer: Renderer
|
renderer: Renderer
|
||||||
) {
|
) {
|
||||||
this.d = params.data;
|
this.d = params.data;
|
||||||
|
|
||||||
if (this.d.cssClass) {
|
if (this.d.cssClass) {
|
||||||
renderer.setElementClass(elementRef.nativeElement, this.d.cssClass, true);
|
renderer.setElementClass(_elementRef.nativeElement, this.d.cssClass, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,16 +233,28 @@ class ActionSheetCmp {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.d.buttons = buttons;
|
this.d.buttons = buttons;
|
||||||
|
}
|
||||||
|
|
||||||
let self = this;
|
onPageDidEnter() {
|
||||||
self.keyUp = function(ev: KeyboardEvent) {
|
let activeElement: any = document.activeElement;
|
||||||
|
if (document.activeElement) {
|
||||||
|
activeElement.blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
let focusableEle = this._elementRef.nativeElement.querySelector('button');
|
||||||
|
if (focusableEle) {
|
||||||
|
focusableEle.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('body:keyup', ['$event'])
|
||||||
|
private _keyUp(ev: KeyboardEvent) {
|
||||||
|
if (this._viewCtrl.isLast()) {
|
||||||
if (ev.keyCode === 27) {
|
if (ev.keyCode === 27) {
|
||||||
console.debug('actionsheet escape');
|
console.debug('actionsheet escape');
|
||||||
self.bdClick();
|
this.bdClick();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener('keyup', this.keyUp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
click(button, dismissDelay?) {
|
click(button, dismissDelay?) {
|
||||||
@ -278,14 +289,6 @@ class ActionSheetCmp {
|
|||||||
dismiss(role): Promise<any> {
|
dismiss(role): Promise<any> {
|
||||||
return this._viewCtrl.dismiss(null, role);
|
return this._viewCtrl.dismiss(null, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPageWillLeave() {
|
|
||||||
document.removeEventListener('keyup', this.keyUp);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
document.removeEventListener('keyup', this.keyUp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ActionSheetOptions {
|
export interface ActionSheetOptions {
|
||||||
|
@ -345,6 +345,7 @@ class AlertCmp {
|
|||||||
|
|
||||||
@HostListener('body:keyup', ['$event'])
|
@HostListener('body:keyup', ['$event'])
|
||||||
private _keyUp(ev: KeyboardEvent) {
|
private _keyUp(ev: KeyboardEvent) {
|
||||||
|
if (this._viewCtrl.isLast()) {
|
||||||
if (ev.keyCode === 13) {
|
if (ev.keyCode === 13) {
|
||||||
console.debug('alert, enter button');
|
console.debug('alert, enter button');
|
||||||
let button = this.d.buttons[this.d.buttons.length - 1];
|
let button = this.d.buttons[this.d.buttons.length - 1];
|
||||||
@ -355,6 +356,7 @@ class AlertCmp {
|
|||||||
this.bdClick();
|
this.bdClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onPageDidEnter() {
|
onPageDidEnter() {
|
||||||
let activeElement: any = document.activeElement;
|
let activeElement: any = document.activeElement;
|
||||||
@ -362,11 +364,9 @@ class AlertCmp {
|
|||||||
activeElement.blur();
|
activeElement.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.d.inputs.length) {
|
let focusableEle = this._elementRef.nativeElement.querySelector('input,button');
|
||||||
let firstInput = this._elementRef.nativeElement.querySelector('input');
|
if (focusableEle) {
|
||||||
if (firstInput) {
|
focusableEle.focus();
|
||||||
firstInput.focus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +68,8 @@ export class MenuToggle {
|
|||||||
*/
|
*/
|
||||||
get isHidden() {
|
get isHidden() {
|
||||||
if (this._inNavbar && this._viewCtrl) {
|
if (this._inNavbar && this._viewCtrl) {
|
||||||
if (this._viewCtrl.isRoot()) {
|
if (this._viewCtrl.isFirst()) {
|
||||||
// this is the root view, so it should always show
|
// this is the first view, so it should always show
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,21 +1077,35 @@ export function run() {
|
|||||||
it('should get first()', () => {
|
it('should get first()', () => {
|
||||||
expect(nav.first()).toBe(null);
|
expect(nav.first()).toBe(null);
|
||||||
let view1 = new ViewController(Page1);
|
let view1 = new ViewController(Page1);
|
||||||
|
view1.setNav(nav);
|
||||||
let view2 = new ViewController(Page2);
|
let view2 = new ViewController(Page2);
|
||||||
|
view2.setNav(nav);
|
||||||
nav._views = [view1];
|
nav._views = [view1];
|
||||||
|
|
||||||
expect(nav.first()).toBe(view1);
|
expect(nav.first()).toBe(view1);
|
||||||
|
expect(view1.isFirst()).toBe(true);
|
||||||
|
|
||||||
nav._views = [view1, view2];
|
nav._views = [view1, view2];
|
||||||
expect(nav.first()).toBe(view1);
|
expect(nav.first()).toBe(view1);
|
||||||
|
expect(view1.isFirst()).toBe(true);
|
||||||
|
expect(view2.isFirst()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get last()', () => {
|
it('should get last()', () => {
|
||||||
expect(nav.last()).toBe(null);
|
expect(nav.last()).toBe(null);
|
||||||
let view1 = new ViewController(Page1);
|
let view1 = new ViewController(Page1);
|
||||||
|
view1.setNav(nav);
|
||||||
let view2 = new ViewController(Page2);
|
let view2 = new ViewController(Page2);
|
||||||
|
view2.setNav(nav);
|
||||||
nav._views = [view1];
|
nav._views = [view1];
|
||||||
|
|
||||||
expect(nav.last()).toBe(view1);
|
expect(nav.last()).toBe(view1);
|
||||||
|
expect(view1.isLast()).toBe(true);
|
||||||
|
|
||||||
nav._views = [view1, view2];
|
nav._views = [view1, view2];
|
||||||
expect(nav.last()).toBe(view2);
|
expect(nav.last()).toBe(view2);
|
||||||
|
expect(view1.isLast()).toBe(false);
|
||||||
|
expect(view2.isLast()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get indexOf()', () => {
|
it('should get indexOf()', () => {
|
||||||
|
@ -189,10 +189,26 @@ export class ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {boolean} Returns if this Page is the root page of the NavController.
|
* @private
|
||||||
*/
|
*/
|
||||||
isRoot(): boolean {
|
private isRoot(): boolean {
|
||||||
return (this.index === 0);
|
// 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.
|
||||||
|
*/
|
||||||
|
isLast(): boolean {
|
||||||
|
return (this._nav ? this._nav.last() === this : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user