在不知道实际文本节点的情况下通过 int offset (start-end) 突出显示 HTML 中的文本

Highlight text in HTML by int offset (start-end) without knowing actual textNodes

我需要突出显示 html 中的一些文本,仅给出开始和结束位置(整数,例如从第 600 到第 712 个字符)。

我可以使用 Range.setStart(startNode, startOffset) and Range.setEnd(endNode, endOffset) 来做到这一点,但只有当我知道 startNodeendNode 时才有效,它们很可能是 textNodes,在浅元素。

是否可以在不知道这些节点的情况下突出显示文本?
如果不是,确定开始和结束节点的最佳解决方案是什么?一种解决方案是遍历 DOM 并计算字符...

您可以使用 TreeWalker 从您的主 div 获取所有 textNodes,然后通过它们的 textContent 的长度来确定您的起点和终点应该在哪里:

var mainDiv = document.getElementById('main');
// create the treewalker which will accept all textNodes
var treeWalker = document.createTreeWalker(mainDiv,NodeFilter.SHOW_TEXT,null,false);
// the array containing our textNodes
var textNodeList = [];
while(treeWalker.nextNode()) textNodeList.push(treeWalker.currentNode);

function getRangeFromInt(start, end){
  var indexSizeError = 'IndexSizeError: Index or size is negative or greater than the allowed amount';
  if(start>end||start<0){console.warn(indexSizeError); return null;}
  
  var length = 0;
  var startNode, endNode, current=0,
  startPos, endPos;

  while(length<=end){
    // we'been too far ? return
    if(current>=textNodeList.length){console.warn(indexSizeError); return null;}
    // add the length of current node to our total length
    length+=textNodeList[current].textContent.length;
    // start is less than the actual total length ?
    if(start<length && !startNode){
      // then our startNode is here
      startPos = start-(length-textNodeList[current].textContent.length);
      startNode = textNodeList[current];
      }
    // same for the end
    if(end<length && !endNode){
      endPos = end-(length-textNodeList[current].textContent.length);
      endNode = textNodeList[current];
      }

    current++;
    }

  var range = document.createRange();
  range.setStart(startNode, startPos);
  range.setEnd(endNode, endPos);

  var selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
  return selection;
  }

var log = document.getElementById('log');
document.querySelector('button').addEventListener('click', function(){
  log.innerHTML = getRangeFromInt(
    this.previousElementSibling.previousElementSibling.value,
    this.previousElementSibling.value);
  },false);
p{font-size:.7em}
#log{color: rgba(0,0,0,.7); border:1px solid; position: absolute; font-size:.5em;}
<input placeholder="start"/><input placeholder="end"/><button>getRange</button>
<div id="main"><p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vel sodales odio. Nunc a nisi blandit, gravida augue quis, tristique ante. Aliquam in sem at tellus tincidunt ornare. Mauris ut scelerisque sapien. Pellentesque dignissim erat enim, vestibulum molestie diam ultrices eget. Nullam semper leo sit amet ante porttitor, vel tincidunt lorem 
</p>
<p>
Nam pellentesque id nulla at venenatis. Integer arcu nisi, suscipit sit amet here neque ac, hendrerit finibus nisl. Morbi quis volutpat libero. Pellentesque in sapien eu magna finibus tempor. Aliquam posuere ornare dolor, vel maximus felis tincidunt vel. Curabitur ac risus ut augue 
</p>
<p>
Pellentesque sollicitudin risus eu mi sollicitudin maximus eu at turpis. here Nunc iaculis tellus neque, in sollicitudin diam sollicitudin nec. Donec vitae urna nec nibh pharetra pulvinar. Proin eget dolor id quam porta 
</p>
<p>
Suspendisse malesuada, elit a blandit efficitur, mi sem molestie orci, at vulputate here erat diam quis mi. Mauris feugiat faucibus semper. Nulla tempor et velit quis interdum. Proin tincidunt lacus ut lacus auctor scelerisque. Aliquam pharetra risus laoreet nulla commodo, at eleifend ipsum dapibus. Pellentesque dignissim congue diam, a fermentum diam 
</p></div>
<p id="log"></p>