代码之家  ›  专栏  ›  技术社区  ›  Dana Robinson

在Internet Explorer中使用精灵按钮和selection.createRange()获取选定文本时出现问题

  •  3
  • Dana Robinson  · 技术社区  · 17 年前

    我正在Stackoverflow心爱的WMD标记编辑器中实现精灵按钮,我遇到了一个奇怪的bug。在所有版本的IE中,单击按钮时所选文本都会丢失,因此,例如,突出显示一段文本并单击代码按钮,就像将光标放置在所选内容的末尾并单击按钮一样。

    例如,强调这一点:

    This
    Is
    Code
    

    点击代码按钮,您将看到:

    This
    Is
    Code`enter code here`
    

    真正奇怪的是,我把原来的非精灵按钮栏留在了 而且效果很好。 其实 所有 按钮和键盘快捷键代码使用相同的 doClick(button) 功能!

    • 旧式无精灵按钮:OK
    • 键盘快捷键:OK
    • 非IE浏览器中的Sprited按钮:正常
    • IE中的Sprited按钮: 世界跆拳道联盟

    我已经把问题归结为打电话给 selection.createRange() 什么也没找到 当点击sprite按钮时。我尝试过使用focus()方法,并确保在 doClick() 但没有快乐。键盘快捷键似乎有效,因为焦点永远不会从输入文本区域丢失。有人能想到一个黑客,让我以某种方式在IE中收集所选文本吗?

    onclick处理程序看起来像这样:

    button.onmouseout = function(){
      this.style.backgroundPosition = this.XShift + " " + normalYShift;
    };
    
    button.onclick = function() {
      if (this.onmouseout) {
        this.onmouseout();
      }
      doClick(this);
    }
    

    我试着移动 onmouseout 呼叫后 doClick 以防这会导致注意力不集中,但这不是问题所在。

    编辑:

    唯一不同的是,在原始按钮代码中,您正在单击图像。在sprite代码中,您正在单击一个列表项 <li> 设置背景图像。也许它试图选择我列表项中不存在的文本?

    /编辑

    实际代码位于我的wmd存储库中 git button-cleanup 支。

    如果你恢复到0d6d1b32bb42a6bd1d4ac4e409a19fdfe8f1ffcc提交,你可以看到两个按钮栏。最上面的一个是精灵,表现出奇怪的行为。底部包含原始按钮栏的残余部分,工作正常。可疑代码位于 setInputAreaSelectionStartEnd() 功能在 TextareaState 对象。

    最后一件我应该提到的事情是,目前,我试图用纯Javascript来保持控件,所以如果可能的话,我想避免用jQuery这样的外部库来修复这个问题。

    谢谢你的帮助!

    2 回复  |  直到 16 年前
        1
  •  4
  •   Dana Robinson    17 年前

    我知道我自己的问题的答案是什么。

    精灵按钮是使用HTML列表和CSS实现的,其中所有列表项都有一个背景图像。使用CSS移动背景图像以显示不同的按钮和状态(如鼠标悬停高亮显示)。标准的CSS按钮打印内容。

    这在IE中运行良好,但有一个例外:当您单击背景图像“按钮”时,IE会尝试选择空列表文本。输入文本区域中的选择消失,当前选择(将由document.selection.createRange()返回)移动到列表项中的空文本。

    对此的修复很简单——我创建了一个变量来缓存选择和一个标志。在IE中,我缓存选择并在mousedown事件处理程序中设置标志。在文本处理中,我检查是否存在标记——如果设置了标记,我将使用缓存的范围,而不是查询document.selection.createRange()。

    以下是一些代码片段:

    wmd.ieCachedRange = null;
    wmd.ieRetardedClick = false;
    
    if(global.isIE) {
      button.onmousedown =  function() { 
        wmd.ieRetardedClick = true;
        wmd.ieCachedRange = document.selection.createRange(); 
      };
    }
    
    
    var range;
    if(wmd.ieRetardedClick && wmd.ieCachedRange) {
      range = wmd.ieCachedRange;
      wmd.ieRetardedClick = false;
    }
    else {
      range = doc.selection.createRange();
    }
    

    解决方案只需要几行代码,避免了弄乱DOM和潜在的布局引擎问题。

    谢谢你的帮助,克里斯托弗。我在思考和谷歌搜索你的答案时想出了答案。

        2
  •  0
  •   Christoph    17 年前

    你必须 blur() IE可以在页面上选择任何其他内容之前单击一个按钮。

    你能提供一个再现错误的最小示例(仅包含相关代码)吗?