4

我正在尝试为使用基于语法的格式的网页创建一个 JavaScript 编辑器。它完全取代innerHTML<pre>使用onkeyup. 但是,这会导致插入符号被移动到编辑器的开头。

我能找到的唯一解决方案是在进行更改之前获取选择开始和结束的偏移量,然后在最后设置它们。我用于获取选择开始和结束的代码是从https://stackoverflow.com/a/4812022/2093695修改的:

var selStart, selEnd;
if (typeof window.getSelection != "undefined") {
    var range = window.getSelection().getRangeAt(0);
    var preCaretRange = range.cloneRange();
    preCaretRange.selectNodeContents(editor);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    selStart = preCaretRange.toString().length;
    selEnd = selStart + range.toString().length;
} else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
    var textRange = document.selection.createRange();
    var preCaretTextRange = document.body.createTextRange();
    preCaretTextRange.moveToElementText(editor);
    preCaretTextRange.setEndPoint("EndToEnd", textRange);
    selStart = preCaretTextRange.text.length;
    selEnd = selStart + textRange.text.length;
} else selStart = 0;

至少在 Firefox 中,这部分工作正常。我的问题是设置选择。到目前为止,我所拥有的如下:

// restore selection
if (selStart) {
    if (range) {
        range = window.getSelection().getRangeAt(0);
        range.setStart(editor,selStart);
        range.setEnd(editor,selEnd);
        // Doesn't work, in FF at least
        // Behavior: when there are no tags,
        //     for 0, caret set at beginning
        //     for 1, caret set at end
        //     for anything greater, "IndexSizeError: Index or size is negative or greater than the allowed amount"
        // when the editor contains tags,
        //     for 0, caret set at beginning of editor
        //     for 1, caret set at beginning of first tag (unless same as start of editor)
        //     for 2, caret set at end of first tag
        //     for 3, caret set at beginning of second tag
        //     for 4, caret set at end of second tag, and so on
        //     for a number that is 1 greater than whatever number would set the caret at the end of the last tag, caret set at end of editor
        //     for a number greater than that, same error as before
    } else if (document.selection && document.selection.createRange) {
        // Not sure what to do here
    }
}

那是如何setStartsetEnd应该工作的?我究竟做错了什么?有没有更好的方法来设置选择的开始和结束,最好不使用库?

4

1 回答 1

6

我为此发布了几个不同的功能。我找不到我最近的一个,但下面有一个指向 jsFiddle 的链接,其中包含一个restoreSelection()应该有用的函数:

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

更新:我找到了此代码的更新版本。它应该工作相同,但内部更优雅一点。

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

于 2013-04-05T08:52:38.383 回答