-
Notifications
You must be signed in to change notification settings - Fork 40
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
contentEditable: clarification of selection and typing behavior #156
Comments
+@johanneswilm |
@rakuco You can try that. There is not always a great audience for such questions though. If you write to the list, link to this issue so we can have the discussion here. |
Personally I am still a bit torn whether or not this is important. The replacement of the existing DOM content will in most cases be something the JS editor will want to control. JS editors also tend to not like it when selections change "automagically" because the browser thinks this is a good idea. On the other hand, the selections should probably be the same. And if doing roughly the same thing in different browsers leads to entirely different selections, the JS editor will need to spend more time trying to standardize these selections before action on the insertion of new content. |
I believe, that there are two perspectives when talking about RTEs. For those which don't implement a custom data model, it'd be great if it was consistent across browser and if the behaviour wasn't magical. For example, Chrome has that "funny" behaviour that deleting the content of The situation may be different in case of RTEs with a custom data model. I don't know how it works in e.g. ProseMirror or Draft, but in CKEditor 5 we built an abstraction over the data and selection and we handle content modifications manually in the model and re-render the DOM if needed. Due to the fact that See https://twitter.com/pomekPL/status/740149101334016000 for how the text attributes are represented. They are just a properties of characters. Hence these two positions: Anyway, you can test how we decided to implement the case with typing over the link on https://ckeditor5.github.io – the link is always fully removed and the typed text isn't linked. Typing over a non-collapsed selection always triggers first a generic |
PS. I forgot to link to #149 where I wrote more about how CKEditor 5 now handles deleting and typing and how it's going to change with |
PPS. I've just realised that I forgot to mention that replacing a text of a link and text of a bolded word are a different cases in terms of UX. For usability reasons a text of an inserted link needs to be replaceable without losing the link style. TBH, we're still thinking on how to best solve this. If we'll decide to modify the behaviour of typing over a link it will be that deleting the link will not reset selection's attributes. It will be consistently handled in all situations where the generic "delete content" algorithm is used. |
As far as I have seen, both editors with and without a data model largely try to control what change happens in the DOM. But you are right, sometimes this means reverting changes that have occurred already due to the lack of the beforeinput event. Another reason for why some let native handling go through and then revert afterward seems to be that otherwise the native browser spell checking doesn't understand what word should be underlined. And I one editor also let undo/redo events go through first when the undo undos auto-correct or spellchecking (and then it cleans the DOM afterward), because this way the browser ";learns" that a particular auto-correct or spell checking is undesired. So browser native handling of some input still occurs sometimes with some editors, but at least I have not seen where this is happening in an "uncontrolled" manner, where the editor just lets stuff happen and then doesn't try to clean it up/standardize it afterward. Or which editors are you thinking of that let the browser handle uncontrolled DOM-changes (without time traveling backward)? What is definitely out of style is using execCommand except when there is no other way (clipboard-based events). So if part of the bug here is that execCommand does something inconsistent, I think all the JS editor projects would prefer if you could instead work on something that they use a lot more than fixing execCommand. Or what do you think @Reinmar? |
Yes, fixing
Hard for me to tell, because I don't know anything specific about any other editor than CKEditor, but I'd presume that all RTEs without a custom data model (and perhaps, to some extent, even some with custom data models) let the browser insert and delete text without much control. In other words – these RTEs behaviour would change if browsers would change their "type over" behaviour. The group of editors with custom data models is pretty small (it's a great minority in fact), because developing such an RTE is extremely hard and long process. The one I know of are CKEditor 5, Quill, ProseMirror, Draft.js and Trix. |
You may be right that those editors exist. I just want to make sure that we don't spend a lot of time working features that effectively no-one is using. For the undo behavior, for example, I contacted all the editors I could find, and none of them let just the browser built-in undo work by itself, and everyone had their own undo manager[1], even those that I don't think have started working on an outright data-model. Now that is of course slightly different than whether one lets the browser handle text input, but if one does manage one's own undo-stack, but at least it means that the JS will have to record what changed on every user input.
I think this depends a lot on the editor and the contents. For example, in links, I usually want to be able to escape them when writing at either end. For bold text the same behavior would be ultra-annoying. Or so I think right now. I am not sure that hard-coding either behavior into browsers is the right path. It's more something that editor projects like CKEditor and similar should experiment with. They'all also be the only ones who can really effectively make the right decision when it comes to "custom" text types such as "piece of text that is visually 'linked' to a comment that is floating to the right of it". But in order for them to be able to do that easily, it may be slightly easier if the selections were always the same (so one doesn't have to have code that checks whether all contents of a node have been selected and then select the node itself in some browsers and not in others). But then again, CKEditor seems to have this figured out, and the others will probably manage to do that as well eventually. [1] #150 (comment) |
This discussion started in Blink bug 663638.
The context
Consider the following snippet:
It is not clear what the behavior should be when a user selects "selectMeAndTypeOver" (i.e. the entirety of the text node within the
<a>
node) and types something else.What I could gather from Blink (M57) and Gecko (Firefox 50) so far is this:
Gecko
document.getSelection()
returns aSelection
object with the<div>
as both anchor and focus nodes (anchorOffset==1
,focusOffset==2
).document.execCommand("insertText", false, "foo")
replaces the entire<a>
node with a new text node. That is,document.getElementById("sample").childNodes
returns 3 text nodes.<a>
node and replaces it with a text node whose contents are whatever is being typed.document.getSelection()
returns aSelection
object with theselectMeAndTypeOver
text node as the anchor (anchorOffset==0
) and thedef
text node as the focus (focusOffset==0
).document.execCommand("insertText", false, "foo")
replaces the contents of text node within the<a>
node with "foo". That is,document.getElementById("sample").childNodes
returns 3 nodes, the second being<a>
.<a>
to be replaced, while<a>
itself remains in the tree.<a>
node or a sibling text node:electMeAndTypeOve
and is moved to either|selectMeAndTypeOver
orselectMeAndTypeOver|
, the new text is added to the existing text node inside . In other words, the contents of the link changes, but the link remains the same.|selectMeAndTypeOver
, the new text is appended to the "abc " text node (it does not become part of the link node).selectMeAndTypeOver|
, the new text is added to the " def" text node (it does not become part of the link node).Blink
document.getSelection()
returns aSelection
object with theselectMeAndTypeOver
text node as both anchor and focus (anchorOffset==0
,focusOffset==19
).document.execCommand("insertText", false, "foo")
replaces the contents of the text node within the<a>
node with "foo". That is, the link remains but the text is changed.<a>
node, while any further input is added to a new text node that is inserted right after the<a>
node. That is, the first character of the input becomes the link's text and all the rest becomes a new text node adjacent to<a>
(document.getElementById("sample").childNodes
returns 1 text node,<a>
and 2 other text nodes).<a>
node is never touched):|selectMeAndTypeOver
, the new contents are appended to the "abc " text node.selectMeAndTypeOver|
, the new contents are added to a new text node that is inserted between the<a>
node and the " def" text node.I wasn't able to test Edge and Safari, but GNOME Web 3.22.1 with WebKitGTK+ 2.14.11 behaved identically to Blink.
The questions
Selection
object returned bydocument.getSelection()
contain as focus and anchor (and respective offsets)?<a>
node or the contents of the text node inside the<a>
? Or should Blink/WebKit's behavior of just adding the first character to the text node within<a>
be followed?<a>
node or adjacent to it? If it should be adjacent to it, should it be merged into the existing nodes or should new text nodes be created?The text was updated successfully, but these errors were encountered: