2010-04-19 177 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