Closed Bug 1496320 Opened 2 years ago Closed 4 months ago

Typing character should be inserted around `<a href>` when insertion point is edge of it and it's coming from outside of the link

Categories

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

62 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla76
Tracking Status
firefox76 --- fixed

People

(Reporter: olisevich, Assigned: masayuki)

References

(Depends on 1 open bug, Blocks 2 open bugs)

Details

Attachments

(3 files)

Attached file Exmaple to reproduce
User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0

Steps to reproduce:

Edit the content in contenteditable <div> with the <a>link</a> and <span>text</span> node inside it.
Place cursor between <a> tag's 'n' and 'k' characters, and move it to the right with the keyboard's right arrow key.
Type some random chars with the keyboard.


Actual results:

The new text would go into <a> tag content.


Expected results:

The new text should go into <span> or create new text node if nothing follows the <a> tag (Chrome and Edge default behaviour)
Apart from this, moving the cursor right to <span> content and returning it back to middle between <a> and <span> sets the input into <span> node.
Component: Untriaged → Editor
Product: Firefox → Core
I think this is expected behavior.

On Chrome and Edge:
There is no way to add characters at the end of the <a> tag's text.
It always insert characters at the beginning of <span> tag.

So, I think Firefox's behavior is better than the other browser.
Then how user is supposed to write some text after the link, even when inserting the space char it belongs to the link.

In Chrome and Egde there is always a way to modify the link going back one char, edit something and delete the last char, and continue to type the next text not belonging to the link.

I FF case, there is no way to do that, except to begin the new line.
Priority: -- → P5
We hit this bug as well. Here's a simple repro:

<div contenteditable>
<div><a href="#">this is a test</a></div>
<div>line 2</div>
</div>

As mentioned above, there's no way to type after the link. Our customer is angry about this behavior.
(In reply to jisong from comment #3)

> As mentioned above, there's no way to type after the link. Our customer is
> angry about this behavior.

Does this occur on Office Online?
Flags: needinfo?(jisong)
It's difficult to say about the original issue since Firefox's behavior is really better than Chrome/Edge as Alice-san said at comment 1.

On the other hand, comment 3's case <https://jsfiddle.net/d_toybox/fm0unrd8/> is really bad. When caret is moved from the following <div> element, inputting text should be inserted after the <a> element.

I don't have any reasonable reason why only a[href] element should be treated specially. Check the following testcase: <https://jsfiddle.net/d_toybox/fm0unrd8/3/>
The worst case in FF behaviour is that it is inconsistent.

If you move the cursor from adjacent right char to the left edge of the link you will continue to type outside anchor element.
Else, if you move the cursor from left to right inside anchor to its edge, you will continue to write to an anchor element.
Also, if you delete the next right adjacent element to the anchor, you will enter the anchor mode editing.

All this cases in Chrome/Edge/Safari are consistent - continue writing simple text, so you are aware that nothing would break up your link text with blind typing.
data:text/html;charset=utf-8,<div contenteditable><div><a href="%23">Link%F0%9F%91%BD</a></div><div>%F0%9F%91%BBnormal</div></div>

Try adding the linked-text following the alien👽.
It is difficult to append linked-text in Chrome... isn't it?


In Firefox, just type linked-text.
If you want to append normal-text, move caret in 2nd line(this is normal-text which is you want), and move to the left edge, then type something, then remove unwanted line break and/or insert new line if you want. It is also easy for me and it is intuitive.
(In reply to Eugene from comment #6)
> The worst case in FF behaviour is that it is inconsistent.
> 
> If you move the cursor from adjacent right char to the left edge of the link
> you will continue to type outside anchor element.
> Else, if you move the cursor from left to right inside anchor to its edge,
> you will continue to write to an anchor element.

I don't think that it's bad inconsistent behavior. In those cases, insertion point keeps context immediately before, and without such behavior, user cannot choose insertion point in adjacent 2 nodes.

> Also, if you delete the next right adjacent element to the anchor, you will
> enter the anchor mode editing.

I think that this is bad inconsistent because the user modifies outside of the element with Delete key. Therefore, insertion point should be moved to the next node.

> All this cases in Chrome/Edge/Safari are consistent

Yeah, from point of view of web-compat, we should change our behavior...

> - continue writing
> simple text, so you are aware that nothing would break up your link text
> with blind typing.

However, we experienced a lot that changing our behavior to other browser's behavior breaks existing web apps. Additionally, our editor is used by Thunderbird.  So, changing our editor behavior means that we will change UX of Thunderbird users. So, this is really unfortunate case since our behavior provides better number of choices to users. (Note that I don't say we should not change our behavior. I'd love to know a good solution.)
(In reply to jisong from comment #3)
> We hit this bug as well. Here's a simple repro:
> 
> <div contenteditable>
> <div><a href="#">this is a test</a></div>
> <div>line 2</div>
> </div>
> 
> As mentioned above, there's no way to type after the link. Our customer is
> angry about this behavior.

FYI: Workaround is type Enter and Backspace. Enter key press forcibly ends <a> element if caret is collapsed at end of <a href> (bug 1422234, i.e., even on ESR60, this workaround should be available).
The workaround works. Our customer tried this workaround too. However, customer still feel it is not acceptable since it always requires additional steps. If this can't get fixed, we can only suggest customer to use Chrome/Edge instead.

Outlook online is also impacted by this issue, while Word online isn't, because it doesn't rely on <div contenteditable />
Flags: needinfo?(jisong)
(In reply to jisong from comment #10)
> The workaround works. Our customer tried this workaround too. However,
> customer still feel it is not acceptable since it always requires additional
> steps. If this can't get fixed, we can only suggest customer to use
> Chrome/Edge instead.

As far as I've tested, you want to provide same UX as native app's Word. If so, why don't you control selection for making guarantee that your apps work consistently on all browsers?

For example,

> document.addEventListener("selectionchange", () => {
>   let selection = window.getSelection();
>   if (!selection.isCollapsed) {
>     return;
>   }
>   if (selection.focusNode.nodeType !== Node.TEXT_NODE ||
>       selection.focusNode.length != selection.focusOffset ||
>       !editor.contains(selection.focusNode)) {
>     return;
>   }
>   let element = selection.focusNode.parentNode;
>   if (element.nodeType !== Node.ELEMENT_NODE) {
>     return;
>   }
>   if (element.tagName.toLowerCase() === "a" &&
>       element.getAttribute("href") !== null) {
>     let range = document.createRange();
>     range.setStartAfter(element);
>     selection.removeAllRanges();
>     selection.addRange(range);
>   }
> });

https://jsfiddle.net/d_toybox/fm0unrd8/7/

Okay, let's change the behavior only when caret is moved from outside of <a href> because it's too difficult to append text at end of paragraph etc when it ends with <a href>. Feel free to file new bug if you believe that Gecko follows other browsers' behavior.

Assignee: nobody → masayuki
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
OS: Unspecified → All
Hardware: Unspecified → All
Summary: New input is sticked to hyperlink tag when the last cursor position was inside hyperlink tag range in contenteditable container → Typing character should be inserted around `<a href>` when insertion point is edge of it and it's coming from outside of the link

Only TypeInState stores last caret position. So, only it can detect the
case caret is moved from outside of <a href> element and is now at start
or end of it.

Note that this patch does not assume <a href> has an empty text node with
another inline element. If we supported it, the loop would be more complicated
and it's really unrealistic edge case. Therefore, it's reasonable to ignore
the case.

And also this patch works with ArrowUp/ArrowDown/PageUp/PageDown
cases. However, I have no idea to reject such cases. But I guess that
it does not so bad behavior for users because caret does not moved in
a text node in <a href>.

Depends on D69479

Pushed by masayuki@d-toybox.com:
https://hg.mozilla.org/integration/autoland/rev/6f44fa3b54fc
part 0: Add automated test r=m_kato
https://hg.mozilla.org/integration/autoland/rev/eee6de1afb6a
part 1: Make `TypeInState` clear "link style" when it detects caret coming from outside of current link r=m_kato
Status: ASSIGNED → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla76
You need to log in before you can comment on or make changes to this bug.