js contenteditable - 防止写入新插入的元素

ten*_*hou 2 javascript range selection contenteditable

我正在研究一种简单的语法高亮显示,用dom元素替换带有类的文本.

说,我有一个

<div contenteditable="true">
  Some text. | And some other text.
</div>
Run Code Online (Sandbox Code Playgroud)

并且光标位于| 管

//如果用户输入 foo

<div contenteditable="true">
  Some text. foo| And some other text.
</div>
Run Code Online (Sandbox Code Playgroud)

//我替换它,然后在插入的元素后设置选择

<div contenteditable="true">
  Some text. <span class="highlight-foo">foo</span>| And some other text.
</div>
Run Code Online (Sandbox Code Playgroud)

但如果你输入,你输入跨度......无论如何.

//键入栏

<div contenteditable="true">
  Some text. <span class="highlight-foo">foobar|</span> And some other text.
</div>
Run Code Online (Sandbox Code Playgroud)

我不希望这样,但我不能在新插入的元素后立即设置选择.

<div contenteditable="true">
  Some text. <span class="highlight-foo">foo</span>bar| And some other text.
</div>
Run Code Online (Sandbox Code Playgroud)

这是突出显示和替换的js ..

...
// 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..
Run Code Online (Sandbox Code Playgroud)

怎么解决?我在这里看了很多,甚至在这里看了很多问题,但没有关于这个特殊问题.

Tim*_*own 6

我假设你在WebKit中测试它.WebKit的插入处理阻止您将插入符号放在文本节点的开头:https://bugs.webkit.org/show_bug.cgi?id = 23189.在Firefox中,您的代码应该没问题.

解决方法都很可怕.一种是插入一个零宽度空间(例如\u200B)并选择它,但是你需要添加特殊代码来处理箭头键和代码以删除零宽度空格.

更新

另一个解决方法是使用WebKit具有链接的特殊情况这一事实,它强制插入符号在链接之后:

http://jsfiddle.net/RfMju/

所以你可以做的,这是令人不快但可行的,<span>当你想要插入符号突出显示元素并将其更改为链接时,使用a .