范围选择和Mozilla

时间:2010-04-19 23:01:50

标签: javascript firefox range selection getselection

我想指定firefox选择一个范围。我可以使用range.select();轻松地使用IE。似乎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没有合作,这不起作用。有什么想法吗?

2 个答案:

答案 0 :(得分: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中测试时,调试工具显示在removeAllRanges中调用reselectFunc后,savedRangeorigRange都会重置。使用此类对象调用addRange会导致在Firefox中抛出异常:

  未被捕的例外:[例外......   “无法转换JavaScript参数   arg 0 [nsISelection.addRange]“   nsresult:“0x80570009   (NS_ERROR_XPC_BAD_CONVERT_JS)”   位置:“JS框架::   file:///home/mk/tests/addrange.html ::   anonymous :: line 19“data:no]

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

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

答案 1 :(得分:0)

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

没有你我无法做到,并给你正确答案: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>