Firas Dib
Firas Dib

Reputation: 2621

Retain cursor position in contenteditable

I am trying to create a richtext area using contenteditable. The parser for the highlighting returns a html string which I replace the content of the element with (perhaps ineffective, thats the way it has to be for now).

The problem with contenteditable is that the cursor position is not retained after something like this, which I can understand.

Is there a way to retain this position? I could make the parser return a element representing where the caret should be (given the cursors offset in the text) if this would aid in a solution.

Thanks in advance.

Upvotes: 3

Views: 312

Answers (1)

guest
guest

Reputation: 6698

I could make the parser return a element representing where the caret should be

That would be enough. Suppose you parse the generated HTML and now you have a reference to the caret-should-be-here element in sentinel.

Use document.createRange() to create a DOM range. Let here be the new range. Call here.selectNode(sentinel) to have the range surround the element.

Call here.deleteContents() to remove the dummy element.

Call window.getSelection().removeAllRanges() to clear the current selection, which has gotten messed up by the HTML change.

Call window.getSelection().addRange(here) to put the cursor where the element used to be.


is sentinel my anchor element?

Yeah, I guess.


How do I fetch the cursor position in the string? ... I want the offset from the start of the string.

Let's start with the cursor position. The zeroth range of the window's selection should be the cursor's position. That is, the range's start and end are in the same place, at the cursor. However, these locations are expressed in a way that's geared toward DOM trees, rather than for string and offsets. They have a (start|end)Container and a (start|end)Offset. Check the DOM spec for what these mean.

You're interested in some sort of string offset. As I interpret it, this would be like, if you took a plaintext-only version of the subtree, what index corresponds to the range? There are multiple ways to define a plaintext version of a subtree. One is what the textContent property returns, where foo<br>bar gives "foobar". Some browsers define innerText, where foo<br>bar gives "foor\nbar". You've probably picked the one that you'll be using, but it's not stated in the question.

Anyway, here's an idea, but it might not be the right kind of offset for your app.

Set the window selection to a single range going from the beginning (wherever index 0 should be) to the cursor position.

Read window.getSelection().toString().length. In the browsers I've developed for, toString on a selection object gives results comparable to innerText.

Upvotes: 1

Related Questions