Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getTargetRanges of beforeinput differ between browsers (should not happen in EditContext) #146

Open
masayuki-nakano opened this issue Oct 13, 2023 · 33 comments
Labels
Agenda+ Queue this item for discussion at the next WG meeting

Comments

@masayuki-nakano
Copy link

Should it always return empty array? In my understanding, browsers do not manage selection range as deleting range in EditContext editing host. Therefore, I think that the range should be considered by the web apps themselves.

On the other hand, this example uses the result of getTargetRanges...

@johanneswilm
Copy link
Contributor

@masayuki-nakano Editcontexts do provide the native selection. So why would this work differently than with contenteditable?

@johanneswilm johanneswilm transferred this issue from w3c/editing Oct 13, 2023
@dandclark
Copy link
Contributor

As pointed out by @johanneswilm and as stated in https://w3c.github.io/edit-context/#edit-context-differences, the user agent will still handle selection and caret navigation in an EditContext. So I think it makes sense that getTargetRanges still works the normal way in EditContext. This is necessary for authors to be able to handle things like replacement from spellcheckers, which would trigger beforeinput with type "insertReplacementText". The author will need the result of getTargetRanges() in that case.

@masayuki-nakano
Copy link
Author

My main point is about the cases deleting text from collapsed range. It requires a lot of computation to consider the range to delete even though web apps finally consider the behavior and the result is not consistent between browsers. See current test result. The amount how much the user wants to delete can be detected is notified by .inputType.

In other words, if getTargetRanges is really required for any inputType values, the detail of getTargetRanges should be defined first, but it could be impossible because there are too many situations.

@johanneswilm
Copy link
Contributor

@masayuki-nakano Can you not wait with calculating the target ranges until the getTargetRanges() method is called? Web apps that want to decide the target ranges themselves and don't require any input from the browser then don't have to call the method and so the calculation never takes place.

The exact ranges that a browser-provided target range covers will be OS/browser dependent as is also now the case. That's why we didn't specify it any further in the case of contenteditable, and I'm imaging in this case you can just run the same code that you are running for contenteditable to calculate them. Is that not the case?

@masayuki-nakano
Copy link
Author

@masayuki-nakano Can you not wait with calculating the target ranges until the getTargetRanges() method is called? Web apps that want to decide the target ranges themselves and don't require any input from the browser then don't have to call the method and so the calculation never takes place.

Good idea for the beforeinput event performance (even for contenteditable). However, one of the problem is, if EditContext works without getTargetRanges, we can avoid to use the builtin HTML editor, but it becomes impossible to port the computing target range command. And there is another problem. The spec needs to define when the result should be computed. The DOM tree can be modified even during the beforeinput propagation or even after the propagation. In the latter case, Chrome behavior is broken, IIRC.

The exact ranges that a browser-provided target range covers will be OS/browser dependent as is also now the case. That's why we didn't specify it any further in the case of contenteditable, and I'm imaging in this case you can just run the same code that you are running for contenteditable to calculate them. Is that not the case?

I think that it does not make sense for web apps to use getTargetRanges without ignoring a lot of odd result because the result means they are not just incompatible especially when deleting parent blocks, etc. E.g., Type Backspace in <ul><li>{}<br></li></ul>. Chrome and Firefox delete the <ul> entirely, but Chrome returns the collapsed range. I agree with getTargetRanges is useful for text deletion, but current spec does not define the behavior for most cases and browsers implement it too roughly. (Especially, when I implement beforeinput as the last implementer, there were no meaningful getTargetRange tests in WPT...)

Even if browsers should return useful ranges for text deletion, I think that the spec should define the behavior clearly. E.g., word amount backward deletion at <div><b>ab</b><i>cd[]</i></div>, staring from {div,0}, {b,0} or {#text,0}?, and ending at {div,2}, {i,1} or #text,2? So, I think that supporting useful getTargetRanges across browsers require a lot of work and it seems that it may not be reasonable for actual usage.

@johanneswilm
Copy link
Contributor

Even if browsers should return useful ranges for text deletion, I think that the spec should define the behavior clearly.

We can try to discuss this point again. Last time we concluded that it's just not possible as different platforms have different ideas about what should be the right target range. This seems like a general question related to getTargetRanges() also in contenteditable and not just related to EditContext. Do I understand that correctly? If yes, should we move this issue to the input events spec?

I think that the target ranges are more important for some inputTypes than others. When using deletion forward/backward, most JavaScript apps should be able to figure out what they want to do without using target ranges by looking at the inputType and the current selection. On the other hand, in the case of using the built-in spell checker, it's important to know which range is to be replaced with the incoming text and because it doesn't replace the current selection, there really is no other way to know where to insert the text without looking at target ranges.

@dandclark
Copy link
Contributor

dandclark commented Oct 18, 2023

It sounds like the main problem here is lack of cross-browser interoperability of getTargetRanges() for deletion inputTypes?

I don't think the EditContext spec needs to define how getTargetRanges() gets calculated, since it should be calculated in the exact same way as in contenteditable. The difference for EditContext is only that the DOM doesn't automatically get modified.

We do need to support getTargetRanges() for inputType === "insertReplacementText", so I guess the question is whether to not support getTargetRanges() for all the other inputTypes due to the interoperability concern.

The simplest approach in my opinion is to just keep getTargetRanges() working in the same way for EditContext as with contenteditable. Where there are important interoperability differences we should do the work in the input-events spec to better define these behaviors for contenteditable as well as EditContext. I think it will not end up mattering much because most developers would not look at getTargetRanges() for deletion commands since they would compute the extent of the deletion themselves.

The alternative is to go through each inputType and decide for each individually whether getTargetRanges() should return an empty array for EditContext or should keep the preexisting behavior. This seems more complicated from a spec and implementation perspective.

@johanneswilm
Copy link
Contributor

johanneswilm commented Oct 18, 2023

I think it will not end up mattering much because most developers would not look at getTargetRanges() for deletion commands since they would compute the extent of the deletion themselves.

Actually, we received reports from JavaScript editors previously that they need this information as there can be platform dependent differences for things like deleting a word or line forward or backward that would require re-implementing a lot in JavaScript that is already in the browser.

Looking at the way target ranges are used in an editor like CKEditor5 that is working mainly using the beforeinput event, it looks like they are not always that helpful though as there are bugs in Firefox [1].

As this seems to be a general issue with target ranges, I will move this issue to the input events spec.

[1] https://github.com/ckeditor/ckeditor5/blob/331d1e7a04729284efbb55937fd97a452488dc8d/packages/ckeditor5-engine/src/view/observer/inputobserver.ts#L82-L83

@johanneswilm johanneswilm transferred this issue from w3c/edit-context Oct 18, 2023
@johanneswilm johanneswilm added the Agenda+ Queue this item for discussion at the next WG meeting label Oct 18, 2023
@johanneswilm johanneswilm changed the title getTargetRanges of beforeinput on EditContext editing host getTargetRanges of beforeinput differ between browsers Oct 18, 2023
@masayuki-nakano
Copy link
Author

masayuki-nakano commented Oct 20, 2023

(Sorry for the delay due to side-effects of vaccination)

I do not agree with this point: getTargetRanges() should return same value as contenteditable even if in an EditContext editing host, because in my understanding, one of the main purposes of EditContext is, making editable app developers free from the incompatibility of contenteditable between browsers. getTargetRanges() for deletion may/can be important for web apps to consider the deleting range especially for developers who do not want to do complicated things about that. From point of view of the API purpose, I think returning different result from it is fine if contenteditable gets different result between browsers. However, in the EditContext editing host, the result may cause incompatible behavior of web apps on different browsers. Therefore, defining the result must be important. E.g. the result of getTargetRanges of delete*Backward contains or does not contain the start tag of <b> in the this case, <b>f[]oo, users may keep the bold style at next type or lose instead. So I think that this is not an issue which can be considered later.

In other words, getTargetRange result may depend on the type of editing host. So, defining all things in InputEvent spec may be not a good place.

Looking at the way target ranges are used in an editor like CKEditor5 that is working mainly using the beforeinput event, it looks like they are not always that helpful though as there are bugs in Firefox

Oh, thank you for the information, if I got the STR, I'll fix it (or them).

@johanneswilm johanneswilm changed the title getTargetRanges of beforeinput differ between browsers getTargetRanges of beforeinput differ between browsers (should not happen in EditContext) Oct 20, 2023
@johanneswilm
Copy link
Contributor

Hey @masayuki-nakano, ok, I understand. You want all browsers to behave the same in EditContext but can live with the current state for contenteditable. I have changed the heading of this issue back to better cover your concern and tagged it to be discussed at next month's meeting.

So, I think that supporting useful getTargetRanges across browsers require a lot of work and it seems that it may not be reasonable for actual usage.

I'm a bit confused here. As we can see in the CKEditor 5 source code, the existing target ranges in contenteditable are already in use today (with provisions made for a bug in Firefox that makes it return target ranges outside of the editable element at times). So given that this is actually being used in at least one of the major open production-level editors out there, why would it require a lot of work to make target ranges useful for actual usage?

So I think that this is not an issue which can be considered later.

The idea is here that if the target ranges are not the same right from the beginning, then JS editors will be written in a different way so that browsers converging later on will not work. Is that your concern? As someone working with CkEditor @Comandeer, is the differences between returned target ranges in different browser a concern for you? If so, is there an area in which standardization would be more useful than another?

For execCommand/contenteditable, browser makers have previously said that some things will not be standardized as it simply reflects different native behavior between platforms that each user agent tries to imitate as the default behavior. The JavaScript editors seem to generally gloss over most differences and instead offer editors that work almost the same everywhere.

The question is whether browser makers would be willing to return target ranges that are fully standardized even if that means breaking with the behavior of native apps in their OS/platform. This could especially be the case in scenarios involving text block merging and complex structures such as lists or tables.

@johanneswilm
Copy link
Contributor

Looking around github for usages of getTargetRanges(), I see that in Facebook's lexical, they use Selection.modify() to calculate the range that a word/line/character from a giving starting position is rather than to look at getTargetRanges():

// We use the DOM selection.modify API here to "tell" us what the selection
// will be. We then use it to update the Lexical selection accordingly. This
// is much more reliable than waiting for a beforeinput and using the ranges
// from getTargetRanges(), and is also better than trying to do it ourselves
// using Intl.Segmenter or other workarounds that struggle with word segments
// and line segments (especially with word wrapping and non-Roman languages).

facebook/lexical@09ee036#diff-b91a462bfae8745a3acc43f8e626c5bbadecc52bfdd984f39b88a475a09eada1R565-R570

This could be an alternative solution for JS editor developers if they don't have getTargetRanges() for certain deletion types. It's unclear to me why this method is currently more reliable as @trueadm claims.

@masayuki-nakano
Copy link
Author

Hey @masayuki-nakano, ok, I understand. You want all browsers to behave the same in EditContext but can live with the current state for contenteditable. I have changed the heading of this issue back to better cover your concern and tagged it to be discussed at next month's meeting.

Thank you very much!

So, I think that supporting useful getTargetRanges across browsers require a lot of work and it seems that it may not be reasonable for actual usage.

I'm a bit confused here. As we can see in the CKEditor 5 source code, the existing target ranges in contenteditable are already in use today (with provisions made for a bug in Firefox that makes it return target ranges outside of the editable element at times). So given that this is actually being used in at least one of the major open production-level editors out there, why would it require a lot of work to make target ranges useful for actual usage?

I think that using same rules to compute getTargetRanges for EditContext editing host makes web apps using EditContext behave exactly same if they want to refer the result at deletion. Otherwise, deletion result may be different on different browsers. In my understanding, nobody wants such result in the EditContext world.

About CKEditor 5, I guess that they don't refer the getTargetRange result when the deletion range reaches an element boundary, or at least they adjust the result because of the incompatibility. (Or just avoid the things with using simple HTML structure as far as possible.)

So I think that this is not an issue which can be considered later.

The idea is here that if the target ranges are not the same right from the beginning, then JS editors will be written in a different way so that browsers converging later on will not work. Is that your concern? As someone working with CkEditor @Comandeer, is the differences between returned target ranges in different browser a concern for you? If so, is there an area in which standardization would be more useful than another?

So, my concern is about that web apps may use getTargetRanges result as-is at deletion and are shipped without enough tests on various browsers, and a lot of web developers do not test non-primary browsers for them in the real cases.

Previously, the result of getTargetRanges is an advance announcement which will occur once the default of beforeinput is not prevented. Additionally, beforeinput event itself is created for overriding the builtin editor behavior. Therefore, in my understanding, the result is not used as-is in most cases. However, in the EditContext world, the result may be directly used for the last result. Therefore, I'm afraid about the inconsistency between browsers.

For execCommand/contenteditable, browser makers have previously said that some things will not be standardized as it simply reflects different native behavior between platforms that each user agent tries to imitate as the default behavior. The JavaScript editors seem to generally gloss over most differences and instead offer editors that work almost the same everywhere.

The question is whether browser makers would be willing to return target ranges that are fully standardized even if that means breaking with the behavior of native apps in their OS/platform. This could especially be the case in scenarios involving text block merging and complex structures such as lists or tables.

I think that the platform difference may just cause web-compat issues or increasing the code of web apps to get consistent behavior.

I think that block merging etc should be handled by web apps itself in the EditContext world. In such cases, browsers should just return current selection range(s) or empty array. In my understanding, it's important only the following case: Selection is collapsed and inputType value is deleteWordBackward, deleteWordForward, deleteSoftLineBackward, deleteSoftLineForward, deleteEntireSoftLine, deleteHardLineBackward, deleteHardLineForward, deleteContentBackward and deleteContentForward because I guess that web developers do not want to compute their range especially when caret is around a combination of some Unicode characters like Emoji or when soft line which requires the layout information.

So, I think that the necessary and simplest rules are:

  • browsers should return current selection as-is (or empty array) if the range is not extended by browser (like deleting block boundaries case)
  • browsers should include or not include phrase element boundaries (and/or inline element boundaries) when the deletion range gets reached there
  • how to treat non-text inline content if the range boundary reaches such content (e.g., <img>, <div style=display:inline-block>)

Then, I guess that you do not need to struggle with this issue so long time.

Looking around github for usages of getTargetRanges(), I see that in Facebook's lexical, they use Selection.modify() to calculate the range that a word/line/character from a giving starting position is rather than to look at getTargetRanges():

// We use the DOM selection.modify API here to "tell" us what the selection
// will be. We then use it to update the Lexical selection accordingly. This
// is much more reliable than waiting for a beforeinput and using the ranges
// from getTargetRanges(), and is also better than trying to do it ourselves
// using Intl.Segmenter or other workarounds that struggle with word segments
// and line segments (especially with word wrapping and non-Roman languages).

facebook/lexical@09ee036#diff-b91a462bfae8745a3acc43f8e626c5bbadecc52bfdd984f39b88a475a09eada1R565-R570

This could be an alternative solution for JS editor developers if they don't have getTargetRanges() for certain deletion types. It's unclear to me why this method is currently more reliable as @trueadm claims.

Ah, using Selection API can check the word boundary etc, it's clever approach. However, Selection API is not cheap (runtime cost). Therefore, I'd be happy if they would stop using it with new APIs (I guess it never happens).

@johanneswilm
Copy link
Contributor

Ah, using Selection API can check the word boundary etc, it's clever approach. However, Selection API is not cheap (runtime cost). Therefore, I'd be happy if they would stop using it with new APIs (I guess it never happens).

Are the changes to the selection obtained by running Selection.modify() consistent across browsers? If so, could we specify that the ranges returned for deleteWordBackward, deleteWordForward, deleteSoftLineBackward, deleteSoftLineForward, deleteEntireSoftLine, deleteHardLineBackward, deleteHardLineForward, deleteContentBackward and deleteContentForward it will be static ranges corresponding to the selection changes that Selection.modify() would produce? What about cases where deleting makes paragraphs merge? Maybe even complex cases with lists and tables merging, etc.?

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 28, 2023
In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 28, 2023
In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
aarongable pushed a commit to chromium/chromium that referenced this issue Oct 30, 2023
In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Reviewed-by: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1217018}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 30, 2023
In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Reviewed-by: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1217018}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 31, 2023
In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Reviewed-by: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1217018}
@Comandeer
Copy link
Member

Sorry for the delayed answer.

As someone working with CkEditor @Comandeer, is the differences between returned target ranges in different browser a concern for you? If so, is there an area in which standardization would be more useful than another?

It's not a big concern as we always validate the returned ranges and fix them ourselves if it's necessary. The more useful area would be "subcharacter" cases (I'll explain them below).

Are the changes to the selection obtained by running Selection.modify() consistent across browsers? If so, could we specify that the ranges returned for deleteWordBackward, deleteWordForward, deleteSoftLineBackward, deleteSoftLineForward, deleteEntireSoftLine, deleteHardLineBackward, deleteHardLineForward, deleteContentBackward and deleteContentForward it will be static ranges corresponding to the selection changes that Selection.modify() would produce?

If they are consistent between browsers, than it sounds good to us. However, I looked into the Selection API spec and found that the smallest possible granularity is "character". How would it behave in cases where there are "subcharacters"? By that, I mean cases like "b̂" (so a letter with an additional accent). I've created a demo with that case. And the current behavior while deleting the content with a Backspace is quite inconsistent in browsers (tested on macOS 14.1):

  • in Firefox only the accent is deleted and the target range offsets show that one character was deleted,
  • in Safari both the letter and its accent is deleted and the target range offsets show that two characters were deleted,
  • in Chrome only the accent is deleted but the target range offsets show that two characters were deleted.

We consider Firefox's behavior the right one.

As for the Selection#modify(), all browsers are consistent, and moving the selection backward with the lowest possible granularity (selection.modify( 'move', 'backward', 'character' )) moves the caret before the letter. I suspect that it would be quite difficult to put the caret "inside" the letter (between the letter itself and its accent) but wouldn't making the target ranges consistent with the Selection#modify() results break the current behavior of deletion in the "subcharacter" cases?

@dandclark
Copy link
Contributor

Notes from 2023-11-09 Editing WG meeting:

[17:09] johanneswilm: next issue: https://github.com/w3c/input-events/issues/146
[17:10] q+
[17:10] --> edgar (~uid184785@7e4e2622.public.cloak) has joined this channel.
[17:11] johanneswilm: should we align getTargetRanges in all cases? or just some types of ranges?
[17:12] dandclark: w.r.t. EditContext, getTargetRanges is needed for many commands
[17:12] dandclark: for deletion cmds we have them zeroed out
[17:12] (does "zeroed out" mean empty range? or null range?)
[17:12] I see, thanks
[17:13] dandclark: this makes it so that sites are unlikely to rely on this, while we figure this out
[17:13] johanneswilm: would be best to not have them removed
[17:14] dandclark: if we ship with them working differently, compat will be difficult moving forward
[17:15] johanneswilm: the non-trivial deletion commands need getTargetRanges (request from JS authors)
[17:15] johanneswilm: ...such as delete word, delete sentence, etc.
[17:15] johanneswilm: FB's editor just uses API for extending selection to determine ranges
[17:15] johanneswilm: masayuki felt that was not a good way
[17:16] johanneswilm: unrealistic to align on complex editing like table merging, paragraph merging
[17:16] johanneswilm: maybe we can align on behaviors when selection is collapsed
[17:16] johanneswilm: (and align on accented character behavior)
[17:17] johanneswilm: on several platforms it's common to delete the accent first and then delete the base char
[17:17] q+
[17:17] johanneswilm: I'm a bit afraid that we may never get full agreement
[17:19] whsieh: can we use insert text replacement?
[17:20] example character: b̂
[17:20] johanneswilm: Chrome only deletes accent mark, target range is inconsistent
[17:21] johanneswilm: or actually it makes sense because target character is affected?
[17:21] q+
[17:22] johanneswilm: defn. of target ranges is very wishy-washy
[17:22] johanneswilm: however, for these character type of deletions it makes sense to be more specific
[17:23] johanneswilm: we should specify this character deletion case, maybe not in the table/paragraph merge case
[17:24] dandclark: approach sounds good to me
[17:25] smaug: doesn't cover the extent of #146
[17:25] johanneswilm: resolution is: be more specific in char-level deletions

@johanneswilm
Copy link
Contributor

@smaug---- @masayuki-nakano Given that EditContext will ship in Chromium without a flag in January (this has been merged already), do you think it would be preferable for it to return an empty array as from getTargetRanges() for inputTypes of deletions, or should it return the existing ones (with improvements for character deletion case as outlined above)? I am afraid that if it ships without any target ranges, then it will end up being yet another half-amputated API and developers will for example only use EditContext on Chrome/EditContext and contenteditable on desktop as it will give them better target ranges. So instead of simplifying, we will just make it all even more complex.

@johanneswilm
Copy link
Contributor

I think that using same rules to compute getTargetRanges for EditContext editing host makes web apps using EditContext behave exactly same if they want to refer the result at deletion. Otherwise, deletion result may be different on different browsers. In my understanding, nobody wants such result in the EditContext world.

The way I understand you here, @masayuki-nakano , is that you want the target ranges to be the same in all browsers. It is my understanding that we wrote the spec in a way that is meant to not return the same target ranges in all browsers, but rather that the target ranges should correspond to the platform dependent behavior. @whsieh is that also your understanding? Is Webkit willing to give up on returning target ranges that correspond to the iOS/MacOS native behavior in order to return the same target ranges as Chromium and Firefox?

If there is no new consensus that target ranges should now be the same across browsers, then I would strongly suggest that EditContext that will ship in Chromium returns the target ranges as required by the spec instead of returning an empty array for some input types. Otherwise it will not be spec compliant, as far as I can tell.

@johanneswilm
Copy link
Contributor

[17:25] johanneswilm: resolution is: be more specific in char-level deletions

We already have non-normative notes on this:

In some scripts on some platforms, backward deletion within a text node with a collapsed selection will delete a single code point [INFRA] rather than an entire grapheme cluster. The getTargetRanges() method can be used to find out how many code points [INFRA] the browser will remove by default if deleting within a text node.

and

In some scripts on some platforms, forward deletion within a text node with a collapsed selection will delete an entire grapheme cluster rather than a single code point [INFRA]. The getTargetRanges() method can be used to find out how many code points [INFRA] the browser will remove by default if deleting within a text node.

So I'm guessing the resolution we took then only means that these notes will be turned into part of the normative text of the specification.

moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Nov 14, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Reviewed-by: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818
vinnydiehl pushed a commit to vinnydiehl/mozilla-unified that referenced this issue Nov 15, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Reviewed-by: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Nov 16, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojiichromium.org>
Commit-Queue: Dan Clark <daniecmicrosoft.com>
Reviewed-by: Anupam Snigdha <snianumicrosoft.com>
Cr-Commit-Position: refs/heads/main{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818

UltraBlame original commit: e584836b1a351c801e83db73dcc453ad1a7f43ee
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Nov 16, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojiichromium.org>
Commit-Queue: Dan Clark <daniecmicrosoft.com>
Reviewed-by: Anupam Snigdha <snianumicrosoft.com>
Cr-Commit-Position: refs/heads/main{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818

UltraBlame original commit: e584836b1a351c801e83db73dcc453ad1a7f43ee
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Nov 16, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojiichromium.org>
Commit-Queue: Dan Clark <daniecmicrosoft.com>
Reviewed-by: Anupam Snigdha <snianumicrosoft.com>
Cr-Commit-Position: refs/heads/main{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818

UltraBlame original commit: e584836b1a351c801e83db73dcc453ad1a7f43ee
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Nov 20, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Reviewed-by: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Nov 20, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojii@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Reviewed-by: Anupam Snigdha <snianu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Nov 21, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojiichromium.org>
Commit-Queue: Dan Clark <daniecmicrosoft.com>
Reviewed-by: Anupam Snigdha <snianumicrosoft.com>
Cr-Commit-Position: refs/heads/main{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818

UltraBlame original commit: ea631482f94e2d8f8474753e35bff27fd67d3fce
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Nov 21, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojiichromium.org>
Commit-Queue: Dan Clark <daniecmicrosoft.com>
Reviewed-by: Anupam Snigdha <snianumicrosoft.com>
Cr-Commit-Position: refs/heads/main{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818

UltraBlame original commit: ea631482f94e2d8f8474753e35bff27fd67d3fce
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Nov 21, 2023
…nges for deletions, a=testonly

Automatic update from web-platform-tests
[EditContext] Don't populate getTargetRanges for deletions

In [1] the issue was raised that getTargetRanges() in beforeinput
is not interoperable across browsers for deletions. We don't want to
include non-interoperable behaviors in EditContext, so return an empty
array for getTargetRanges() when beforeinput is received for deletions
in EditContext.

We may revisit this later on and start providing a range if
interoperable behavior can be designed.

[1] w3c/input-events#146

Bug: 999184
Change-Id: Iac697f89a7c7ecee57c850e7b929e42670c10e32
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4985470
Reviewed-by: Koji Ishii <kojiichromium.org>
Commit-Queue: Dan Clark <daniecmicrosoft.com>
Reviewed-by: Anupam Snigdha <snianumicrosoft.com>
Cr-Commit-Position: refs/heads/main{#1217018}

--

wpt-commits: 818b3f80df16e77a879749335b997cdc8223777b
wpt-pr: 42818

UltraBlame original commit: ea631482f94e2d8f8474753e35bff27fd67d3fce
@johanneswilm
Copy link
Contributor

johanneswilm commented Dec 7, 2023

I believe that by returning an empty array as getTargetRanges instead of something like false the issue is actually made a lot bigger. An empty array means that no change occurs, which is completely reasonable under many circumstances - such as when the user is pressing backspace at the beginning of an editable container. So by returning false information, you now communicate to the users that they cannot trust target ranges ever and will need to use alternative mechanisms to find the real target ranges.

The point of target ranges was never to make all browsers return the same values. In fact, it was meant to allow to program text editors so that they would behave similar to native apps across platforms. Breaking from the spec is not improving this situation.

Also, all inputTypes will have differing target ranges - not just those specific to deleting. They are not returning the exact same, as was never meant to be and is probably impossible to implement.

johanneswilm added a commit that referenced this issue Dec 14, 2023
make code point replacement normative, based on resolution on #146
@dandclark
Copy link
Contributor

dandclark commented Dec 15, 2023

Notes from 2023/12/14 WG meeting:

6:04 PM getTargetRanges have always been different in browsers in contenteditable
6:04 PM should it work the same way in editcontext
smaug: I think we should aim for compatibility whenever possible
johanneswilm: counter argument is that one should be able to write platform specific editor
johanneswilm: for now, should getTargetRanges work as with contenteditable or empty ranges
johanneswilm: I'd prefer the the model getTargetRanges have
6:09 PM whsieh: last time we discussed about accent character characters - so I don't think it makes sense to have the same behavior everywhere. But what it the means in context of EditContext I'm less sure about.
dandclark: initially I was thinking empty array would be ok, but since then I've learned more about the platform conventions
6:11 PM dandclark: let's fix the easy inconsistencies, but other than that, give authors the power to do what they want.
6:13 PM johannes: that wouldn't mean we never change the behavior
smaug: if we ship something, it will be hard to fix later
dandclark: I don't think we're making it too much harder by having the same behavior with editcontext and contentediable
6:16 PM johanneswilm: empty array would be also confusing for the author
6:16 PM smaug: it could be null value if needed
6:17 PM johanneswilm: target ranges can handle accents, but selection API can't
whsieh: it is more about if browser deletes accent or such, that could be standardized, less about os differences
6:23 PM dandclark: currently in the implementation target ranges is empty for deletion
6:23 PM I'd like to go for non-empty

@sanketj
Copy link
Member

sanketj commented Dec 21, 2023

Notes from 2023/12/23 side call

8:10 AM johannesmilm: Apple may not be willing to change native behavior and position may be that they don't want to converge, need Apple position confirm
8:11 AM johannneswilm: Masayuki (Firefox) has different position
8:11 AM smaug: Canvas important case, platform behavior not applicable there
8:11 AM smaug: Do you need EditContext at all if you basically want contenteditable capabilities?
8:12 AM smaug: getTargetRanges unreliable in any scenarios
8:12 AM johannneswilm: Canvas scenario was top off mind when this API was first designed
8:13 AM johannneswilm: JS editors want browsers to do selection, ex. CodeMirror
8:14 AM johannneswilm: JS editors want DOM based editing but their own model and can handle DOM changes themselves
8:14 AM smuag: Why do they need EditContext then?
8:15 AM johannneswilm: IME integration is important
8:15 AM johannneswilm: EditContext much better at handling IME, no need to dance around IME as with contenteditable
8:15 AM johannneswilm: Huge source of pain previously
8:16 AM johannneswilm: Have been working towards this solution for over 10 years
8:17 AM johannneswilm: getTargetRanges are needed for a variety of operations to work correctly, deletions, insertReplacementText, spellcheck
8:17 AM johannneswilm: Spec needs to be updated, it's actually opposite to what Chromium implements
8:17 AM smaug: How so?
8:17 AM johannneswilm: Inputevents spec requires editing host to specify what target ranges should be
8:18 AM smaug: If canvas is host, no target ranges. Other cases, may be different. That is not defined.
8:18 AM johannneswilm: Not sure about spec, but two totally different cases.
8:18 AM smaug: Still needs to be defined
8:19 AM johannneswilm: getTargetRanges should apply to all cases, not just deletion
8:19 AM smaug: Agree, that's what is confusing. The cases are really different, some are handled by the browser and some not.
8:20 AM johannneswilm: Agree that does probably need to be specified.
8:20 AM johannneswilm: Target ranges is not selection though, those two aren't necessarily connected
8:20 AM johannneswilm: Ex: Replacing word with spellchecker, selection may be somewhere else
8:21 AM smaug: Can be used to denote focus via empty range
8:21 AM johannneswilm: If the EditContext or input events spec doesn't say, we should say this: In the case of Canvas, no target ranges should be returned.
8:22 AM daniec: Agree that needs to be specified, but that shouldn't mean other cases shouldn't have this case
8:22 AM daniec: Only way for authors to plug into native spellchecker
8:22 AM daniec: getTargetRanges need to work for non canvas cases
8:23 AM sanketj: Agree with that
8:23 AM johannneswilm: Specific reason for getTargetRanges vs. different API is that getTargetRanges can to sub character specificity
8:23 AM johannneswilm: Not possible with selection API for example
8:24 AM johannneswilm: Behaves differently on Mac
8:24 AM smaug: Does it behave differently on Mac or just Firefox?
8:25 AM johannneswilm: Mac specific behavior, non normative note in spec that on some OS behavior works this way
8:25 AM johannneswilm: Also says that browsers may have different behaviors
8:25 AM johannneswilm: Alternatively, engine would need to maintain list of grapheme clusters and behave differently on each OS
8:26 AM smaug: How would this be possible on Canvas? Need consistency in implementation.
8:26 AM dandclark: When using Canvas, authors take the responsibility of managing more functionality on their own
8:27 AM dandclark: That's why non Canvas case is important
8:27 AM dandclark: Canvas only for really large editors
8:27 AM dandclark: Smaller editors would still benefit from non Canvas support of EditContext
8:27 AM johannneswilm: Agree
8:28 AM johannneswilm: Why would we disallow getTargetRanges just for deletion?
8:28 AM smaug: Intent is just to have compatible behavior.
8:28 AM smaug: All implementations should behave the same, especially given that this is a new API.
8:29 AM smaug: Perfect time to fix the old mistakes, where implementations are inconsistent.
8:29 AM dandclark: If getTargetRanges can be fixed for contenteditable, that would be delightful, but I don't see a path to doing that.
8:29 AM dandclark: API explicitly accounts for platform differences
8:29 AM dandclark: Not really a path for cross-platform consistency
8:30 AM dandclark: If can't get there for contenteditable, EditContext behavior needs to have slightly different
8:30 AM dandclark: EditContext behavior can still be interoperable
8:31 AM smaug: Really hard to fix contenteditable, so shouldn't we try to fix EditContext?
8:31 AM dandclark: Not so much about the browser, the OSes would have to change, that's really hard
8:31 AM johannneswilm: JS Editors would love if OSes could agree, but seems unlikely
8:32 AM johannneswilm: Target ranges was built the way it was to get around these OS differences, since OSes want web apps to behave similar to native apps
8:32 AM johannneswilm: Goal of those designing this wanted that as a goal as well
8:32 AM johannneswilm: Fixing the API would go against that original goal
8:33 AM johannneswilm: Wanting web apps to behave like native apps still seems to be position for companies that control the OS
8:33 AM smaug: Lots of test failures in getTargetRanges in all browsers
8:33 AM johannneswilm: Behavior is already very different
8:34 AM smaug: Some web tests may not be testing what spec says
8:34 AM smaug: Point is implementations are doing different things
8:35 AM johannneswilm: Some cases may be just be browser bugs, but other cases may be spec compliant but behave differently on different platforms
8:35 AM johannneswilm: Happy to look into tests if that helps
8:35 AM johannneswilm: Would be a good exercise to look at getTargetRanges and find cases where things don't look right
8:35 AM johannneswilm: Some cases may need more specification
8:36 AM johannneswilm: Still don't see how getTargetRanges can behave the same everywhere
8:36 AM smaug: Can we specify the cases where OS behavior is different?
8:36 AM smaug: Other cases should be tested and specified properly
8:37 AM johannneswilm: Looked into this last year for web compat for contenteditable standardization, gets complex very quickly
8:37 AM johannneswilm: Likely means we won't have getTargetRanges for a long time, because a lot of cases to get sorted out
8:38 AM smaug: But this would be the best time since EditContext is brand new and its a point in time where we can think about interoperability
8:39 AM johannneswilm: Other editing behaviors may still be standardizable, don't think getTargetRanges can be
8:39 AM johannneswilm: JS editors do special things with contenteditable behaviors on other platforms too
8:40 AM johannneswilm: Because browsers kept changing and sites were breaking, JS editors started relying on getTargetRanges
8:40 AM johannneswilm: Likely to continue
8:40 AM smaug: Shouldn't ideally work that way
8:40 AM smaug: We really want compat and interop
8:41 AM dandclark: Unfortunately, doesn't seem possible here.
8:41 AM dandclark: EditContext is not making this worse.
8:41 AM smaug: This is best time to fix it though.
8:42 AM johannneswilm: Have had a continuous stream of issues for getTargetRanges for several years, but no success fixing them so far
8:42 AM johannneswilm: Spent a long time discussing these issues and browsers made some changes, but hard to get everything in place in a timely manner
8:42 AM johannneswilm: Editors don't want to wait for a long for EditContext to work for them
8:43 AM dandclark: +1
8:43 AM dandclark: Doesn't seem worth it to delay EditContext in favor of fixing getTargetRanges
8:43 AM smaug: Can we at least define behavior for getTargetRanges?
8:43 AM smaug: May be doable without caring about legacy.
8:44 AM smaug: Very different from contenteditable, because compat considerations. Existing editors may break with contenteditable.
8:44 AM smaug: Not true for EditContext, it is brand new.
8:44 AM dandclark: See getTargetRanges not as a new API, but an old API that already has a lot of history
8:45 AM johannneswilm: What should we do?
8:45 AM johannneswilm: Can getTargetRanges work with EditContext the same way they do for contenteditable?
8:45 AM smaug: Spec unclear for canvas case
8:45 AM dandclark: Yes, but not unclear for non canvas cases
8:45 AM johannneswilm: Can update spec for canvas case
8:47 AM smaug: EditContext seems quite complex for JS editors
8:47 AM johannneswilm: JS editors doing DOM changes themselves anyways, takes away complexity around IMEs
8:48 AM johannneswilm: Tried in the past to isolate IME operations from contenteditable, didn't work out on Android
8:48 AM johannneswilm: EditContext + input events seems like the most plausible solution
8:50 AM smaug: Spec not clear about mapping from DOM to EditContext position
8:51 AM dandclark: Spec may need updates, but developer needs to define mapping model
8:51 AM dandclark: Developer in control with EditContext, may have different behaviors depending on their own editing model
8:52 AM smaug: Curious is Apple has had web compat issues around this
8:53 AM johannneswilm: Editors are based on getTargetRanges
8:53 AM johannneswilm: There are real pain points for JS editors with this API.
8:54 AM smaug: JS editors have to work around issues and therefore browsers get compat bugs.
8:54 AM johannneswilm: That's why having getTargetRanges behaving reasonably is important.
8:55 AM johannneswilm: In the past, impossible to change contenteditable, now may be possible without breaking editors, because editors are more browser agnostic with their model
8:56 AM smaug: Still there are cases where things can be broken
8:56 AM smaug: I'd like to discuss with Masayuki
8:57 AM smaug: More optimistic about sticking to existing getTargetRanges behavior for EditContext after this conversation
8:57 AM johannneswilm: What resolution is EditContext looking for?
8:59 AM dandclark: Looking for agreement that current text spec is fine for non canvas cases
9:00 AM dandclark: Sooner we get agreement here the better, since EditContext has shipped in Chromium
9:01 AM smaug: I'll discuss with Masayuki and get back on our position.
9:02 AM johannneswilm: Dan or I will update spec for canvas case.

@masayuki-nakano
Copy link
Author

masayuki-nakano commented Jan 11, 2024

My point is, it's hard to define the rules of getTargetRanges at element boundaries. E.g., if you press Backspace at start of a paragraph and the paragraph(s) may wrap text within inline elements and the preceding paragraph may have invisible <br>. So, getTargetRanges may return:

  • abc[</span><br></p><p>]def
  • abc{</span><br></p><p>]def
  • abc</span>{<br></p><p>]def
  • abc</span><br>{</p><p>]def

However, according to the meeting log, editor app developers want only range(s) in text. I agree with the usage, but I cannot agree with fully implementing getTargetRanges without the details. Therefore, I'd like to suggest the following rules:

  • If selection is not collapsed, getTargetRanges should return the selection ranges as-is (of course, if the selection range will be modified)
  • If selection is collapsed and the inputType just insert new content, getTargetRanges should return the collapsed selection range as-is
  • If selection is collapsed and the inputType extends the range to touch from the collapsed range (like delete*), getTargetRanges should return a range in text nodes. The start container and the end container can be different, but it should be minimized. E.g., if it tries to delete a word, and the word boundary starts from start of a text node which follows another text node, the start of the range should be start of the following text node rather than end of the preceding text node. Similarly, the word boundary ends at end of a text node which is followed by another text node, the end of the range should be end of the preceding text node rather than start of the preceding text node.
  • But if the range cannot be represented with text nodes, e.g., Backspace at <p><img><img>{}</p>, getTargetRanges should return null instead of empty array.

In my understanding, editor app developers who don't want to use contenteditable want to control everything about element level editing. So, I think that this idea should be enough for editor app developers and we don't need to dive the abyss.

@johanneswilm
Copy link
Contributor

However, according to the meeting log, editor app developers want only range(s) in text.

That must be a misunderstanding. No one requested to have target ranges only in text. It was merely said that there were certain cases when working within text nodes where it was extra important for getTargetRanges() to return useful answers as there are no alternative ways of receiving this information.

I agree with the usage, but I cannot agree with fully implementing getTargetRanges without the details.

But has it not been implemented and shipped in Firefox already? I know there are a few bugs in Firefox'es current implementation, but are you suggesting to remove it altogether?

  • If selection is not collapsed, getTargetRanges should return the selection ranges as-is (of course, if the selection range will be modified)

So what if the user has some content selected and then right clicks on a spell checking suggestion somewhere else in the DOM? For example:

I [have selected] some part of the teft.

The user clicks on "teft" to change it to "test", but because "have selected" is selected, the result will be:

I [test] some part of the teft.

[...] The start container and the end container can be different, but it should be minimized. E.g., if it tries to delete a word, and the word boundary starts from start of a text node which follows another text node, the start of the range should be start of the following text node rather than end of the preceding text node.

A few years ago, when we were still a taskforce, I was told that for good reason browser makers decided not to come to agreement on what constitutes a word, a sentence, a paragraph, etc. . Has this changed? If it has not, and there is no agreement in sight, then it's probably not a good to wait with EditContext until such agreement exists.

Similarly, the word boundary ends at end of a text node which is followed by another text node, the end of the range should be end of the preceding text node rather than start of the preceding text node.

If there is agreement on where the word boundary is, this sounds like a good idea. But why not implement it uniformly also in contenteditable? It will be very confusing if getTargetRanges return something slightly differently in contenteditable/EditContext.

  • But if the range cannot be represented with text nodes, e.g., Backspace at <p><img><img>{}</p>, getTargetRanges should return null instead of empty array.

This sounds like it will make it a confusing API. I don't understand what the need for this is. getTargetRanges() as they are implemented already, show (when they are not buggy) what content would have been affected, had the browser handled the action. The result will differ from platform to platform as was intended from the start.

@smaug----
Copy link

So what if the user has some content selected and then right clicks on a spell checking suggestion somewhere else in the DOM? For example:

Then the selection isn't collapsed, so getTargetRanges works like with contentEditable.

@dandclark
Copy link
Contributor

Notes from discussion during today's Editing WG call:

[08:31] let's move on to #146
[08:32] smaug: basic proposal is that when you're doing something like backspace and selection is collapsed, don't report any ranges
[08:32] q+
[08:32] <@dandclark> q+
[08:32] q-
[08:32] smaug: which elements merged/removed is up to engine
[08:33] johanneswilm: getTargetRanges() will be different in cE vs. EC?
[08:33] johanneswilm: it's possible to change behavior in cE/input events, FF has done it in the past
[08:34] johanneswilm: (clarify): if the selection is not collapsed, getTargetRanges should return non-empty range
[08:34] johanneswilm: ...more exactly, should return the selection range
[08:35] johanneswilm: we want to allow web authors to match platform conventions
[08:35] johanneswilm: this makes it difficult
[08:38] smaug: do WK and chrome have different behviors
[08:39] johanneswilm: the implementations are not consistent, and it's not a requirement
[08:40] johanneswilm: from developer POV: you either use cE where you get platform convention info or you use EC and you get better IME handling
[08:40] dandclark: second everything johanneswilm has been saying
[08:40] dandclark: seems not good to have this tradeoff
[08:41] smaug: does Chrome have different behavior on macOS vs. windows when merging elements?
[08:42] johanneswilm: I don't think it's impossible to change getTR for cE
[08:42] johanneswilm: it's used by editors that need to be very robust, and handle corner cases and platform/engine differences like this
[08:43] johanneswilm: good to align behaviors when it makes sense
[08:43] (would be good to)
[08:43] johanneswilm: I know there's one bug in FF that many authors are currently working around atm
[08:43] johanneswilm: shouldn't be an issue to standardize to make this workaround unneeded
[08:43] smaug: need to sync up with masayuki again
[08:44] <@dandclark> w3c/edit-context#86
[08:44] johanneswilm: dandclark and I discussed what to do with getTR in canvas, issue is w3c/edit-context#86
[08:45] snianu: I'll check and see if there's platform-specific behaviors in Chrome when merging elements during editing

@masayuki-nakano
Copy link
Author

I agree with the usage, but I cannot agree with fully implementing getTargetRanges without the details.

But has it not been implemented and shipped in Firefox already? I know there are a few bugs in Firefox'es current implementation, but are you suggesting to remove it altogether?

No, I'm talking about EditContext. getTargetRanges for contenteditable and designMode is for a previous notice of how the implementation will work. However, in the EditContext case, browsers won't do nothing, but web apps manage the element changes especially when joining/splitting elements. So, why does it required by EditContext users?

(Although I'd really love somebody would consider the detail of getTargetRanges for contenteditable and designMode too.)

  • If selection is not collapsed, getTargetRanges should return the selection ranges as-is (of course, if the selection range will be modified)

So what if the user has some content selected and then right clicks on a spell checking suggestion somewhere else in the DOM? For example:

I [have selected] some part of the teft.

The user clicks on "teft" to change it to "test", but because "have selected" is selected, the result will be:

I [test] some part of the teft.

Ah, if the inputType is replacing somewhere, it should return the range in text nodes. So I mean I just didn't think the replacing case.

[...] The start container and the end container can be different, but it should be minimized. E.g., if it tries to delete a word, and the word boundary starts from start of a text node which follows another text node, the start of the range should be start of the following text node rather than end of the preceding text node.

A few years ago, when we were still a taskforce, I was told that for good reason browser makers decided not to come to agreement on what constitutes a word, a sentence, a paragraph, etc. . Has this changed? If it has not, and there is no agreement in sight, then it's probably not a good to wait with EditContext until such agreement exists.

I'm not sure the context, currently I think that all browsers support per-word deletion, therefore, I just used it for the example.

Similarly, the word boundary ends at end of a text node which is followed by another text node, the end of the range should be end of the preceding text node rather than start of the preceding text node.

If there is agreement on where the word boundary is, this sounds like a good idea. But why not implement it uniformly also in contenteditable? It will be very confusing if getTargetRanges return something slightly differently in contenteditable/EditContext.

Why does it make the developers confused? In my understanding, EditContext should work without dependencies of browsers as far as possible (except the deletion range computation). However, Input Event spec does define getTargetRanges only as:

getTargetRanges() returns an arrays StaticRanges representing the text that the event will modify if it is not canceled. The returned StaticRanges MUST cover only the code points that the browser would normally replace, even if they are only part of a grapheme cluster.

So, there is no definition for the node boundary cases.

  • But if the range cannot be represented with text nodes, e.g., Backspace at <p><img><img>{}</p>, getTargetRanges should return null instead of empty array.

This sounds like it will make it a confusing API. I don't understand what the need for this is. getTargetRanges() as they are implemented already, show (when they are not buggy) what content would have been affected, had the browser handled the action. The result will differ from platform to platform as was intended from the start.

I think that limiting the result range in text nodes makes the spec editors free from the mission impossible to define every edge case of getTargetRanges. That's the reason why I suggested that in the previous comment.

@css-meeting-bot
Copy link
Member

The Web Editing Working Group just discussed target ranges and editcontext.

The full IRC log of that discussion <johanneswilm> topic: target ranges and editcontext
<johanneswilm> github: https://github.com//issues/146
<johanneswilm> It seems like there are different ideas about whether EditContext on a dom element should behave like contenteditable in that same browser or whether it should behave the same across browsers.

@css-meeting-bot
Copy link
Member

The Web Editing Working Group just discussed getTargetRanges of beforeinput differ between browsers (should not happen in EditContext) #146.

The full IRC log of that discussion <dandclark> topic: getTargetRanges of beforeinput differ between browsers (should not happen in EditContext) #146
<dandclark> github: https://github.com//issues/146
<dandclark> johanneswilm: Masayuki thinks EditContext should work the same for all browsers. Other browser makers say we should be able to follow conventions on specific platforms.
<dandclark> ...: Spec currently says the second, should make it possible to follow conventions. Chomium implementation has removed target ranges and not yet put them back, going against the spec.
<dandclark> smaug: getTargetRanges says that representing text that event will modify if event is cancelled. It's only about the text. It's unclear what target ranges represent if you press delete/backspace and there is no text
<dandclark> johanneswilm: Why is it unclear?
<dandclark> smaug: In the input events spec, getTargetRanges talks about just text, not nodes
<dandclark> johanneswilm: yeah, text doesn't seem right, should it be the content?
<dandclark> smaug: But there's no content if selection is collapsed
<dandclark> ...: So it's a bit unclear now
<dandclark> johanneswilm: What's the part that's not clear? It's not the selection, it's the part being affected
<dandclark> ...: There's no problem of understanding in the implementations, no implementation has made it work only for text. But I agree the word 'text' there is not the best
<dandclark> ...: Are we moving closer to anything?
<dandclark> ...: Masayuki has different view vs Apple
<dandclark> ...: Can't have both, either it's working the same across all browsers or it's making it possible to follow conventions
<dandclark> smaug: have you heard feedback in Edge/Chromium
<dandclark> johanneswilm: getTargetRanges is important, need to know which part of grapheme range to delete
<dandclark> johanneswilm: Open source projects I know of are waiting until this has been resolved to build on this
<dandclark> dandclark: I haven't heard feedback that pushes us in one way or another
<dandclark> sanketj_: Will we realistically get interop here?
<dandclark> johanneswilm: If all browsers return the same yes, but then we're removing this feature.
<dandclark> ...: Won't return same target ranges across all browsers
<dandclark> smaug: Interop should always be the goal in some way
<dandclark> ...: But I understand there is this platform specific behavior.
<dandclark> sanketj_: Does every browser do exactly what the OS wants on a given OS?
<dandclark> johanneswilm: If I recall, whsieh said there's code in webkit that behaves differently in Windows, not supported anymore but in theory it's there. Question is whether Chromium does that.
<dandclark> snianu: I made some changes in Chromium for word deletion for Windows. Behavior was not the same as other native apps like Word, Notepad. Did change some behavior that was Windows only
<dandclark> johanneswilm: So we can say there's some level of that?
<whsieh> Looks like Chromium still has this? https://chromium.googlesource.com/chromium/src/+/HEAD/third_party/blink/renderer/core/editing/editing_behavior.h
<dandclark> ...: If there's some of that, then we will never get the same behavior
<dandclark> sanketj_: Seems that way to me
<whsieh> (the editing behavior is what I had in mind when I mentioned Safari/windows behavior before)
<dandclark> sanketj_: Is the answer do nothing? Agree we can't standardize that part?
<dandclark> johanneswilm: If we can't, then what's the consequence? I think we should follow the spec as is (re-add target ranges to Chromium)
<dandclark> smaug: What's the minimum viable API that editors need? Can we achieve that in some other way?
<dandclark> johanneswilm: Is proposal to only have target ranges for text certain changes. But the only thing we achieve is some editors need to have both contenteditable and EditContext around
<dandclark> johanneswilm: This would make sense if we could eventually achieve interop. But otherwise seems we are cutting hole in feature unnecessarily.
<dandclark> johanneswilm: Could we write something in spec so Firefox doesn't have to implement that part?
<dandclark> smaug: That's immediately an interop issue
<dandclark> johanneswilm: If you get target ranges you can funnel the platform conventions without knowing them
<dandclark> smaug: On <canvas> target ranges won't work anyway
<dandclark> johanneswilm: Can we get target ranges back, and then also have a list of the interop differences that we can track and knock down? Masayuki has done this in the past, let's do more. Some may be platform issues, some may be bugs.
<dandclark> smaug: I will talk to Masayuki
<dandclark> smaug: For <canvas> case they presumably already have code handling this
<dandclark> johanneswilm: On <canvas> your document model doesn't need to follow logic of HTML document
<dandclark> johanneswilm: So resolution is smaug will speak to Masayuki?
<dandclark> sanketj_: Proposal is to keep target ranges in spec, let Chromium put them back, then Masayuki enumerates specific interop differences?
<dandclark> johanneswilm: Yes, and we can't promise resources but will try to get browser makers to fix these where possible
<dandclark> dandclark: SGTM

@css-meeting-bot
Copy link
Member

The Web Editing Working Group just discussed getTargetRanges of beforeinput differ between browsers (should not happen in EditContext).

The full IRC log of that discussion <dandclark> Topic: getTargetRanges of beforeinput differ between browsers (should not happen in EditContext)
<dandclark> github: https://github.com//issues/146
<dandclark> smaug: Can someone look and confirm that browsers other than Firefox have different behavior on mac vs windows?
<dandclark> dandclark: I can, if noone else gets to this
<dandclark> smaug: I will keep pinging Masayuki for feedback
<dandclark> whsieh: In webkit we use the selection range for most typing commands when editing
<dandclark> whsieh: Not sure what getTargetRanges returns for transpose. Should probably return both? Because replacing both characters with swapped content
<dandclark> johanneswilm: And they have to be next to each other

@dandclark
Copy link
Contributor

Following up on this:

smaug: Can someone look and confirm that browsers other than Firefox have different behavior on mac vs windows?
dandclark: I can, if noone else gets to this

In Chromium there is an EditingBehavior class that centralizes a bunch of checks for editing functionality that differs by design between platforms.

Picking one example from those, Word-breaking behavior deliberately differs in Chromium to follow platform conventions on Windows vs non-Windows. See SelectionModifier::NextWordPositionForPlatform or this CL.

@masayuki-nakano
Copy link
Author

In Gecko, the behavior difference is not centralized, so, I cannot list all items up. However, as far as I know, the following things are different between platforms:

  • Whether contains following white space when selecting a word (e.g., double click on a word)
  • Whether deleting adjacent white space when deleting a word selected by double click
  • Some shortcut keys about editing, e.g., per-word deleting runs with different key combinations
  • The word deletion behavior when selection is not collapsed
  • Whether Ctrl and Shift key of RTL keyboard layout changes the text direction or does not

I don't know whether word breaker and/or grapheme cluster consideration depend on platform or not in some specific languages.

@css-meeting-bot
Copy link
Member

The Web Editing Working Group just discussed getTargetRanges of beforeinput differ between browsers (should not happen in EditContext).

The full IRC log of that discussion <sanketj_> Topic: getTargetRanges of beforeinput differ between browsers (should not happen in EditContext)
<sanketj_> github: https://github.com//issues/146
<sanketj_> johanneswilm: Last update was that Olli asked for documented cases where browsers purposely behave differently on different platforms.
<sanketj_> ...: Dan and Masayuki found cases where Chromium and Gecko behave differently.
<sanketj_> johanneswilm: Does that convince us that we are always going to have differences?
<sanketj_> smaug: Will follow up with Masayuki after this meeting. Couldn't do it before.

@css-meeting-bot
Copy link
Member

The Web Editing Working Group just discussed getTargetRanges of beforeinput differ between browsers (should not happen in EditContext).

The full IRC log of that discussion <dandclark> topic: getTargetRanges of beforeinput differ between browsers (should not happen in EditContext)
<dandclark> github: https://github.com//issues/146
<dandclark> smaug: I think Masayuki is more positive on having getTargetRanges
<dandclark> smaug: He's happy to expose the differences because platforms have different behaviors. That's how I interpret his statement on this. I will confirm.
<dandclark> ...: Should I file new issue to add getTargetRanges?
<dandclark> I to confirm with masayuki and reply

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Agenda+ Queue this item for discussion at the next WG meeting
Projects
None yet
Development

No branches or pull requests

7 participants