Javascript Firefox三次单击选择返回错误的开始和结束偏移

Javascript Firefox三次单击选择返回错误的开始和结束偏移,javascript,html,firefox,selection,Javascript,Html,Firefox,Selection,我有一段代码,它应该返回用户选择的开始和结束偏移量: <!DOCTYPE html> <html> <head> <script type="text/javascript"> function getSelRange() { var selObj = window.getSelection(); var range = selObj.getRangeAt(0); alert(range.s

我有一段代码,它应该返回用户选择的开始和结束偏移量:

<!DOCTYPE html>
 <html>
  <head>
   <script type="text/javascript">
    function getSelRange() {
      var selObj = window.getSelection();
      var range  = selObj.getRangeAt(0);
      alert(range.startOffset+"-"+range.endOffset);
    }

   </script>
  </head>
  <body>
    <button onclick="getSelRange()">Get the selected text!</button>
    <p>Select some text!</p>
  </body>
</html>

函数getSelRange(){
var selObj=window.getSelection();
变量范围=selObj.getRangeAt(0);
警报(范围.startOffset+“-”+范围.endOffset);
}
获取所选文本!
选择一些文本

当我通过拖动从
p
中选择一些文本时,它会正确地提醒数字。但是,当我在
p
中通过三次单击选择整个文本时,它会向0-1发出警报。看起来只有在Firefox中,三次单击不能正确返回选择范围

如何在三次单击时获得正确的起点和终点?

(更新) 我已经在一种方式,它将工作在三次点击时,段落包含多行

<script>
    function getSelRange() {
        var selObj = window.getSelection();
        var range = selObj.getRangeAt(0);
        var r = document.getElementById('txt').innerHTML.split('<br>');

        if (r[(range.endOffset-1)/2] == selObj) {
            alert(0+"-"+r[(range.endOffset-1)/2].length);
        } else if (range.startOffset >= range.endOffset) {
            alert(range.startOffset + "-" + r[(range.endOffset-1)/2].length);
        } else {
            alert(range.startOffset + "-" + range.endOffset);
        }  
    }
</script>

函数getSelRange(){
var selObj=window.getSelection();
变量范围=selObj.getRangeAt(0);
var r=document.getElementById('txt').innerHTML.split('
'); if(r[(范围内偏移-1)/2]==selObj){ 警报(0+“-”+r[(range.endOffset-1)/2]。长度); }else if(range.startOffset>=range.endOffset){ 警报(range.startOffset+“-”+r[(range.endOffset-1)/2]。长度); }否则{ 警报(range.startOffset+“-”+range.endOffset); } }


函数getSelRange(){
var selObj=window.getSelection();
变量范围=selObj.getRangeAt(0);
var r=document.getElementById('txt').innerHTML.split('
'); var selLines=selObj.toString().split('\n'); var Str=document.getElementById('txt').innerHTML; Str=Str.replace(/
/g,“xzznlzzx”); var pr=selObj.toString()。替换(/\r?\n/g,“xzznlzzx”); var rStr=Str.substring(0,Str.indexOf(pr)); var rSplit=rStr.split('xzznlzzx'); var prSplit=pr.split('xzznlzzx'); var countStart=0; var countEnd=0; var i=0;
for(;iFirefox正在返回正确的范围。问题在于,您认为范围必须具有相对于文本节点的起始和结束边界的假设是不正确的

所发生的事情是,Firefox报告的范围从
元素的第零个子节点开始,到
元素的第一个子节点结束。这是完全有效的

您可以执行以下操作来调整此范围,使其边界位于
元素的文本节点内:

演示:

代码:


它几乎可以工作,但是如果我将
p
的内部HTML更改为
检查
Foo
使其成为两行,那么如果我通过三次单击选择其中一行,它仍然返回
0-1
。谢谢。但是现在另一个问题是,如果通过拖动和跨越多行来进行选择,比如说从第二行的中间第三行的中间,开始和结束都是相对于相应的行单独计算的。您能告诉我选择多行时需要什么输出吗?我想要开始和结束,就像
p
中的整个文本是一次性的,没有

@Cupidvogel我添加了一个新提琴代码有点长,因为它需要很多检查才能工作。希望这对您有所帮助。这与我在answer@Zword当前位置一些例子可能是这样。总的来说,它们根本不一样。我真的不明白你的答案是什么。哈哈,当问题出现时,我总能期待蒂姆的回答rns选择范围:)@Cupidvogel:没有几年那么可靠ago@Marc:不是这样的bug。Rangy抽象了API的差异(主要是
<script>
function getSelRange() {
    var selObj = window.getSelection();
    var range  = selObj.getRangeAt(0);
    var r=document.getElementById('txt').innerHTML.split('<br>');
    var selLines = selObj.toString().split('\n');

    var Str = document.getElementById('txt').innerHTML;
    Str=Str.replace(/<br>/g,"xzznlzzx");
    var pr=selObj.toString().replace(/\r?\n/g,"xzznlzzx");
    var rStr=Str.substring(0,Str.indexOf(pr));

    var rSplit=rStr.split('xzznlzzx');
    var prSplit=pr.split('xzznlzzx');

    var countStart=0;
    var countEnd=0;
    var i=0;
    for(;i<(rSplit.length-1);i++)
    {
        countStart=countStart+r[i].length;
    }
    for(j=0;j<(prSplit.length-1);i++,j++)
    {
        countEnd=countEnd+r[i].length;
    }

    countEnd=countEnd+countStart;
    if(r[(range.endOffset-1)/2]==selObj)
    {
    alert((0+countStart)+"-"+(r[(range.endOffset-1)/2].length+countEnd));
    }
    else{
        if(r[i].length<selObj.toString().length)
        {
        var indx = selObj.toString().indexOf(r[i]);
        }
        else{
        var indx = r[i].indexOf(selObj.toString());
        var vals=selObj.toString().length;
        var res = r[i].substring(indx+vals,indx+vals+1);
        if(res==""){indx=1}
        else{indx=-1}
        }
        if(indx!=-1)
        {
        alert((range.startOffset+countStart)+"-"+(r[i].length+countEnd));
        }
        else{
        alert((range.startOffset+countStart)+"-"+(range.endOffset+countEnd));
        }
    } 
}
</script>
function adjustRange(range) {
    range = range.cloneRange();
    if (range.startContainer.nodeType != 3) {
        var nodeAfterStart = range.startContainer.childNodes[range.startOffset];
        if (nodeAfterStart && nodeAfterStart.nodeType == 3) {
            range.setStart(nodeAfterStart, 0);
        }
    }
    if (range.endContainer.nodeType != 3 && range.endOffset >= 1) {
        var nodeBeforeEnd = range.endContainer.childNodes[range.endOffset - 1];
        if (nodeBeforeEnd && nodeBeforeEnd.nodeType == 3) {
            range.setEnd(nodeBeforeEnd, nodeBeforeEnd.data.length);
        }
    }
    return range;
}