ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.02k stars 13.51k forks source link

bug: contenteditable not selectable or editable in iOS #18368

Closed CFT-Chris closed 3 years ago

CFT-Chris commented 5 years ago

Bug Report

Ionic version:

[x] 4.x

Current behavior: A <div contenteditable="true"> can't be edited in iOS mobile view when inside <ion-app>. Tapping on the div does not make the editor caret appear.

Expected behavior: Be selectable/editable. Can edit contenteditable within ion-app for Android and browser, but not iOS mobile.

Steps to reproduce:

  1. ionic start ion-app-contenteditable-ios blank --capacitor
  2. edit app.component.html
    <div contenteditable="true" style="height: 100px; background: teal">Editable, outside ion-app</div>
    <ion-app style="margin-top: 100px;">
    <div contenteditable="true" style="height: 100px; background: tomato">Editable, inside ion-app</div>
    </ion-app>
  3. ionic build
  4. npx cap add ios
  5. npx cap open ios

Test in simulator.

Related code: Repo with above example: https://github.com/CFT-Chris/ion-app-contenteditable-ios

Other information: This is the same as #6336 and it still reproduces now. I can confirm adding the CSS is a sufficient workaround:

[contenteditable] {
    -webkit-user-select: text;
    user-select: text;
}

Ionic info:

Ionic:

   ionic (Ionic CLI)             : 4.12.0 (C:\Users\Chris\AppData\Roaming\npm\node_modules\ionic)
   Ionic Framework               : @ionic/angular 4.4.2
   @angular-devkit/build-angular : 0.13.9
   @angular-devkit/schematics    : 7.3.9
   @angular/cli                  : 7.3.9
   @ionic/angular-toolkit        : 1.5.1

Capacitor:

   capacitor (Capacitor CLI) : 1.0.0-beta.25
   @capacitor/core           : 1.0.0-beta.25
CFT-Chris commented 5 years ago

This is an issue with Safari, which uses webkit. https://stackoverflow.com/questions/20823468/user-selectnone-breaking-safari-contenteditable

It is a very old bug (as far back as 2013), and it does not appear that Safari will ever get around to replacing the webkit implementation of user-select.

In app.scss if inside <html class="plt-mobile ios"><ion-app>, then user-select: none and any contenteditable inside of this container cannot be selected/edited given the webkit implementation of user-select.

Seeing that this behaviour will not be fixed anytime soon and that we are stuck with Safari for web views for iOS Ionic apps, I think the workaround should be permanently be put in app.scss like so:

html.plt-mobile {
  ion-app {
    user-select: none;
  }

  &.ios ion-app [contenteditable] {
    user-select: text;
  }
}

Without it, it seems like any Ionic devs that want a rich-text editor (they frequently employ a contenteditable div) in their iOS apps will end up down the same rabbit hole time and time again, sinking many hours to eventually arrive at this same conclusion.

I will submit a PR with this proposed change. It can be shot down if a better alternative exists but nearly all stackoverflow articles and old Ionic issues about this have proposed this CSS solution.

peterpeterparker commented 5 years ago

I'm not exactly facing the same behavior. Yes user-select: text; has to be set but it works in my case the same if I set it on the ion-app or the editable div (for example).

The problem, for me at least, is rather than only direct text children of the editable content could be selected and none of the children elements could be selected.

For example

<div contenteditable="true" style="user-select: text; -webkit-user-select:text;">
        Hello
        <p>something</p>
    </div>
</div>

Without ion-app=> EVERYTHING is selectable Inside ion-app=> Only "Hello" is selectable, "< p >something< /p >" will remains not selectable

Here some screenshots:

Capture d’écran 2019-05-28 à 06 55 00 Capture d’écran 2019-05-28 à 06 55 52

And a video:

https://www.dropbox.com/s/rsi7dhkxt1o33i8/not-selectable.mov?dl=0

peterpeterparker commented 5 years ago

Looks like there was such an issue back then with Ionic v1 which was never solved :(

References: https://github.com/ionic-team/ionic/issues/3542 and https://github.com/ionic-team/ionic-v1/issues/6

peterpeterparker commented 5 years ago

Probably another duplicate too: https://github.com/ionic-team/ionic/issues/16901

peterpeterparker commented 5 years ago

I've cloned and build locally Ionic core and track down the issue in ion-app. I figured out that inputShims, which is only imported on iOS, is the root cause of the problem. Commenting the import and the above problem doesn't happens anymore.

Why is another question but that's a start.

Update: in the script, there is an option inputBlurring which per default is true. turning it to false solves the problem

const inputBlurring = config.getBoolean('inputBlurring', true);

p.s.: in case of Ionic core, you could disable this blurring function like the following:

import '@ionic/core';

import {setupConfig} from '@ionic/core';
setupConfig({
    inputBlurring: false
});
CFT-Chris commented 5 years ago

Hi @peterpeterparker,

I also reproduce what you are seeing (child elements of contenteditables div are immediately blurred trying to select text within them).

Would disabling inputBlurring be too big of a change and impact things outside of contenteditable divs? Perhaps there is a way to disable inputBlurring for contenteditables only?

I'm eyeing this line in particular in inputBlurring: const SKIP_SELECTOR = 'input, textarea, [no-blur]';

Maybe we could add [contenteditable] to that list. I can confirm that if we add the no-blur attribute to our contenteditable divs the bug you describe no longer reproduces.

Also regarding your comment:

I'm not exactly facing the same behavior. Yes user-select: text; has to be set but it works in my case the same if I set it on the ion-app or the editable div (for example).

I think the user-select: text always needs to be applied at the [contenteditable] level and not the ion-app level, per the proposed PR fix. Otherwise, all contents end up being selectable, which I would assume is the undesired behaviour the original app.scss style was trying to fix given the amount of accidental touch holds, swiping and scrolling on mobile platforms.

peterpeterparker commented 5 years ago

Agree with you @CFT-Chris , maybe adding [contenteditable] to the SKIP_SELECTOR would work but it need test. I printed out the element intercepted in the input-blurring function and it turned out, at least in my test, that iOS called twice the function, once with the effective element and once with a body element, so I'm not sure if it would work or not, probably deserve a test.

Also agree with you, user-select: text should be applied on the [contenteditable] level, my above remark was more about trying to debug the issue.

I think it doesn't need any PR regarding the style of Ionic core, if something should be done is probably something regarding the function input-blurring but that's only my guess

chetan-prime commented 4 years ago

For anyone who is still having this issue. I was able to fix this on my Ionic 4 project by adding the no-blur attribute to the tag. That is already there in the bypass list for SKIP_SELECTOR

KreativeKoder commented 4 years ago

In Ionic4 adding no-blur and the styling is what worked for me: <div contenteditable no-blur style="user-select: text; -webkit-user-select: auto;" </div>

liamdebeasi commented 3 years ago

Thanks! I opened a new PR (https://github.com/ionic-team/ionic-framework/pull/22404) since I needed to make a few changes. We will get this merged in soon.

liamdebeasi commented 3 years ago

Thanks for the issue. This has been resolved via https://github.com/ionic-team/ionic-framework/pull/22404, and a fix will be available in an upcoming release of Ionic Framework.

ionitron-bot[bot] commented 3 years ago

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.