2010-04-19 98 views
1

我想指定firefox选择一个范围。我可以轻松地使用IE,使用range.select();.看来,FFX预计一个DOM元素。我错了吗,还是有更好的方法去解决这个问题?范围选择和Mozilla

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

// 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一直没有合作的,这不工作。有任何想法吗?

+0

你能告诉我们一些代码?这会让我们更容易看到发生了什么。我想你读了https://developer.mozilla.org/en/DOM/Selection – 2010-04-19 23:31:44

回答

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,铬和Opera测试此,调试工具显示,在调用reselectFuncremoveAllRanges,既savedRangeorigRange后复位。有这样一个对象调用addRange导致异常在Firefox中被抛出:

未捕获的异常:[异常... “无法把JavaScript参数 ARG 0 nsISelection.addRange]” nsresult:“0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)” 位置: “JS帧:: 文件:///home/mk/tests/addrange.html :: 匿名::线19” 的数据:无]

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

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

+0

谢谢,这是有帮助的,但我不认为完全解决了我的问题。他使用“字段”,我认为这意味着文本在textarea/input中。我希望能够跨多个DOM元素(因此是一个片段)设置范围和选择。你知道如何做到这一点吗? – Matrym 2010-04-19 23:46:11

+0

@Matrym:我在编辑问题后添加了一个测试用例 – 2010-04-20 01:46:31

0

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

我不能这样做,即使没有你,并授予你正确的答案吧: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> 
+0

呵呵。我不得不将它切换回s.removeAllRanges();因为chrome不会另外识别它。但是,这样做是可以的 - 只要首先克隆原始选择范围。 – Matrym 2010-04-20 06:55:19

+0

不客气(尽管我认为这种行为很奇怪,但我会为此提出另一个问题)。一个警告:不要使用像's'这样的短全局变量(甚至是'''),因为浏览器中的其他组件可能也会使用它们,导致意外行为(最好是使用一个全局对象变量,函数,对象等)被分配)。 – 2010-04-20 11:33:24

+0

这可能会让你感兴趣:http://blog.siteroller.net/understanding-javascript-selection-and-range – SamGoody 2011-02-09 09:08:34