Open Bug 1773065 (avoid-implicit-multi-range-selection) Opened 2 years ago Updated 11 days ago

Selection rangeCount is greater than 1 when selection includes element with user-select: none

Categories

(Core :: DOM: Selection, defect)

Firefox 101
defect

Tracking

()

Tracking Status
firefox103 --- affected

People

(Reporter: woods, Unassigned)

References

(Blocks 2 open bugs)

Details

Attachments

(1 file)

Steps to reproduce:

On macOS, from at least Firefox 100 to 103.0a1:

  1. Navigate to https://rangecount.unstable.email/
  2. Select all selectable content
  3. In the developer console, invoke window.getSelection().rangeCount
  4. Observe the result is 2

Actual results:

It seems that selections which traverse elements with user-select: none have multiple ranges, which contravenes the specification. (https://www.w3.org/TR/selection-api/#definition) This causes e.g. Range.getRangeAt(0) to produce an unexpected result.

Expected results:

The number of ranges in the selection must not be greater than 1.

Component: Untriaged → DOM: Core & HTML
Product: Firefox → Core

What exactly contradicts the specification? Multiple ranges is how Gecko has always represented both user-select: none, and table selection.

Component: DOM: Core & HTML → DOM: Selection

From the specification (https://www.w3.org/TR/selection-api/#definition):

Each selection can be associated with a single range.

This specification follows non-Gecko engines in restricting selections to at most one range, but the API was still originally designed for selections with arbitrary numbers of ranges. This explains oddities like the coexistence of removeRange() and removeAllRanges(), and a getRangeAt() method that takes an integer argument that must always be zero.

And MDN reflects this (https://developer.mozilla.org/en-US/docs/Web/API/Selection):

However, browsers other than Gecko did not implement multiple ranges, and the specification also requires the selection to always have a single range.

Hence the difference in behavior between browsers for the reduced test case, https://rangecount.unstable.email/

I was able to reproduce the issue on Mac10.13 using build 100.0a1 upgraded to latest 103.0a1 (20220608121353) using the steps from description.

Status: UNCONFIRMED → NEW
Has STR: --- → yes
Ever confirmed: true
Severity: -- → S3

This is done in nsRange.cpp around here:

This causes the anchor/focus position of Selection incompatible with the other browsers.

For reaching here, Selection needs to be in user's operation here.
https://searchfox.org/mozilla-central/rev/f9beb753a84aa297713d1565dcd0c5e3c66e4174/dom/base/Selection.cpp#1159

This means that we allow web apps to create selection ranges across non-selectable elements. Therefore, I guess that most things which were tried to avoid with splitting selection ranges have already been fixed.

According to disabling the path result in tryserver, we don't have so many tests about this behavior.
https://treeherder.mozilla.org/jobs?repo=try&revision=bcf72abfff941d9887efc3737a356d0a1a852fef

When I do "Select All" here, current build does not paint the button labels as selected, but patched build does it. I think that we need to make some adjustment for keeping current behavior in some features.

  • SelectFrames should stop setting the "selected" flag to frames when the range is created by user's operation and the frame's content is not selectable.

It seems that the serializer ignores the non-selectable nodes at copy.

No longer blocks: 1738866
See Also: → 1842684

Bug 1874539 comment 0:

Note: this is important for providing screen reader support and retain the ability to copy text (e.g. code) from a website.

It seems that we should give higher priority than before.

Alias: avoid-implicit-multi-range-selection

Hi folks, thank you for linking the issues together. I would like to add some context to the comment on the screen reader aspect of things and also provide some information for people attempting a similar approach. (Apologies for the longer post.)

Background

As far as I am able to tell and test, screen readers currently don't present non-visual users with a convenient way to consume code from the web. Screen reader users have to manually navigate the code and rely on spelling out code one character at a time.

There are currently very few techniques to replace the original content and present screen readers with optimized content for a pleasant experience. The @media aural is deprecated and no longer has any function. The speak-as: spell-out rule would allow for selectively marking parts of the code for letter-by-letter announcement, but this rule is currently experimental and is only supported in Safari. The aria-label attribute only works on interactive elements in most browsers. The only cross-browser way to present alternative content for screen readers is via the screen reader replacement technique, such as the one described at https://webaim.org/techniques/css/invisiblecontent/ .

Using this technique one can provide a more pleasant screen reader experience by marking up important control characters when generating the HTML code, such as:

<code><span class="sr-only">double left brace</span><span aria-hidden="true" style="user-select:none">{{</span>...</code>

Providing a spelled-out version in HTML instead of relying on the screen reader interpretation is necessary because it heavily depends on the programming language in question. For example, white space is uninteresting in most languages, but very important in Python. A screen reader can only fall back to a character-by-character spelling for code if no alternative is present because it does not have the context of the programming language in question. In contrast, the spelled-out alternative lets a screen reader user listen through an entire blog post with code similar to an audio book. The separate <span> tags also allow the screen reader to navigate in meaningful increments, even if this doesn't always work.

Drawbacks of this solution

This solution is not perfect, but it produces a much more pleasant out of the box experience for screen reader users when reading through a page with lots of code in it. (Tested with NVDA, JAWS, and Android Talkback.) As far as I could tell, it has the following two drawbacks.

First, when code with replacements is selected for copying, it causes the code to be copied with extra line breaks as indicated in bug 1874539 and is caused by the issue present in this bug. This is a Firefox-only issue, it works as expected in Webkit browsers. The problem can be worked around by providing a "copy code" button, but negatively impacts users who wish to only copy parts of the code.

Second, it will likely cause a degradation in user experience on Braille displays since the characters are spelled out on the display. The aria-braillelabel attribute is currently not supported in any browser I know of. Even if it were supported, it would likely function similar to aria-label and not work on non-interactive elements. I can't test this as Braille displays are prohibitively expensive, so I'd love some feedback on this.

To work around both issues in my project, I have implemented a JavaScript mechanism to disable screen reader optimizations and revert to the unoptimized HTML. However, it would be preferable to fix this issue in Firefox so at least non-Braille users can have a good experience out of the box.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: