I'm working on a simply syntax highlighter that replaces text with dom elements with classes.
Say, I have a
<div contenteditable="true">
Some text. | And some other text.
</div>
and the cursor is at the | pipe
//if a user types foo
<div contenteditable="true">
Some text. foo| And some other text.
</div>
// and I replace it, then set the selection after the inserted element
<div contenteditable="true">
Some text. <span class="highlight-foo">foo</span>| And some other text.
</div>
but if you type, you type into the span..no matter what.
//type bar
<div contenteditable="true">
Some text. <span class="highlight-foo">foobar|</span> And some other text.
</div>
and I don't want that, but I can't set the selection right after the newly inserted element.
<div contenteditable="true">
Some text. <span class="highlight-foo">foo</span>bar| And some other text.
</div>
here's the js that does the highlighting and replacing..
...
// chunk is the variable that holds foo, if we stick the the above example..
// select it
range.setStart(range.startContainer, range.startOffset-chunk.length);
// add it to the range
sel.addRange(range);
// replace it..then set the range to the textNode after the span
// because after the injection selection.anchorNode is the textNode inside the span..
// in chrome, however, this below sets the range correctly.
range.setStart(sel.anchorNode.parentNode.nextSibling, 0);
// and it's all good until now, but adding the range to the selection does nothing..
sel.removeAllRanges();
sel.addRange(range)
// the selection is still inside the span..
How to solve that? oO I've read a lot on it even looked a fair amount of questions on here, but nothing regarding this particular problem.
I assume you're testing this in WebKit. WebKit's caret handling prevents you from placing the caret at the start of a text node: https://bugs.webkit.org/show_bug.cgi?id=23189. In Firefox your code should be fine.
The workarounds are all horrible. One is to insert a zero-width space (such as
\u200B
) and select it, but then you have add special code to handle arrow keys and code to remove the zero-width spaces.Update
Another workaround is to use the fact that WebKit has a special case for links where it forces the caret to go after the link:
http://jsfiddle.net/RfMju/
So what you could do, which is unpleasant but doable, is to use a
<span>
when you want the caret to go inside the highlighted element and change it into a link otherwise.