solid-docs icon indicating copy to clipboard operation
solid-docs copied to clipboard

Cursor position resets in contentEditable div

Open alivingspirit opened this issue 3 years ago • 10 comments

When you try to update the content of a contentEditable div or other element the cursor position resets to 0. This makes it impossible to type anything using signals. I'm pretty sure this is not the correct behavior although all my searching does not produce a workaround.

Here is the example. Try to type in the box. https://playground.solidjs.com/?hash=-1236695707&version=1.1.1

alivingspirit avatar Mar 22 '22 04:03 alivingspirit

Hmm this is a tricky issue. There aren't any solutions that don't involve reading the DOM on set, which is terrible for performance. So it's hard to have that the default behavior for any text.

I checked, Svelte does do this check. (set_data looks at wholeText) Vue appears to as well: https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCB7IHJlZiB9IGZyb20gJ3Z1ZSdcblxuY29uc3QgaW5wdXQgPSByZWYoJ0hlbGxvIFdvcmxkIScpXG5cbmZ1bmN0aW9uIGluY3JlbWVudChlKSB7XG4gIGlucHV0LnZhbHVlID0gZS50YXJnZXQudGV4dENvbnRlbnQ7XG59XG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8ZGl2IGNvbnRlbnRlZGl0YWJsZSBAaW5wdXQ9XCJpbmNyZW1lbnRcIj57e2lucHV0fX08L2Rpdj5cbiAgICA8ZGl2PlxuICAgICAge3tpbnB1dH19XG4gICAgPC9kaXY+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0ifQ==

Preact doesn't do the check for children, but does for dangerouslySetInnerHTML: https://github.com/preactjs/preact/issues/2691 Inferno doesn't do the check for children, but does for dangerouslySetInnerHTML or if you set a special flag on the element. React doesn't do the check with children or dangerouslySetInnerHTML Solid doesn't do the check with children or innerHTML

All the VDOM libraries suggest doing some form of uncontrolled as it is the most performant. The simplest version with Solid is: https://playground.solidjs.com/?hash=-1000230651&version=1.3.9

It wouldn't be too hard.. to check innerHTML, and using that is already a de-opt so maybe it's fine. It also might be just worth documenting and leaving as is.

ryansolid avatar Mar 22 '22 07:03 ryansolid

That's actually the normal browser behavior. You can use the getSelectionRange/setSelectionRange API to fix the cursor position after input manually (be sure to calculate the correct position if you added something before the cursor).

atk avatar Mar 22 '22 08:03 atk

@atk @ryansolid Thank you for the detailed response. I think one of or a combination of these options will work for my use case.

alivingspirit avatar Mar 24 '22 23:03 alivingspirit

Ok not sure what we do with this. But I think no action for now. This probably is worth documenting if there is a logical place. But it is really specific to contenteditable. Maybe this issue issue is enough until we find a home. @Jutanium any thoughts?

ryansolid avatar Mar 30 '22 17:03 ryansolid

I think a selection primitive might be a solution. It's on my todo list, but not too far up.

atk avatar Mar 30 '22 17:03 atk

Yeah, I ran into this problem as a Solid beginner, and I think this is something we can add to the FAQ section, or into a guide on the new docs site.

Jutanium avatar Apr 01 '22 14:04 Jutanium

It might interest you that a PR for a selection primitive just landed in @solid-primitives, soon to be released. You'll be able to use it like this:

const [selection, setSelection] = createSelection();
createEffect(() => {
  // store selection
  const selected = selection();
  // writing html will break the selection
  div.innerHTML = html();
  // restore the selection
  setSelection(selected);
});

atk avatar Apr 21 '22 21:04 atk

@solid-primitives/selection is now published, so you can use it.

atk avatar Apr 23 '22 19:04 atk

Amazing! Thank you.

alivingspirit avatar Apr 24 '22 03:04 alivingspirit

Deploy Preview for solid-docs ready!

Name Link
Latest commit 01ef6ca2e2d8ff2f38f20f5805646e91163793c6
Latest deploy log https://app.netlify.com/sites/solid-docs/deploys/62eed48438050f000929e2e7
Deploy Preview https://deploy-preview-128--solid-docs.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

netlify[bot] avatar Aug 06 '22 20:08 netlify[bot]

Thanks for the easy change - please label your PRs next time, though!

Jutanium avatar Aug 06 '22 21:08 Jutanium

please label your PRs @Jutanium What does this means? I can't find a way to label PR.

Priestch avatar Aug 07 '22 06:08 Priestch

I meant name it, so like instead of "update WRITING.md" with no description, describe what you did in the title

Jutanium avatar Aug 07 '22 12:08 Jutanium

Do the solidJS selection primitives work around when a component resides within a Shadow Root? In the research/prototyping I did, browsers behave differently using the Selection API in these cases. Does SolidJS get around this somehow?

luijar avatar Sep 06 '23 13:09 luijar

I don't have a specific workaround. Can you provide a test case to make sure I'm not missing something?

atk avatar Sep 12 '23 07:09 atk