Open Bug 957724 Opened 11 years ago Updated 2 years ago

getSelection().toString() is inconsistent with its ranges

Categories

(Core :: DOM: Selection, defect)

26 Branch
x86
All
defect

Tracking

()

UNCONFIRMED

People

(Reporter: wblandin, Unassigned)

Details

(Keywords: testcase, Whiteboard: [bugday-20140113])

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 Steps to reproduce: - Go to http://jsfiddle.net/PrFTV/ - Mousedown on "F", mouseup on the first "o", WITHOUT actually selecting the first "o". Actual results: - window.getSelection().toString() is "F" (correct behaviour) - window.getSelection().getRangeAt(0).endContainer AND window.getSelection().focusNode are references to the second span (containing "o") Expected results: - window.getSelection().toString() is "F" - window.getSelection().getRangeAt(0).endContainer AND window.getSelection().focusNode are references to the first span (containing "F")
Reproduced with 2014-01-13-03-02-03-mozilla-central-firefox-29.0a1.en-US.linux-x86_64.
OS: Mac OS X → All
Whiteboard: [bugday-20140113]
Also with 2009-01-01-05-mozilla-central-firefox-3.2a1pre.en-US.linux-x86_64.
New URL is http://jsfiddle.net/PrFTV/1/. Confirmed on FF OSX 29.0.1
Component: Untriaged → DOM: Core & HTML
Keywords: testcase
Product: Firefox → Core
Why is this a problem per se? The range ends right before the "o", not right after the "F"; those are different document positions.
Component: DOM: Core & HTML → Selection
I updated the fiddle: http://jsfiddle.net/PrFTV/2/ What is surprising to me is that the behavior is different depending whether you mouseover (without selecting) the second span or not. If you select '1' and keep the cursor on '1', then endContainer.textContent will === '1' If you select '1' and move the cursor to '2' (without selecting it), then endContainer.textContent will === '2' selection.toString() is the same in both cases, but not its range.
Sure. The range represents the actual bit of the DOM that was selected. toString() (and the visual display of the selection, to some extent) can't represent all that; it can only represent the text contained in that range. Similarly, if you select just an image then the range will contain it, and the visual display will even indicate it, but toString() will show the alt text (likely empty string), not the image itself...
Or even simpler. Given this markup: a<span style="display:none">b</span>c and then double-clicking on the string, toString() will return "ac" but of course the range includes that <span> containing "b" (its start is in the "a" textnode, at offset 0, and the end is in the "c" textnode, at offset 1).
Thanks for your explanation, it is very clear. However, I can't think of any use case where a user would want to select invisible DOM nodes. Is there a way to obtain the endContainer of the displayed/visible selection, as you would do in WebKit and Blink using `window.getSelection().getRangeAt(0).endContainer`?
What would you use that for? Note that things are not that simple, btw; they never are with selections, unfortunately. Consider this markup: a<br>b and drag the mouse from right before the "a" to right before the "b". Now the toString() is "a\n" but the only visible selection in Gecko is on the "a"... (some other browsers will indicate that the newline is selected in this case, but Gecko does not).

This behaviour is still present in Firefox 83. I want to contribute another test case to describe the selection behaviour: https://jsfiddle.net/

There, the string "M QMMQ M" is displayed, each character is wrapped in a span tag.

(1) As described above, depending on where the user starts a mousedown to select "QMMQ" the resulting range is either:
startContainer = " " / startOffset = 1, if the mousedown is occuring over the space before Q (while at the same time not selecting the space)
or
startContainer = "Q" / startOffset = 0, if the mousedown is occuring over the Q
It is unintuitive and inconsistent to get two different range results for the exact same visual selection.

(2) If the user double clicks the word QMMQ the resulting selection range is:
startContainer = " " / startOffset = 1 and endContainer = " " / startOffset = 0
which is also unintuitive. In that case, I would expect:
startContainer = "Q" / startOffset = 0 and endContainer = "Q" / startOffset = 1

Chromium handles these cases consistent and intuitively. Sure, there might be good reasons to handle the selection the firefox way, this is just a comment. A use case where the chromium behaviour is of advantage is if you have all characters wrapped in spans to annotate / highlight ranges of text using css. Having window.getSelection reliably return the text nodes which are the start and end of the visual selection helps here as one does not have to look at startOffset/endOffset and possible need to move to the next / previous sibling to get the correct span.

sorry, here is the correct link: https://jsfiddle.net/yoepq4dL/1/
The range is logged to the console when pressing the "show selection" button

Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.