Range.getBoundingClientRect() returns wrong top/y if caret set to first char in multiline contentEditable
Categories
(Core :: DOM: Selection, defect, P3)
Tracking
()
People
(Reporter: mail, Unassigned)
References
(Blocks 1 open bug)
Details
(Keywords: parity-chrome)
Attachments
(2 files)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36
Steps to reproduce:
- Open attached file index.html
- Resize window so that the text wraps into multiple lines
- Open dev console by pressing F12 and switch to console
- Click before the first char in the first line of text
- top/y position logged in console is correct :)
- Click the before the first char in the second line
- top/y position is logged in console incorrect :(
Notes:
- The problem only appears on the first character in each line. For all other characters inside the text, the positions are reported correctly.
- The problem also appears on todays beta and nightly builds of Firefox.
- The problem does NOT appear in latest Google Chrome or Internet Explorer 11.
Actual results:
top/y position is the same for the first char in the second line as is for the first char in the first line.
Expected results:
top/y for first char of second line should be different from first line.
Reporter | ||
Comment 1•3 years ago
|
||
It seems if setting caret to first char in second line, the position of the last char of the first line is reported. This includes x/left/y/top.
Comment 2•3 years ago
|
||
Hi,
I was able to reproduce this issue on my machine win 10x64 on the latest Nightly 88.0a1: top/y position is the same for the first char in the second line as is for the first char in the first line. I can confirm that this issue doesn't occurs on Chrome.
Updated•3 years ago
|
Comment 3•3 years ago
|
||
Looks like that nsRange::CollectClientRectsAndText()
does not take the result of Selection::GetInterlinePosition()
and always use end of line's character.
https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/dom/base/nsRange.cpp#2713
Kagami, could you take a look?
Comment 4•3 years ago
|
||
Sounds a bit tricky since the method should work independent from the current selection (because the range can be cloned). I guess we should add an internal caret association state for ranges to make this work. Does this sound good to you?
Comment 5•3 years ago
|
||
(In reply to Kagami :saschanaz from comment #4)
Sounds a bit tricky since the method should work independent from the current selection (because the range can be cloned). I guess we should add an internal caret association state for ranges to make this work. Does this sound good to you?
I think that it should depend on how Chrome behave. I guess that in the most cases, it's required only with nsRange::mSelection
is set to non-null. But if Chrome keeps the interline position after cloning a selection range, we should follow it.
Comment 6•3 years ago
|
||
AFAICT Blink does not have a notion of "interline position". Gecko can put the selection at the end of line + next to the whitespace but Blink cannot, it only puts the caret before the whitespace. So I think we can't follow them unless we want to remove such behavior.
What this means is that each offset on Blink corresponds to a single visual position but not on Gecko.
Comment 7•3 years ago
|
||
And I think we don't want to remove that behavior since at least one word processor (MS Word) also behaves same. (The caret can be after the whitespace at the end of the line.)
Storing the caret state makes sense to me for now, since it prevents unexpected change after cloning and thus aligns better with Chrome. Does this make sense to you?
Comment 8•3 years ago
|
||
(In reply to Kagami :saschanaz from comment #6)
AFAICT Blink does not have a notion of "interline position". Gecko can put the selection at the end of line + next to the whitespace but Blink cannot, it only puts the caret before the whitespace. So I think we can't follow them unless we want to remove such behavior.
Indeed. If a line break occurs at middle of a word, the behavior is exactly same as Gecko:
https://jsfiddle.net/d_toybox/q6uy4bon/3/
So, the remaining web-compat issue is, whether after a white-space which caused a line break should be included in the previous line or next line. But your comment 7 is reasonable to keep our current behavior.
Therefore, I think that this can be closed as WONTFIX for now.
Comment 9•3 years ago
|
||
Interesting, I'm seeing slightly different behavior where the end of lines are considered as next lines (on Android right now). Maybe a good chance to file a spec issue? 🤔
Comment 10•3 years ago
|
||
Hmm, I'm really confused.
Firefox for Desktop:
- When selection is collapsed at end of line which ends with a white-space, the position is end of the line.
- When selection is collapsed at start of line whose previous line ends with a white-space, the position is end of the previous line.
- When selection is collapsed at end of line which ends with a non-white-space, the position is end of the line.
- When selection is collapsed at start of line whose previous line ends with a non-white-space, the position is end of the previous line.
Chrome for Desktop:
- When selection is collapsed at end of line which ends with a white-space, the position is start of the next line.
- When selection is collapsed at start of line whose previous line ends with a white-space, the position is start of the line.
- When selection is collapsed at end of line which ends with a non-white-space, the position is end of the line.
- When selection is collapsed at start of line whose previous line ends with a non-white-space, the position is end of the previous line.
So, the difference is, white-space which caused a line break is positioned end of the previous line or start of next line.
Description
•