我正在尝试为使用基于语法的格式的网页创建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
}
}
setStart
和setEnd
应该如何运作?我究竟做错了什么?是否有更好的方法来设置选择的开始和结束,最好不使用库?
答案 0 :(得分:6)
我为此发布了几个不同的功能。我找不到我最近的那个,但以下链接到包含restoreSelection()
函数的jsFiddle应该有用:
https://stackoverflow.com/a/7404126/96100
更新:我找到了此代码的最新版本。它应该工作相同,但内部更优雅。