Closed Bug 1612076 Opened 6 years ago Closed 2 years ago

Caret in contentEditable content becomes invisible when next to uneditable element

Categories

(Core :: DOM: Editor, defect, P3)

72 Branch
defect

Tracking

()

RESOLVED FIXED
123 Branch
Tracking Status
firefox123 --- fixed

People

(Reporter: marijnh, Assigned: masayuki)

References

(Blocks 1 open bug)

Details

(Whiteboard: [h2review-noted], [wptsync upstream])

Attachments

(2 files)

Attached file test.html —

Depending on the surrounding DOM structure and the way the cursor was moved somewhere, the caret is sometimes invisible when directly next to an uneditable inline element in an editable container.

In the attached HTML file, this can be reproduced by clicking anywhere in the first paragraph ("Normal"), and then pressing the down arrow key. There is no visible cursor, though the editable element still has focus and the DOM selection has a reasonable value (in the second paragraph at position 1).

Typing something at that point works and makes the cursor visible again. Backspacing out the typed text results in the exact same DOM selection (as visible from JavaScript), but this time the cursor is visible.

Possibly related to 1175495, though the circumstances that trigger this are different.

Hmm, caret is moving the uneditable node and this makes users confused (although contenteditable="false" must not be used widely).

Priority: -- → P3
See Also: → 1175495

contenteditable="false" must not be used widely

Modern editors often want to display rich content (mentions, markers, completions, and similar) inside editable content. If you don't set that to uneditable, you have to deal with the possibility of the user accidentally typing into your widgets, so there's a good reason to use uneditable elements inside editable content.

Some more details: The original file, where the uneditable element is in an otherwise empty paragraph, allows you to reproduce this with direct user arrow motion. If there's content around it, as in the demo below, the issue doesn't seem to come up with keyboard cursor motion, but does occur reliably when setting the cursor after the uneditable element with a script.

<div contenteditable=true>one<span contenteditable=false>X</span>two</div>
<script>getSelection().collapse(document.querySelector("div"), 2)</script>

Since CodeMirror makes quite heavy use of such widgets in the content, and version 6 builds on contenteditable for accessibility reasons, this is really quite a problem for us.

Priority: P3 → P2
Whiteboard: [h2review-noted]

I just tried to reproduce this error in Mozilla Firefox 80.0a1 2020-07-23. The cursor does move down to the second paragraph but required two hits of the down-arrow and the text-cursor shows at the end of "UNEDITABLE". I wonder if the problem is that it requires two hits rather than a single hit.

I'm still seeing the exact behavior described in the original issue in both 79 and 81 nightly (on Linux). After putting the cursor on the first line and pressing the down arrow, there is no visible cursor.

Severity: normal → S3

I can confirm that this bug still exists on Firefox 106.0 (Linux). Any chance to get it fixed?

OS: Unspecified → All
Priority: P2 → P3
Hardware: Unspecified → All
Summary: Cursor in contentEditable content becomes invisible when next to uneditable element → Caret in contentEditable content becomes invisible when next to uneditable element

This issue still persists, but it is not present in Edge/Chrome/Safari.

Oh, this is a simple bug.

Assignee: nobody → masayuki
Status: NEW → ASSIGNED

When pressing ArrowLeft key at:

<p>abc</p><p><span contenteditable=false>def</span>{}<br></p>

, caret is moved into the non-editable text because
nsCaret::GetCaretFrameForNodeOffset looks for a preceding text node from
the BRFrame. This is required if the preceding text node ends with a
collapsible white-space but followed by a <br> because the text frame
should not contain the white-space rect and BRFrame frame should be next
to it, i.e., the white-space looks like a overflown content.

So, for rendering a caret, the method needs to return non-editable text frame
even in the case, but for considering new caret position in the DOM tree, it
should not return non-editable text frame.

Therefore, this patch adds a param to nsCaret::GetCaretFrameForNodeOffset()
which forcibly return editable content frame or not and makes
Selection::GetPrimaryOrCaretFrameForNodeOffset call it with the new option
because its callers are the handler of caret navigation.

Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/7e32f178b02f Make `AdjustCaretFrameForLineEnd` stop scanning text node if first node is editable but reached non-editable one r=emilio
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/43721 for changes under testing/web-platform/tests
Whiteboard: [h2review-noted] → [h2review-noted], [wptsync upstream]
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 123 Branch
Upstream PR merged by moz-wptsync-bot
Upstream PR merged by moz-wptsync-bot
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: