当前位置: 首页 > 面试题库 >

JavaScript获取相对于其父容器的范围的开始和结束偏移量

萧远
2023-03-14
问题内容

假设我有这个HTML元素:

<div id="parent">
 Hello everyone! <a>This is my home page</a>
 <p>Bye!</p>
</div>

并且用户用他的鼠标选择“家”。

我希望能够确定#parent开始选择的字符数(以及#parent选择结束的字符数)。即使他选择了HTML标签,这也应该起作用。(并且我需要它在所有浏览器中都能正常工作)

range.startOffset
看起来很有希望,但是它仅是相对于范围的立即容器的偏移量,并且仅当容器是文本节点时才是字符偏移量。


问题答案:

更新

正如评论中指出的那样,我的原始答案(如下)仅返回选择的结尾或插入符号的位置。修改代码以返回起始偏移量和结束偏移量非常容易;这是一个这样做的例子:

function getSelectionCharacterOffsetWithin(element) {

    var start = 0;

    var end = 0;

    var doc = element.ownerDocument || element.document;

    var win = doc.defaultView || doc.parentWindow;

    var sel;

    if (typeof win.getSelection != "undefined") {

        sel = win.getSelection();

        if (sel.rangeCount > 0) {

            var range = win.getSelection().getRangeAt(0);

            var preCaretRange = range.cloneRange();

            preCaretRange.selectNodeContents(element);

            preCaretRange.setEnd(range.startContainer, range.startOffset);

            start = preCaretRange.toString().length;

            preCaretRange.setEnd(range.endContainer, range.endOffset);

            end = preCaretRange.toString().length;

        }

    } else if ( (sel = doc.selection) && sel.type != "Control") {

        var textRange = sel.createRange();

        var preCaretTextRange = doc.body.createTextRange();

        preCaretTextRange.moveToElementText(element);

        preCaretTextRange.setEndPoint("EndToStart", textRange);

        start = preCaretTextRange.text.length;

        preCaretTextRange.setEndPoint("EndToEnd", textRange);

        end = preCaretTextRange.text.length;

    }

    return { start: start, end: end };

}



function reportSelection() {

  var selOffsets = getSelectionCharacterOffsetWithin( document.getElementById("editor") );

  document.getElementById("selectionLog").innerHTML = "Selection offsets: " + selOffsets.start + ", " + selOffsets.end;

}



window.onload = function() {

  document.addEventListener("selectionchange", reportSelection, false);

  document.addEventListener("mouseup", reportSelection, false);

  document.addEventListener("mousedown", reportSelection, false);

  document.addEventListener("keyup", reportSelection, false);

};


#editor {

  padding: 5px;

  border: solid green 1px;

}


Select something in the content below:



<div id="editor" contenteditable="true">A <i>wombat</i> is a marsupial native to <b>Australia</b></div>

<div id="selectionLog"></div>

这是一个函数,将获取指定元素内插入符号的字符偏移量;但是,这是一个幼稚的实现,几乎肯定会与换行符产生不一致,并且不会尝试处理通过CSS隐藏的文本(我怀疑IE会正确地忽略此类文本,而其他浏览器则不会)。正确处理所有这些东西将很棘手。现在我已经尝试过了我的瘦长库。

function getCaretCharacterOffsetWithin(element) {
    var caretOffset = 0;
    var doc = element.ownerDocument || element.document;
    var win = doc.defaultView || doc.parentWindow;
    var sel;
    if (typeof win.getSelection != "undefined") {
        sel = win.getSelection();
        if (sel.rangeCount > 0) {
            var range = win.getSelection().getRangeAt(0);
            var preCaretRange = range.cloneRange();
            preCaretRange.selectNodeContents(element);
            preCaretRange.setEnd(range.endContainer, range.endOffset);
            caretOffset = preCaretRange.toString().length;
        }
    } else if ( (sel = doc.selection) && sel.type != "Control") {
        var textRange = sel.createRange();
        var preCaretTextRange = doc.body.createTextRange();
        preCaretTextRange.moveToElementText(element);
        preCaretTextRange.setEndPoint("EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
    }
    return caretOffset;
}


 类似资料:
  • 我使用以下方法基于用户选择创建一个范围: 调用此函数的组件执行以下操作: 每当我选择文本时,范围总是相对于高亮显示的跨度结束的位置。因此,如果我的文本在0到50之间,我选择范围[25,26],然后选择范围[26,27],而不是突出显示范围[26,27],它突出显示范围[0,1],因为范围是[0,1]相对于{after}生成的文本。 只要我突出显示{之前}渲染的任何文本,我就没有问题,只有当我突出显

  • 是否可以跟踪卡桑德拉的“预订”? 基本上,我的大多数查询将涉及一个和一个,我希望在其中找到与该时间相交的所有保留。 我的模式如下所示: 我输入了一些数据,如下所示: 我正在尝试这样的查询: 我得到一个这样的错误: 我认为这是可以做到的,因为在这个SO问题中似乎是这样的:在cassandra中存储时间范围 但是,架构没有发布,我们也没有使用pycassa,而且我似乎无法弄清楚如何将其映射到CQL。

  • 问题内容: 我有这样的时间戳字符串: 我想对它们进行排序,以便可以从上述时间戳获取起始范围和终止范围。我正在做如下: 这将为我提供上述时间戳列表的开始和结束范围。这是正确的方法还是有更好的方法? 更新资料 因此,我应该执行以下操作: 问题答案: 将那些ISO 8601 字符串解析为对象。 将这些日期时间对象添加到并排序。您可能想要诸如或。 java.time类实现该方法,以作为实现合同。因此,这些

  • 考虑基于范围的for循环的begin expr和end expr的规范(N4140[标准范围]/p1)。给定类型为RangeT的范围, 开始表达式和结束表达式的确定如下: 如果“范围”是数组类型,则“开始表达式”和“结束表达式”分别是“范围”和“范围绑定”,其中“范围绑定”是数组绑定。如果RangeT是大小未知的数组或类型不完整的数组,则程序格式错误 如果RangeT是类类型,则在类RangeT的

  • 问题内容: 我想知道如何检索实例的父结构。 我不知道如何实现这一目标。 例如: 干杯 问题答案: 您应该保留一个指向引擎盖的指针。 当你增加房子 那么您可以轻松更改,尽管此时可能不需要吸气剂。

  • 我有一个类似于以下内容的DataFrame(sqlDF)(在本例中进行了简化),其中我试图删除在另一行的开始日期和结束日期范围内具有start_date和end_date的所有行: 首先,最终用户要求我删除start_date和end_date之间间隔小于5天的所有记录,我使用了以下方法: 从而产生如下所示的数据frame: 现在,我需要筛选出开始日期和结束日期在同一id的另一行开始日期和结束日期