简体   繁体   中英

Text Highlighting - Content Editable

I've been experimenting with contenteditable fields in javascript. As you can probably guess, I'm trying to build a WYSIWYG editor. Piecing together answers I found on Stack Overflow, I managed to build this test case . The test case's job is to manually and programmatically highlight text and embolden it. There is just one small problem. If you click the "bold" button once, a substring is highlighted and subsequently made bold. However, if you click it again, it prompts an error:

"Error: Failed to execute 'setStart' on 'Range': There is no child at offset 12.
at Error (native)
at HTMLInputElement.<anonymous> (http://run.jsbin.io/runner:15:13)
at HTMLDocument.oa (http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js:18:373)
at HTMLDocument.c.event.handle (http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js:55:307)
at HTMLDocument.j.handle.o (http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js:49:363)"

After the first button press, the text field representing the WYSIWYG editor's content contains the following:

Some text he<span style="font-weight: bold;">re for y</span>ou to bold

Upon testing (by outputting the first child's length), my hypothesis is that it's trying to highlight only the first part - "Some text he." Further testing, including commenting out the statement to embolden the selection, confirmed this, I believe. In fact, when this is commented out the editor works well.

I searched on Google and Stack Exchange, yet partially due to my ignorance as to why this is happening I could find nothing.

My question is therefore - why is this error appearing, and what can I do to avoid it and reach my goal of programmatically highlighting and embolding this text?

Referring to your linked demo code, you're setting the range with this code:

range.setStart(mainDiv.firstChild, 12);
range.setEnd(mainDiv.firstChild, 20);

But mainDiv.firstChild is the first text node of main div. On initial run that text node is

Some text here for you to bold

After the first run that text node gets broken into three pieces: 1 before the bold, one inside the bold, and one after.

Some text he<span style="font-weight: bold;">re for y</span>ou to bold

So your mainDiv.firstChild becomes

Some text he

For that reason the call to range.setEnd(mainDiv.firstChild, 20) is out of range.

To avoid this, don't hard-code your calls to setRange. Instead get your ranges directly from user selection (a very common case) or after inspecting the actual DOM just prior to making the call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM