S
SolidJSโ€ข8mo ago
Jules Sommer

createSelection() primitive odd behaviour in contentEditable div's

Now I am not entirely looking for a solution with this post, though one would be appreciated, I believe I am just going to work around this behaviour for my use case. However, when using the createSelection() primitive to get the user selection in a textarea versus a contentEditable div, the behaviour is fairly different and bordering on broken in the case of the contentEditable div ( and I am aware of why this is and will get into that soon ). If you take a look at the attached video, and pay close attention to whenever I input a newline character, moving the cursor to the beginning of that newly created line, in the contentEditable div ( above ) the primitve returns the [start,end] tuple of [0,0] regardless of whether or not there is content on previous lines - contrast this to the textarea where it correctly gets the length of the text previous to the cursor and also accounts for this when the selection is not collapsed, i.e start !== end. I am aware this is because of differences in the window.getSelection() API and the properties available on each DOM element's object representation in TS, we can see this in the source code of the primitive where you'll notice special handling of the textarea and input element cases since those objects have the available selectionStart and selectionEnd properties which simplify the process of fetching these values, and for other cases the function goes on to fallback to the window.getSelection() API:
if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement) {
return setSelection([active, active.selectionStart ?? NaN, active.selectionEnd ?? NaN]);
}
if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement) {
return setSelection([active, active.selectionStart ?? NaN, active.selectionEnd ?? NaN]);
}
Now I suppose my question, or more accurately discussion topic, is what could be done about this in terms of a PR to improve this behavior, or if that should be done at all - for all I know this is the preferred or best possible solution, so I am opening it up to discussion, I suppose. I spent a good couple hours fiddling around with a fork of the primitive and tried to handle it by introducing a special case for contentEditable divs where I would walk the DOM and check for linebreak <br/> elements, which seemed like it would vary between browsers and not at all be performant, but it sort of worked. I tried a few other things, and ultimately decided it wasn't worth the hassle of bending the DOM api's to my will and just decided to use a textarea which would get masked by a div with the rendered content. Thoughts?
GitHub
solid-primitives/packages/selection/src/index.ts at main ยท solidjs-...
A library of high-quality primitives that extend SolidJS reactivity. - solidjs-community/solid-primitives
7 Replies
Alex Lohr
Alex Lohrโ€ข8mo ago
Thank you for the feedback! It is some time since I wrote this primitive. I have put this issue on my to-do list, right after the setup for cookieStorage on the server in the storage package.
Jules Sommer
Jules Sommerโ€ข8mo ago
oh wow I wasn't expecting the author of this primitive to stumble upon this - I am willing to help out with a fix, I assume it wasn't intended behaviour but rather just an edge case. Do you have any ideas better than walking the DOM to determine whether the selection spans multiple Nodes? I was getting frustrated with my attempts since it seems like there should just be a browser API for this......
Alex Lohr
Alex Lohrโ€ข8mo ago
The existing API is supposed to handle even more complex use cases, which explains the complexity.
Jules Sommer
Jules Sommerโ€ข8mo ago
you mean the browser API? the complexity makes sense but why it differs needlessly between elements and browsers is what is frustrating to me. Though I suppose to some degree all web APIs do because the comlpexity can be skipped if all you need is selectionStart and selectionEnd to achieve the use case I am working with but that somehow doesn't exist on a div object with contentEditable={true}
Alex Lohr
Alex Lohrโ€ข8mo ago
Agreed.
spirobel
spirobelโ€ข7mo ago
Do you expect it to become as comprehensive as the lexicaljs abstraction on input events? will we be able to build rich text experiences on top of it that work seamlessly on all devices? ๐Ÿ˜€
Alex Lohr
Alex Lohrโ€ข7mo ago
At some point, hopefully. At the moment, my time constraints are a bit too heavy.
Want results from more Discord servers?
Add your server
More Posts
What's the most idiomatic way of forwarding an onClick event handler?Given a `Button` component that wraps a `<button>`, what's the best way to forward the `onClick` hanLoad more buttonHeres the scenario, i have signal of an array which hold list of words. Then i show them with <For /How is the type of the onclick event ?Hello I have a question about the on-click method of the button, the event doesn't have a type, the Loading CSS issue (FOUC) on optional parameterI have setup a simple website with below route. ``` src โ””โ”€โ”€ routes โ””โ”€โ”€ home โ””โ”€โ”€ index.Any advantages by tanstack libraries for solidjs users?I found that tanstack have some libraries support for solidjs. tanstack query, tanstack table, tanstSetting a deeply nested store property changes produces new reference for property's parent?Wanted to confirm the observed behavior I'm seeing when modifying deeply nested store properties. Can I avoid the getter while keeping the reactivity?```ts const [organization] = useSelectedOrganization(); const formatMoney = () => moneyFormatter(orCombining Solid store with query engine?My app needs to support a wide range of object queries and I want them to be fast, i.e. indexed. SomESLint error: ref is never reassigned, use constWith a farily simple practice app set up with TS + ESLint, there seems to be an issue when using refchildren.forEach typescript problemI have this problem in the forEach with typescript. Property 'forEach' does not exist on type 'Reso