在Firefox中,修改从选择中克隆的范围会在第一次时清除选择

时间:2009-03-20 10:55:16

标签: javascript firefox

<script>
    var is_gecko = /gecko/i.test(navigator.userAgent);
    var is_ie    = /MSIE/.test(navigator.userAgent);

    function insertNodeAtSelStart()
    {
        if(is_gecko)
        {
            var S = window.getSelection();
            if(!S.isCollapsed)
            {
                var R = S.getRangeAt(0);
                var R1 = R.cloneRange();
                var NN = document.createElement("startMarker");
                R1.insertNode(NN);
                NN.parentNode.removeChild(NN);
            }
        }

        if(is_ie)
        {
            // IE-specific code
        }
    }
</script>

<div>
    <span>one two three</span>
</div>

<input type="button" value="Insert node at selection start" onclick="insertNodeAtSelStart();" />

首次在加载页面并选择一些文本后单击按钮,Firefox会清除选择。随后,它没有。这是我的代码或Firefox中的错误吗?

2 个答案:

答案 0 :(得分:3)

Firefox通过成功将Node插入其起始点来清除选择。

对我来说,第二次单击有时(取决于选择的文本范围)会失败,并显示:

Error: uncaught exception: [Exception... "Index or size is negative or greater than the allowed amount"  code: "1" nsresult: "0x80530001 (NS_ERROR_DOM_INDEX_SIZE_ERR)"  location: "..."]
在insertNode调用上

。由于插入不成功,因此不会清除选择。大概这就是你正在发生的事情 - 检查你的错误控制台。

此失败似乎确实是Firefox错误。我无法完全找出触发它的确切条件,但它与选择中的节点边界有关。

我可以通过调用document.body.normalize()使整个span内容返回到单个Text节点,然后通过插入/删除循环进行分割,从而使您的示例始终工作(并清除选择)。 / p>

答案 1 :(得分:2)

事实上,你偶然发现了一个丑陋的Gecko虫子,这种虫子在多年的生命中不断爬行:( 是的,最新的开发版本仍然存在这个错误。

无论如何,如果您不想等待Mozilla的修复,更简单/更快的解决方法是在插入新节点之前折叠范围。

为了符合,这里是用于测试代码的(某种程度上简化的)样本:

<p id="para">select two or more letters, then </p>
<input id="butt" type="button" value="click me">
<script type="text/javascript">
  if (!window.getSelection)
    throw new Error("MSIE, you're not welcome!");

  var marker = document.createElement('span');
  marker.style.color = '#6C6';
  marker.appendChild(document.createTextNode('|'));

  function insertNodeAtSelStart() {
    // window.getSelection().getRangeAt(0).insertNode(marker.cloneNode(true));
    var r = window.getSelection().getRangeAt(0);
    var n = marker.cloneNode(true);
    r.collapse(true); // workaround for Gecko :(
    r.insertNode(n);  // Gecko sometimes(?!) fails with NS_ERROR_DOM_INDEX_SIZE_ERR
  }
  document.getElementById('butt').onclick = insertNodeAtSelStart;
</script>

OT,那不是“is _ gecko”,“is _ not _ ie”会更合适,因为这个代码应该在除MSIE之外的每个浏览器上按预期运行; - )