我正在开发一个简单的(我认为)文字处理器。它使用 contenteditable。我有一个单词列表,我希望这些单词始终突出显示。
<article contenteditable="true" class="content">
<p>Once upon a time, there were a couple of paragraphs. Some things were <b>bold</b>, and other things were <i>italic.</i></p>
<p>Then down here there was the word highlight. It should have a different color background.</p>
</article>
所以基本上我需要的是一种将单词包装在 <span>
中的方法标签。事实证明这比我预期的要困难。
这是我首先尝试的:
var text = document.querySelector('article.content').innerHTML
start = text.indexOf("highlight"),
end = start + "highlight".length;
text = text.splice(end, 0, "</span>");
text = text.splice(start, 0, "<span>");
document.querySelector('article.content').innerHTML = text;
它使用 splice
找到方法here .
它确实做了我需要它做的事情,但有一个大问题:光标移动了。由于所有文本都被替换,光标会丢失其位置,这对于文本编辑器来说不是一件好事。
我也尝试过使用 document.createRange
几次,但问题是,虽然给定范围的起点和终点仅包含可见字符, text.indexOf("highlight")
给出包括标签等的索引。
一些我不确定如何执行的想法:
- 找出光标开始的位置,并在使用上面的代码后将其再次放置在那里
- 查找
createRange
之间的索引差异和indexOf
- 也许已经有一个具有此类功能的库,但我找不到
感谢您的帮助!
最佳答案
首先,我建议不要通过操纵 innerHTML
来执行此操作。它效率低下且容易出错(例如,考虑内容包含具有“突出显示”类的元素的情况)。下面是使用 DOM 方法直接操作文本节点的示例:
https://stackoverflow.com/a/10618517/96100
可以通过多种方式保持插入符位置。您可以使用 character offset-based approach ,由于不考虑 <br>
隐含的换行符,因此有一些缺点和 block 元素但是比较简单。或者,您可以使用 selection save and restore module我的 Rangy 库,这可能超出了您的需求,但可以使用相同的方法。
这是使用第一种方法的示例:
关于javascript - 将标签放置在 contenteditable 内的某些文本周围,无需移动光标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24682716/