MOBILE-2508 core: Implement and apply supress events directive

main
Dani Palou 2018-08-06 08:51:15 +02:00
parent e6c5607463
commit a2614eda26
7 changed files with 122 additions and 12 deletions

View File

@ -1,7 +1,7 @@
<form (ngSubmit)="submitForm($event)"> <form>
<textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows [(ngModel)]="message" name="message" (onResize)="textareaResized()"></textarea> <textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows [(ngModel)]="message" name="message" (onResize)="textareaResized()"></textarea>
<ion-buttons end> <ion-buttons end>
<button ion-button icon-only clear="true" type="submit" [disabled]="!message" [attr.aria-label]="'core.send' | translate"> <button ion-button icon-only clear="true" type="submit" [disabled]="!message" [attr.aria-label]="'core.send' | translate" [core-suppress-events] (onClick)="submitForm($event)">
<ion-icon name="send" color="dark"></ion-icon> <ion-icon name="send" color="dark"></ion-icon>
</button> </button>
</ion-buttons> </ion-buttons>

View File

@ -48,20 +48,22 @@ export class CoreSendMessageFormComponent implements OnInit {
/** /**
* Form submitted. * Form submitted.
* @param {any} $event Form submit *
* @param {Event} $event Mouse event.
*/ */
submitForm($event: any): void { submitForm($event: Event): void {
let value = this.message.trim(); $event.preventDefault();
$event.target.reset(); $event.stopPropagation();
// Focus again on textarea. let value = this.message.trim();
$event.target[0].focus();
if (!value) { if (!value) {
// Silent error. // Silent error.
return; return;
} }
this.message = ''; // Reset the form.
value = this.textUtils.replaceNewLines(value, '<br>'); value = this.textUtils.replaceNewLines(value, '<br>');
this.onSubmit.emit(value); this.onSubmit.emit(value);
} }

View File

@ -1,4 +1,4 @@
<ng-content></ng-content> <ng-content></ng-content>
<a ion-button icon-only clear [attr.aria-label]="label | translate" (click)="toggle()" [core-keep-keyboard]="selector" [inButton]="true"> <a ion-button icon-only clear [attr.aria-label]="label | translate" [core-suppress-events] (onClick)="toggle($event)">
<core-icon [name]="iconName"></core-icon> <core-icon [name]="iconName"></core-icon>
</a> </a>

View File

@ -99,8 +99,13 @@ export class CoreShowPasswordComponent implements OnInit, AfterViewInit {
/** /**
* Toggle show/hide password. * Toggle show/hide password.
*
* @param {Event} event The mouse event.
*/ */
toggle(): void { toggle(event: Event): void {
event.preventDefault();
event.stopPropagation();
this.shown = !this.shown; this.shown = !this.shown;
this.setData(); this.setData();
} }

View File

@ -24,6 +24,7 @@ import { CoreAutoRowsDirective } from './auto-rows';
import { CoreLongPressDirective } from './long-press'; import { CoreLongPressDirective } from './long-press';
import { CoreChartDirective } from './chart'; import { CoreChartDirective } from './chart';
import { CoreBackButtonDirective } from './back-button'; import { CoreBackButtonDirective } from './back-button';
import { CoreSupressEventsDirective } from './supress-events';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -37,7 +38,8 @@ import { CoreBackButtonDirective } from './back-button';
CoreAutoRowsDirective, CoreAutoRowsDirective,
CoreLongPressDirective, CoreLongPressDirective,
CoreChartDirective, CoreChartDirective,
CoreBackButtonDirective CoreBackButtonDirective,
CoreSupressEventsDirective
], ],
imports: [], imports: [],
exports: [ exports: [
@ -51,7 +53,8 @@ import { CoreBackButtonDirective } from './back-button';
CoreAutoRowsDirective, CoreAutoRowsDirective,
CoreLongPressDirective, CoreLongPressDirective,
CoreChartDirective, CoreChartDirective,
CoreBackButtonDirective CoreBackButtonDirective,
CoreSupressEventsDirective
] ]
}) })
export class CoreDirectivesModule {} export class CoreDirectivesModule {}

View File

@ -17,6 +17,9 @@ import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
/** /**
* IMPORTANT: This directive is deprecated because it causes a weird effect (the keyboard closes and opens again).
* We recommend using core-suppress-events directive for a better user experience.
*
* Directive to keep the keyboard open when clicking a certain element (usually a button). * Directive to keep the keyboard open when clicking a certain element (usually a button).
* *
* @description * @description
@ -39,6 +42,8 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
* *
* <textarea id="send-message-input"></textarea> * <textarea id="send-message-input"></textarea>
* <button [core-keep-keyboard]="'#send-message-input'" [inButton]="true">Send</button> * <button [core-keep-keyboard]="'#send-message-input'" [inButton]="true">Send</button>
*
* @deprecated v3.5.2
*/ */
@Directive({ @Directive({
selector: '[core-keep-keyboard]' selector: '[core-keep-keyboard]'

View File

@ -0,0 +1,95 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Based on http://roblouie.com/article/198/using-gestures-in-the-ionic-2-beta/
import { Directive, ElementRef, OnInit, Input, Output, EventEmitter } from '@angular/core';
/**
* Directive to suppress all events on an element. This is useful to prevent keyboard closing when clicking this element.
*
* This directive is based on some code posted by johnthackstonanderson in
* https://github.com/ionic-team/ionic-plugin-keyboard/issues/81
*
* @description
*
* If nothing is supplied or string 'all', then all the default events will be suppressed. This is the recommended usage.
*
* If you only want to suppress a single event just pass the name of the event. If you want to suppress a set of events,
* pass an array with the names of the events to suppress.
*
* Example usage:
*
* <a ion-button [core-suppress-events] (onClick)="toggle($event)">
*/
@Directive({
selector: '[core-suppress-events]'
})
export class CoreSupressEventsDirective implements OnInit {
@Input('core-suppress-events') suppressEvents: string | string[];
@Output() onClick = new EventEmitter();
protected element: HTMLElement;
constructor(el: ElementRef) {
this.element = el.nativeElement;
}
/**
* Initialize event listeners.
*/
ngOnInit(): void {
let events: string[];
if (this.suppressEvents == 'all' || typeof this.suppressEvents == 'undefined' || this.suppressEvents === null) {
// Suppress all events.
events = ['click', 'mousedown', 'touchdown', 'touchmove', 'touchstart'];
} else if (typeof this.suppressEvents == 'string') {
// It's a string, just suppress this event.
events = [this.suppressEvents];
} else if (Array.isArray(this.suppressEvents)) {
// Array supplied.
events = this.suppressEvents;
} else {
events = [];
}
// Suppress the events.
for (const evName of events) {
this.element.addEventListener(evName, this.stopBubble.bind(this));
}
// Now listen to "click" events.
this.element.addEventListener('mouseup', (event) => { // Triggered in Android & iOS.
this.onClick.emit(event);
});
this.element.addEventListener('touchend', (event) => { // Triggered desktop & browser.
this.stopBubble(event);
this.onClick.emit(event);
});
}
/**
* Stop event default and propagation.
*
* @param {Event} event Event.
*/
protected stopBubble(event: Event): void {
event.preventDefault();
event.stopPropagation();
}
}