Closed mozesstumpf closed 2 months ago
I haven't clearly mentioned, but the problem is there with the current implementation, that lets say, the user presses the Shift
+ ArrowRight
, so I have to extend the selection via script, so I set the focus with the Selection.extend
.
From that point (since the direction
is not node-position based), when I get the StaticRange
from the getComposedRanges
method, I can't know for sure that which one is the focus boundary-point, therefore I will not be able to determine that which node should I extend.
I don't think we can change this behavior. Selection behavior is tied to the underlying platform's behavior / convention.
Selection behavior is tied to the underlying platform's behavior / convention.
I'm not sure whether you are talking about the direction or the selection's behavior. I'm completely fine with the selection's behavior, my concern is that I will not be able to determine the anchor and focus node within a ShadowRoot.
Selection behavior is tied to the underlying platform's behavior / convention.
I'm not sure whether you are talking about the direction or the selection's behavior. I'm completely fine with the selection's behavior, my concern is that I will not be able to determine the anchor and focus node within a ShadowRoot.
What do you mean by that? Selection direction is neither forward nor backward when a user selects text with a mouse on macOS, and anchor & focus are not well defined in such cases.
What do you mean by that? Selection direction is neither forward nor backward when a user selects text with a mouse on macOS, and anchor & focus are not well defined in such cases.
Currently, we have access to the anchor & focus node via the Selection API (anchorNode
, focusNode
), but if the selection crosses the shadow boundary, these nodes will be rescoped to the shadow host, therefore we must rely on the direction
property.
Let me demonstrate the issue in an example with a basic operation of the selection with keyboard (Shift
+ ArrowLeft
/ArrowRight
)
We have a text that will be selected with double click, which makes the direction
's value to none
.
// within a ShadowRoot
<div cE=true>Lorem |ipsum| dolor</div>
The Shift
+ ArrowLeft
should extend the focus boundary-point, but since we can't determine that anymore due to the inconsistent behavior of the direction
, we don't know that which boundary-point should be extended.
So, from that point, if I press Shift
+ ArrowLeft
and update the bounday-point via script, that can be any of the following results:
<div cE=true>Lorem| ipsum| dolor</div>
// or
<div cE=true>Lorem |ipsu|m dolor</div>
After we changed the selection to any of the scenario above, we still can't rely on the direction
to determine the focus boundary-point, since it may not be updated.
When the selection's range is mutated by scripts, e.g. via selectNode(node), direction of the selection must be preserved.
There is an example with comments about the basic implementation of the inline directional navigation with selection, that shows why I have to rely on the "nodeDirection
".
The
Shift
+ArrowLeft
should extend the focus boundary-point, but since we can't determine that anymore due to the inconsistent behavior of thedirection
, we don't know that which boundary-point should be extended.So, from that point, if I press
Shift
+ArrowLeft
and update the bounday-point via script, that can be any of the following results:<div cE=true>Lorem| ipsum| dolor</div> // or <div cE=true>Lorem |ipsu|m dolor</div>
The correct behavior on macOS is to always expand the selection. i.e. if Shift + ArrowLeft is pressed, then the selection should extend to the left, and if Shift + ArrowRight is pressed, then the selection should extend to the right.
The correct behavior on macOS is to always expand the selection. i.e. if Shift + ArrowLeft is pressed, then the selection should extend to the left, and if Shift + ArrowRight is pressed, then the selection should extend to the right.
But in both scenario, the focus boundary-point will be extended.
In the example above, I was talking about the manual implementation of these keys.
<div cE=true>Lorem |ipsum| dolor</div>
...................A......F
// A=anchor, F=focus
In this example, if the selection is in the Light DOM, I can determine the focus boundary-point with the Selection.focusNode/focusOffset
.
When the user presses the Shift
+ ArrowLeft
, I can update the boundary-points via script for that:
<div cE=true>Lorem |ipsu|m dolor</div>
...................A.....F
If the selection is within a Shadow DOM, the Selection.focusNode/focusOffset
will be rescoped to the shadow host, therefore I must use the getComposedRanges
that returns a StaticRange
. The problem is that I can't know for sure that the startContainer/startOffset
or the endContainer/endOffset
is the focus boundary-point.
But in both scenario, the focus boundary-point will be extended.
That's not true. The correct behavior is to pick the left edge if left arrow is pressed and pick the right edge if the right arrow is used since there is no directionality defined in such cases.
The correct behavior is to pick the left edge if left arrow is pressed and pick the right edge if the right arrow is used since there is no directionality defined in such cases.
If the Shift
key is not pressed, then it collapses to the edge, but if the Shift
is pressed, then it extends the focus boundary-point.
The video was recorded in windows, but I've checked it on macOS as well and that has the same behavior.
https://github.com/user-attachments/assets/84cd54d5-732f-408b-a05a-4b79a8bc8f71
The correct behavior is to pick the left edge if left arrow is pressed and pick the right edge if the right arrow is used since there is no directionality defined in such cases.
If the
Shift
key is not pressed, then it collapses to the edge, but if theShift
is pressed, then it extends the focus boundary-point.
You need to double click on a word to select the word on macOS instead of drag-selecting it.
Oh, now I get that why it has to be directionless, thanks!
There is one more thing might worth to mention, in the User Interactions:
set update selection's direction to forwards if the start is before or equal to the end, backwards if if the end is before the start
In this statement, we should refer to anchor and the focus instead of the range's boundary points, aren't we?
The main use cases where the
direction
can be useful:When we have an "in-range" selection (so it's not collapsed), and we press
Shift
+ArrowKey
to navigate, it extends the focus boundary point.During the Selection, the engines handles the focus boundary point differently. For example, in Chromium, if the anchor is an editable, the focus boundary point has to be an editable as well, meanwhile Gecko allows the focus boundary-point to end in a non-editable node, therefore we may have to extend the focus to an editable node.
There may other use cases, but at the end, all that matters that we know which one is the anchor and the focus boundary-point.
With the current behavior of the
direction
that mainly relies on the user's interaction and changes the direction accordingly, is very confusing from the developer perspective, because the selection can be collapsed even if thedirection
isbackward
orforward
, or it can be "in-range" even if thedirection
isnone
, so it's much harder to figure out which one is the anchor and focus boundary-point.I'd like to discuss here that what's the purpose of the
direction
property with the current implementation, and what's the advantage of setting thedirection
based on the user's interaction instead of the node's position in the document.