Place tags around certain text within contenteditable without moving cursor

左心房为你撑大大i 提交于 2019-12-11 05:40:14

问题


I am working on a simple (I thought) word processor. It uses contenteditable. I have a list of words that I want to always appear highlighted.

<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>

So basically what I need is a way to wrap a word in <span> tags. This has proven more difficult than I expected.

Here was what I tried first:

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;

It uses the splice method found here.

And it does exactly what I need it to do, with one big issue: the cursor gets moved. Because all the text is replaced, the cursor loses its place, which isn't a good thing for a text editor.

I've also tried a couple times using document.createRange, but the issue is that while given the start and end points of a range only includes visible characters, text.indexOf("highlight") gives the index including the tags and such.

A few ideas which I'm not sure how to execute:

  • Figure out where the cursor begins and place it there again after using the code above
  • Find the difference in indexes between createRange and indexOf
  • Maybe there's already a library with this kind of functionality that I just can't find

Thank you for your help!


回答1:


Firstly, I would recommend against doing this by manipulating innerHTML. It's inefficient and error-prone (think of the case where the content contains an element with a class of "highlight", for example). Here's an example of doing this using DOM methods to manipulate the text nodes directly:

https://stackoverflow.com/a/10618517/96100

Maintaining the caret position can be achieved a number of ways. You could use a character offset-based approach, which has some disadvantages due to not considering line breaks implied by <br> and block elements but is relatively simple. Alternatively, you could use the selection save and restore module of my Rangy library, which may be overkill for your needs, but the same approach could be used.

Here is an example using the first approach:

http://jsbin.com/suwogaha/1



来源:https://stackoverflow.com/questions/24682716/place-tags-around-certain-text-within-contenteditable-without-moving-cursor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!