MOBILE-3749 a11y: Repair autofocus directive
parent
a8c40ff1d0
commit
c3d0e39c3e
|
@ -58,7 +58,7 @@
|
|||
<ion-label position="stacked">{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>
|
||||
<core-show-password name="password">
|
||||
<ion-input name="password" type="password" placeholder="{{ 'core.login.password' | translate }}"
|
||||
[autofocus]="true" #passwordinput [clearOnEdit]="false">
|
||||
core-auto-focus #passwordinput [clearOnEdit]="false">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
</ion-item>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<ion-label>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>
|
||||
<core-show-password name="password">
|
||||
<ion-input name="password" type="password" placeholder="{{ 'core.login.password' | translate }}"
|
||||
[autofocus]="true" #passwordinput [clearOnEdit]="false">
|
||||
core-auto-focus #passwordinput [clearOnEdit]="false">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
</ion-item>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<!-- Form to edit the file's name. -->
|
||||
<ion-input type="text" name="filename" [placeholder]="'core.filename' | translate" autocapitalize="none" autocorrect="off"
|
||||
(click)="$event.stopPropagation()" [autofocus]="true" [(ngModel)]="newFileName" *ngIf="editMode">
|
||||
(click)="$event.stopPropagation()" core-auto-focus [(ngModel)]="newFileName" *ngIf="editMode">
|
||||
</ion-input>
|
||||
|
||||
<div class="buttons" slot="end" *ngIf="manage">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<form #messageForm>
|
||||
<textarea class="core-send-message-input" [autofocus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows
|
||||
<textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows
|
||||
[(ngModel)]="message" name="message" (onResize)="textareaResized()" (keyup.enter)="enterClicked($event)"
|
||||
(keyup.control.enter)="enterClicked($event, 'control')" (keyup.meta.enter)="enterClicked($event, 'meta')"></textarea>
|
||||
<ion-button fill="clear" size="large" type="submit" [disabled]="!message || sendDisabled"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
import { Directive, Input, ElementRef, AfterViewInit } from '@angular/core';
|
||||
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
@ -20,16 +20,17 @@ import { CoreUtils } from '@services/utils/utils';
|
|||
/**
|
||||
* Directive to auto focus an element when a view is loaded.
|
||||
*
|
||||
* You can apply it conditionallity assigning it a boolean value: <ion-input [core-auto-focus]="{{showKeyboard}}">
|
||||
* The value of the input will decide if show keyboard when focusing the element (only on Android).
|
||||
* In case value is nofocus, the directive is disabled.
|
||||
*
|
||||
* @deprecated since 3.9.5. ion-input now supports an [autofocus] attribute, please use that one instead.
|
||||
* <ion-input [core-auto-focus]="showKeyboard">
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[core-auto-focus]',
|
||||
})
|
||||
export class CoreAutoFocusDirective implements OnInit {
|
||||
export class CoreAutoFocusDirective implements AfterViewInit {
|
||||
|
||||
@Input('core-auto-focus') coreAutoFocus: boolean | string = true;
|
||||
@Input('core-auto-focus') showKeyboard: boolean | string = true;
|
||||
|
||||
protected element: HTMLElement;
|
||||
|
||||
|
@ -38,31 +39,54 @@ export class CoreAutoFocusDirective implements OnInit {
|
|||
}
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.autoFocus();
|
||||
ngAfterViewInit(): void {
|
||||
if (this.showKeyboard === 'nofocus') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function after the view is initialized.
|
||||
* Function to focus the element.
|
||||
*
|
||||
* @param retries Internal param to stop retrying then 0.
|
||||
*/
|
||||
protected autoFocus(): void {
|
||||
const autoFocus = CoreUtils.isTrueOrOne(this.coreAutoFocus);
|
||||
if (autoFocus) {
|
||||
// Wait a bit to make sure the view is loaded.
|
||||
setTimeout(() => {
|
||||
// If it's a ion-input or ion-textarea, search the right input to use.
|
||||
let element = this.element;
|
||||
if (this.element.tagName == 'ION-INPUT') {
|
||||
element = this.element.querySelector('input') || element;
|
||||
} else if (this.element.tagName == 'ION-TEXTAREA') {
|
||||
element = this.element.querySelector('textarea') || element;
|
||||
}
|
||||
|
||||
CoreDomUtils.focusElement(element);
|
||||
}, 200);
|
||||
protected setFocus(retries = 10): void {
|
||||
if (retries == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait a bit to make sure the view is loaded.
|
||||
setTimeout(() => {
|
||||
// If it's a ion-input or ion-textarea, search the right input to use.
|
||||
let element: HTMLElement | null = null;
|
||||
|
||||
if (this.element.tagName == 'ION-INPUT') {
|
||||
element = this.element.querySelector('input');
|
||||
} else if (this.element.tagName == 'ION-TEXTAREA') {
|
||||
element = this.element.querySelector('textarea');
|
||||
} else {
|
||||
element = this.element;
|
||||
}
|
||||
|
||||
if (!element) {
|
||||
this.setFocus(retries - 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const showKeyboard = this.showKeyboard === '' || CoreUtils.isTrueOrOne(this.showKeyboard);
|
||||
CoreDomUtils.focusElement(element, showKeyboard);
|
||||
|
||||
if (element != document.activeElement) {
|
||||
this.setFocus(retries - 1);
|
||||
|
||||
return;
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
type="password"
|
||||
placeholder="{{ 'core.courses.password' | translate }}"
|
||||
[(ngModel)]="password"
|
||||
[autofocus]="true"
|
||||
core-auto-focus
|
||||
[clearOnEdit]="false">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<ion-label></ion-label>
|
||||
<ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}"
|
||||
formControlName="username" autocapitalize="none" autocorrect="off" autocomplete="username" enterkeyhint="next"
|
||||
required="true">
|
||||
required="true" core-auto-focus>
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-item *ngIf="siteChecked && !isBrowserSSO" class="ion-margin-bottom">
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<ion-item>
|
||||
<ion-label></ion-label>
|
||||
<ion-input type="text" name="value" placeholder="{{ 'core.login.usernameoremail' | translate }}"
|
||||
formControlName="value" autocapitalize="none" autocorrect="off" [autofocus]="autoFocus">
|
||||
formControlName="value" autocapitalize="none" autocorrect="off" [core-auto-focus]="showKeyboard">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-button type="submit" class="ion-margin" expand="block" [disabled]="!myForm.valid">
|
||||
|
|
|
@ -35,7 +35,7 @@ export class CoreLoginForgottenPasswordPage implements OnInit {
|
|||
|
||||
myForm!: FormGroup;
|
||||
siteUrl!: string;
|
||||
autoFocus!: boolean;
|
||||
showKeyboard!: boolean;
|
||||
|
||||
constructor(
|
||||
protected formBuilder: FormBuilder,
|
||||
|
@ -55,7 +55,7 @@ export class CoreLoginForgottenPasswordPage implements OnInit {
|
|||
}
|
||||
|
||||
this.siteUrl = siteUrl;
|
||||
this.autoFocus = Platform.is('tablet');
|
||||
this.showKeyboard = Platform.is('tablet');
|
||||
this.myForm = this.formBuilder.group({
|
||||
field: ['username', Validators.required],
|
||||
value: [CoreNavigator.getRouteParam<string>('username') || '', Validators.required],
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<core-show-password name="password">
|
||||
<ion-input class="core-ioninput-password" name="password" type="password"
|
||||
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
|
||||
autocomplete="current-password" enterkeyhint="go" required="true">
|
||||
autocomplete="current-password" enterkeyhint="go" required="true" core-auto-focus>
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
</ion-item>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<h2>{{ 'core.login.siteaddress' | translate }}</h2>
|
||||
</ion-label>
|
||||
<ion-input name="url" type="url" placeholder="{{ 'core.login.siteaddressplaceholder' | translate }}"
|
||||
formControlName="siteUrl" [autofocus]="showKeyboard && !showScanQR">
|
||||
formControlName="siteUrl" [core-auto-focus]="showKeyboard">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<h2>{{ 'core.login.siteaddress' | translate }}</h2>
|
||||
</ion-label>
|
||||
<ion-input name="url" placeholder="{{ 'core.login.siteaddressplaceholder' | translate }}" formControlName="siteUrl"
|
||||
[autofocus]="showKeyboard && !showScanQR" (ionChange)="searchSite($event, siteForm.value.siteUrl)">
|
||||
[core-auto-focus]="showKeyboard" (ionChange)="searchSite($event, siteForm.value.siteUrl)">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<ion-item>
|
||||
<ion-label></ion-label>
|
||||
<ion-input type="search" name="search" [(ngModel)]="searchText" [placeholder]="placeholder"
|
||||
[autocorrect]="autocorrect" [spellcheck]="spellcheck" [autofocus]="autoFocus"
|
||||
[autocorrect]="autocorrect" [spellcheck]="spellcheck" [core-auto-focus]="autoFocus || 'nofocus'"
|
||||
[disabled]="disabled" role="searchbox" (ionFocus)="focus($event)">
|
||||
</ion-input>
|
||||
<ion-button slot="end" fill="clear" type="submit" size="small" [attr.aria-label]="searchLabel"
|
||||
|
|
|
@ -391,11 +391,12 @@ export class CoreDomUtilsProvider {
|
|||
* Focus an element and open keyboard.
|
||||
*
|
||||
* @param el HTML element to focus.
|
||||
* @param showKeyboard Show keyboard when focusing the element.
|
||||
*/
|
||||
focusElement(el: HTMLElement): void {
|
||||
focusElement(el: HTMLElement, showKeyboard = true): void {
|
||||
if (el?.focus) {
|
||||
el.focus();
|
||||
if (CoreApp.isAndroid() && this.supportsInputKeyboard(el)) {
|
||||
if (showKeyboard && CoreApp.isAndroid() && this.supportsInputKeyboard(el)) {
|
||||
// On some Android versions the keyboard doesn't open automatically.
|
||||
CoreApp.openKeyboard();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue