diff --git a/src/components/rich-text-editor/core-rich-text-editor.html b/src/components/rich-text-editor/core-rich-text-editor.html index 69f78c45e..972fe0c0c 100644 --- a/src/components/rich-text-editor/core-rich-text-editor.html +++ b/src/components/rich-text-editor/core-rich-text-editor.html @@ -5,18 +5,18 @@
- - - - - - - - - - - - + + + + + + + + + + + +
@@ -25,7 +25,7 @@
- +
diff --git a/src/components/rich-text-editor/rich-text-editor.ts b/src/components/rich-text-editor/rich-text-editor.ts index 761bb56a2..1a03f7d64 100644 --- a/src/components/rich-text-editor/rich-text-editor.ts +++ b/src/components/rich-text-editor/rich-text-editor.ts @@ -22,7 +22,6 @@ import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreEventsProvider } from '@providers/events'; import { FormControl } from '@angular/forms'; -import { Keyboard } from '@ionic-native/keyboard'; import { Subscription } from 'rxjs'; /** @@ -69,7 +68,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy rteEnabled = false; editorSupported = true; - constructor(private domUtils: CoreDomUtilsProvider, private keyboard: Keyboard, private urlUtils: CoreUrlUtilsProvider, + constructor(private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private sitesProvider: CoreSitesProvider, private filepoolProvider: CoreFilepoolProvider, @Optional() private content: Content, elementRef: ElementRef, private events: CoreEventsProvider, private utils: CoreUtilsProvider) { @@ -104,28 +103,6 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy this.textarea.value = param; }); - // Setup button actions. - const buttons = (this.decorate.nativeElement as HTMLDivElement).getElementsByTagName('button'); - for (let i = 0; i < buttons.length; i++) { - const button = buttons[i]; - let command = button.getAttribute('data-command'); - - if (command) { - if (command.includes('|')) { - const parameter = command.split('|')[1]; - command = command.split('|')[0]; - - button.addEventListener('click', ($event) => { - this.buttonAction($event, command, parameter); - }); - } else { - button.addEventListener('click', ($event) => { - this.buttonAction($event, command); - }); - } - } - } - // Use paragraph on enter. document.execCommand('DefaultParagraphSeparator', false, 'p'); @@ -397,13 +374,9 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy setTimeout(() => { if (this.rteEnabled) { this.editorElement.focus(); - this.setCurrentCursorPosition(this.editorElement.firstChild); } else { this.textarea.setFocus(); } - setTimeout(() => { - this.keyboard.show(); - }); }); } @@ -472,25 +445,23 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy * Execute an action over the selected text. * API docs: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand * - * @param {any} $event Event data - * @param {string} command Command to execute. - * @param {any} [parameters] Parameters of the command. + * @param {any} $event Event data + * @param {string} command Command to execute. */ - protected buttonAction($event: any, command: string, parameters: any = null): void { + protected buttonAction($event: any, command: string): void { $event.preventDefault(); $event.stopPropagation(); - document.execCommand(command, false, parameters); - setTimeout(() => { - if (this.rteEnabled) { - this.editorElement.focus(); + if (command) { + if (command.includes('|')) { + const parameters = command.split('|')[1]; + command = command.split('|')[0]; + + document.execCommand(command, false, parameters); } else { - this.textarea.setFocus(); + document.execCommand(command, false); } - setTimeout(() => { - this.keyboard.show(); - }); - }); + } } /** diff --git a/src/components/send-message-form/core-send-message-form.html b/src/components/send-message-form/core-send-message-form.html index 8a7aa0ef1..aea20f503 100644 --- a/src/components/send-message-form/core-send-message-form.html +++ b/src/components/send-message-form/core-send-message-form.html @@ -1,7 +1,7 @@ -
+ - diff --git a/src/components/send-message-form/send-message-form.ts b/src/components/send-message-form/send-message-form.ts index 15e1e414f..bac82624d 100644 --- a/src/components/send-message-form/send-message-form.ts +++ b/src/components/send-message-form/send-message-form.ts @@ -48,20 +48,22 @@ export class CoreSendMessageFormComponent implements OnInit { /** * Form submitted. - * @param {any} $event Form submit + * + * @param {Event} $event Mouse event. */ - submitForm($event: any): void { - let value = this.message.trim(); - $event.target.reset(); + submitForm($event: Event): void { + $event.preventDefault(); + $event.stopPropagation(); - // Focus again on textarea. - $event.target[0].focus(); + let value = this.message.trim(); if (!value) { // Silent error. return; } + this.message = ''; // Reset the form. + value = this.textUtils.replaceNewLines(value, '
'); this.onSubmit.emit(value); } diff --git a/src/components/show-password/core-show-password.html b/src/components/show-password/core-show-password.html index 39ec9513f..ba281d0ed 100644 --- a/src/components/show-password/core-show-password.html +++ b/src/components/show-password/core-show-password.html @@ -1,4 +1,4 @@ - + diff --git a/src/components/show-password/show-password.ts b/src/components/show-password/show-password.ts index 3b679df23..7671da8d6 100644 --- a/src/components/show-password/show-password.ts +++ b/src/components/show-password/show-password.ts @@ -99,8 +99,13 @@ export class CoreShowPasswordComponent implements OnInit, AfterViewInit { /** * 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.setData(); } diff --git a/src/directives/directives.module.ts b/src/directives/directives.module.ts index 28db74390..90c21ca2e 100644 --- a/src/directives/directives.module.ts +++ b/src/directives/directives.module.ts @@ -24,6 +24,7 @@ import { CoreAutoRowsDirective } from './auto-rows'; import { CoreLongPressDirective } from './long-press'; import { CoreChartDirective } from './chart'; import { CoreBackButtonDirective } from './back-button'; +import { CoreSupressEventsDirective } from './supress-events'; @NgModule({ declarations: [ @@ -37,7 +38,8 @@ import { CoreBackButtonDirective } from './back-button'; CoreAutoRowsDirective, CoreLongPressDirective, CoreChartDirective, - CoreBackButtonDirective + CoreBackButtonDirective, + CoreSupressEventsDirective ], imports: [], exports: [ @@ -51,7 +53,8 @@ import { CoreBackButtonDirective } from './back-button'; CoreAutoRowsDirective, CoreLongPressDirective, CoreChartDirective, - CoreBackButtonDirective + CoreBackButtonDirective, + CoreSupressEventsDirective ] }) export class CoreDirectivesModule {} diff --git a/src/directives/keep-keyboard.ts b/src/directives/keep-keyboard.ts index 2cdc41e1f..1c99b27ea 100644 --- a/src/directives/keep-keyboard.ts +++ b/src/directives/keep-keyboard.ts @@ -17,6 +17,9 @@ import { CoreDomUtilsProvider } from '@providers/utils/dom'; 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). * * @description @@ -39,6 +42,8 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; * * * + * + * @deprecated v3.5.2 */ @Directive({ selector: '[core-keep-keyboard]' diff --git a/src/directives/supress-events.ts b/src/directives/supress-events.ts new file mode 100644 index 000000000..88bfc891b --- /dev/null +++ b/src/directives/supress-events.ts @@ -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: + * + * + */ +@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(); + } +}