这是什么问题?

if ( window.getSelection() )
  EditField = window.getSelection().getRangeAt(0);

引发错误:

最佳答案

这个问题似乎是WebKit特有的。我无法在IE或Firefox中复制它。如OP所述,Google Chrome上的错误是:



Safari存在相同的问题,但消息有所不同:



通常发生在简单的WYSIWYG编辑器中。例子:

<form name="frm">
    <div contenteditable="true" style="border:1px solid grey;height:8em;width:100%;">
    Text inside my editor.
    </div>
    Click this button to insert some text into the text editor:
    <button type="button" onclick="doInsert('TEST');">Insert</button>
</form>

<script>
    function doInsert(text) {
        var sel = window.getSelection && window.getSelection();
        if (sel) {
            var range = sel.getRangeAt(0);              // error here
            var node = document.createTextNode(text);
            range.deleteContents();
            range.insertNode(node);
        }
    }
</script>


页面加载后,单击按钮;您将在JavaScript控制台(Chrome)或错误控制台(Safari)中看到错误消息。但是,如果在单击按钮之前单击编辑器部分内的任何位置,则不会发生该错误。

这个问题很容易预防;始终在调用rangeCount之前检查getRangeAt:
function doInsert(text) {
    var sel = window.getSelection && window.getSelection();
    if (sel && sel.rangeCount > 0) {
        var range = sel.getRangeAt(0);
        ...

当然,可以通过在页面加载时给予编辑器焦点(使用focus方法)来避免这种情况。

但是,有些罕见的事件会导致您的编辑器稍后失去选择范围。到目前为止,我只能使用多选列表控件来重现此内容:

<form name="frm">
  <div contenteditable="true" style="border:1px solid grey;height:8em;width:100%;">
    Click to position the caret anywhere inside this editor section.
  </div>
  Next, select an item from this list:
  <select id="insertables" multiple="multiple">
    <option>foo</option>
    <option>bar</option>
    <option>baz</option>
  </select>
  <br />Finally, click this button to insert the list item into the text editor:
  <button type="button" onclick="doInsert(frm.insertables.value);">Insert</button>
</form>

<script>
  function doInsert(text) {
    var sel = window.getSelection && window.getSelection();
    if (sel) {
      var range = sel.getRangeAt(0); // error here
      var node = document.createTextNode(text);
      range.deleteContents();
      range.insertNode(node);
    }
  }
</script>


同样,我可以通过检查rangeCount来防止错误。但是问题仍然出在,我的按钮没有像预期那样在最后的已知插入号位置插入所选列表项。方法focus没有帮助;它将插入符号的位置重置为编辑器中的左上角位置。

一种解决方案是连续保存当前选择范围(为此,捕获事件SelectionChange):
var savedRange = null;

document.addEventListener("selectionchange", HandleSelectionChange, false);

function HandleSelectionChange() {
    var sel = window.getSelection && window.getSelection();
    if (sel && sel.rangeCount > 0) {
        savedRange = sel.getRangeAt(0);
    }
}

并在单击按钮时将其还原:
function doInsert(text) {
    var sel = window.getSelection && window.getSelection();
    if (sel && sel.rangeCount == 0 && savedRange != null) {
        sel.addRange(savedRange);
    }
    if (sel && sel.rangeCount > 0) {
        var range = sel.getRangeAt(0);
        var node = document.createTextNode(text);
        range.deleteContents();
        range.insertNode(node);
    }
}

fiddle :http://jsfiddle.net/stXDu/

09-10 11:16