【问题标题】:Range Selection and Mozilla范围选择和 Mozilla
【发布时间】:2010-04-20 12:48:22
【问题描述】:

我想指定firefox选择一个范围。我可以使用 IE 轻松做到这一点,使用 range.select();。 FFX 似乎需要一个 dom 元素。是我弄错了,还是有更好的方法来解决这个问题?

我首先获取文本选择,将其转换为范围(我认为?)并保存文本选择。这是我最初得到范围的地方:

    // Before modifying selection, save it
    var userSelection,selectedText = '';
    if(window.getSelection){
        userSelection=window.getSelection();
    }
    else if(document.selection){
        userSelection=document.selection.createRange();
    }
    selectedText=userSelection;
    if(userSelection.text){
        selectedText=userSelection.text;        
    }
    if(/msie|MSIE/.test(navigator.userAgent) == false){
        selectedText=selectedText.toString();
    }
    origRange = userSelection;

我稍后更改了选择(成功)。我通过 IE 中的范围和 ffx 中的 dom ID 来执行此操作。但是在我这样做之后,我想将选择设置回到原来的选择。

这在 IE 中就像一个魅力:

setTimeout(function(){
    origRange.select();
},1000);

我想在 FFX 中做这样的事情:

var s = w.getSelection();
setTimeout(function(){
    s.removeAllRanges();
    s.addRange(origRange);
},1000);

很遗憾,FFX 不合作,这不起作用。有什么想法吗?

【问题讨论】:

标签: javascript firefox range selection getselection


【解决方案1】:

简短的回答是:IE 和其他浏览器在使用 JavaScript 选择文本的实现上有所不同(IE 有其专有的方法)。看看Selecting text with JavaScript

另外,请参阅 MDC 的 setSelectionRange

编辑:做一个小测试用例后,问题就清楚了。

<!DOCTYPE html>
<html>   
  <head> 
    <meta charset="UTF-8">
    <title>addRange test</title>
    <style>
      #trigger { background: lightgreen }
    </style>
  </head>
  <body> 
    <p id="test">This is some (rather short) text.</p>
    <span id="trigger">Trigger testCase().</span>
    <script>
var origRange;

var reselectFunc = function () {
    var savedRange = origRange;
    savedRange.removeAllRanges();
    savedRange.addRange(origRange);
};

var testCase = function () {
    // Before modifying selection, save it
    var userSelection,selectedText = '';

    if(window.getSelection){
        userSelection=window.getSelection();
    }
    else if(document.selection){
        userSelection=document.selection.createRange();
    }
    selectedText=userSelection;
    if(userSelection.text){
        selectedText=userSelection.text;
    }
    if(/msie|MSIE/.test(navigator.userAgent) === false){
        /* you shouldn't do this kind of browser sniffing,
           users of Opera and WebKit based browsers
           can easily spoof the UA string */
        selectedText=selectedText.toString();
    }
    origRange = userSelection;

    window.setTimeout(reselectFunc, 1000);
};

window.onload = function () {
    var el = document.getElementById("trigger");
    el.onmouseover = testCase;
};
    </script>
  </body>
</html>

在 Firefox、Chromium 和 Opera 中测试时,调试工具显示在 reselectFunc 中调用 removeAllRanges 后,savedRangeorigRange 都被重置。使用这样的对象调用 addRange 会导致 Firefox 中抛出异常:

未捕获的异常:[异常... “无法转换 JavaScript 参数 参数 0 [nsISelection.addRange]" nsresult:“0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" 位置:“JS框架:: 文件:///home/mk/tests/addrange.html :: 匿名 :: 第 19 行”数据:无]

不用说在所有三个浏览器中都没有选择文本。

显然这是预期的行为。在调用 removeAllRanges 后,所有分配了 (DOM)Selection 对象的变量都会被重置。

【讨论】:

  • 谢谢,这很有帮助,但我认为不能完全解决我的问题。他正在使用“字段”,我认为这意味着文本在文本区域/输入中。我希望能够跨多个 dom 元素(因此是片段)设置范围和选择。你知道怎么做吗?
【解决方案2】:

谢谢马塞尔。你是对的,诀窍是克隆范围,然后删除特定的原始范围。这样我们就可以恢复到克隆的范围。您的帮助使我找到了以下代码,它将选择切换到其他地方,然后根据超时返回。

如果没有你,我无法做到这一点,并给你正确的答案:D

<!DOCTYPE html>
<html>   
<head> 
    <meta charset="UTF-8">
    <title>addRange test</title>
    <style>
      #trigger { background: lightgreen }
    </style>
  </head>
  <body> 
    <p id="switch">Switch to this text</p>
    <p id="test">This is some (rather short) text.</p>
    <span id="trigger">Trigger testCase().</span>
    <script>
var origRange;
var s = window.getSelection();

var reselectFunc = function () {
     s.removeAllRanges();
     s.addRange(origRange);
};

var testCase = function () {
// Before modifying selection, save it
var userSelection,selectedText = '';

if(window.getSelection){
    userSelection=window.getSelection();
}
else if(document.selection){
    userSelection=document.selection.createRange();
}
selectedText=userSelection;
if(userSelection.text){
    selectedText=userSelection.text;
}
if(/msie|MSIE/.test(navigator.userAgent) === false){
    /* you shouldn't do this kind of browser sniffing,
       users of Opera and WebKit based browsers
       can easily spoof the UA string */
    selectedText=selectedText.toString();
}
origRange = userSelection;




 var range = s.getRangeAt(0);
 origRange = range.cloneRange();
 var sasDom = document.getElementById("switch");
 s.removeRange(range);
 range.selectNode(sasDom);
 s.addRange(range);

window.setTimeout(reselectFunc, 1000);
};
window.onload = function () {
    var el = document.getElementById("trigger");
    el.onmouseover = testCase;
};
    </script>
</body>
</html>

【讨论】:

  • 嗯。我不得不将它切换回 s.removeAllRanges();因为chrome无法识别它。但是,这样做是可以的 - 只要先从原始选择范围进行克隆。
  • 不客气(虽然我认为这种行为很奇怪,但我会为此提出另一个问题)。一个警告:不要使用像s(甚至i)这样的短全局变量,因为浏览器中的其他组件也可能使用它们,从而导致意外行为(最好是使用一个全局对象,所有其他变量、函数、对象等被赋值)。
  • 这可能会让你感兴趣:blog.siteroller.net/…
猜你喜欢
  • 2010-09-18
  • 2018-03-08
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2015-01-17
相关资源
最近更新 更多