Select 如何在已高亮显示的文本中高亮显示用户选择的文本?

Select 如何在已高亮显示的文本中高亮显示用户选择的文本?,select,text,highlight,Select,Text,Highlight,我有一个在div中显示一些文本的页面,我需要在某些部分突出显示这些文本。我通过使用标签和适当的css样式围绕需要突出显示的文本来实现这一点。 例如。 我的文本看起来像这样,其中有突出显示的部分。 这个很好用。但是,该页面的另一个要求是,用户必须能够选择文本,单击按钮,并且所选文本也必须高亮显示 我遇到的问题是,当试图识别要抓取的选定文本的范围时(使用window.getSelection.getRangeAt(0)),这会给我一个范围,该范围会在文本中的每个标记之后重置,而不是从文本的开头重

我有一个在div中显示一些文本的页面,我需要在某些部分突出显示这些文本。我通过使用标签和适当的css样式围绕需要突出显示的文本来实现这一点。 例如。

我的文本看起来像这样,其中有突出显示的部分。

这个很好用。但是,该页面的另一个要求是,用户必须能够选择文本,单击按钮,并且所选文本也必须高亮显示


我遇到的问题是,当试图识别要抓取的选定文本的范围时(使用window.getSelection.getRangeAt(0)),这会给我一个范围,该范围会在文本中的每个
标记之后重置,而不是从文本的开头重置

对于那些将来想知道我是如何做到这一点的人:

jQuery.fn.highlight = function(startOffset,endOffset,type) {
 function innerHighlight(node, startOffset,endOffset) {
     var calledStartOffset = parseInt(startOffset);
     var startOffsetNode=getChildNodeForOffset(node,parseInt(startOffset));
     var endOffsetNode=getChildNodeForOffset(node,parseInt(endOffset));
     startOffset = resizeOffsetForNode(startOffsetNode,parseInt(startOffset));

     if (startOffsetNode == endOffsetNode){
         endOffset = resizeOffsetForNode(endOffsetNode,parseInt(endOffset));
         highlightSameNode(startOffsetNode, parseInt(startOffset),parseInt(endOffset),type,calledStartOffset);
     } else {
         highlightDifferentNode(startOffsetNode,endOffsetNode,parseInt(startOffset),parseInt(endOffset),type,calledStartOffset);
     }
 }
 return this.each(function() {
     innerHighlight(this, startOffset,endOffset);
 });
};

function resizeOffsetForNode(offsetNode,offset){
 if (offsetNode.id >= 0){
     offset = parseInt(offset)-parseInt(offsetNode.id);
 } else if (offsetNode.previousSibling != null && offsetNode.previousSibling.id > 0){
     offset = parseInt(offset)-parseInt(offsetNode.previousSibling.id)-parseInt(offsetNode.previousSibling.textContent.length);
 }  
 return offset;
}

function getChildNodeForOffset(testNode,offset) {
    if (testNode.nodeType == 1 && testNode.childNodes && !/(script|style)/i.test(testNode.tagName)) {
       var offsetNode=null;
       var currentNode;
       for (var i = 0; i < testNode.childNodes.length; ++i) {
           currentNode=testNode.childNodes[i];
           if (currentNode.id >= 0 && parseInt(currentNode.id) <= parseInt(offset) && ((parseInt(currentNode.id) + parseInt(currentNode.textContent.length)) >= parseInt(offset))){
               offsetNode = currentNode;
               break;
           } else if (currentNode.id >= 0 && parseInt(currentNode.id) > parseInt(offset)){
               offsetNode = currentNode.previousSibling;
               break;
           }
        }
       if (offsetNode==null){
           offsetNode = testNode.childNodes[testNode.childNodes.length-1]; 
       }
       return offsetNode;
    }
}

function highlightSameNode(node, startOffset,endOffset,type,calledStartOffset) {
   var skip = 0;
   if (node.nodeType == 3) {
   if (startOffset >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'entity '+ type;
    spannode.id=calledStartOffset;
    var middlebit = node.splitText(startOffset);
    var endbit = middlebit.splitText(endOffset-startOffset);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
   }
  } else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
    var childnode = node.childNodes[0];
    highlightSameNode(childnode, startOffset,endOffset,type,calledStartOffset);
  }
}

function highlightDifferentNode(startnode, endnode, startOffset,endOffset,type,calledStartOffset) {
   var skip = 0;
   if (startnode.nodeName == "#text") {
       if (startOffset >= 0) {
            var spannode = document.createElement('span');
            spannode.className = 'entity '+ type;
            spannode.id=calledStartOffset;
            var endbit = node.splitText(startOffset);
            var endclone = endbit.cloneNode(true);
            spannode.appendChild(endclone);
            endbit.parentNode.replaceChild(spannode, endbit);
       }
   } else if (startnode.nodeName == "SPAN") {
       if (startOffset >= 0) {
            var spannode = document.createElement('span');
            spannode.className = 'entity '+ type;
            spannode.id=calledStartOffset;
            var endTextbit = startnode.childNodes[0].splitText(startOffset);
            spannode.appendChild(endTextbit);
            startnode.parentNode.insertBefore(spannode, startnode.nextSibling);
       }
   }
   var currentTestNode=startnode.nextSibling;
   while (currentTestNode!=endnode){
       if (currentTestNode.nodeName == "#text") {
            var spannode = document.createElement('span');
            spannode.className = 'entity '+ type;
            spannode.id=parseInt(currentTestNode.previousSibling.id)+parseInt(currentTestNode.previousSibling.textContent.length);
            var currentNodeClone=currentTestNode.cloneNode(true);
            spannode.appendChild(currentNodeClone);
            endbit.parentNode.replaceChild(spannode, currentTestNode);
       } else if (currentTestNode.nodeName == "SPAN") {
            currentTestNode.className = 'entity overlap';
       }
       currentTestNode=currentTestNode.nextSibling;
   }
   var previousNodeEnd = parseInt(endnode.previousSibling.id)+parseInt(endnode.previousSibling.textContent.length);
   var spannode = document.createElement('span');
   spannode.className = 'entity '+ type;
   spannode.id=previousNodeEnd;
   if (endnode.nodeName == "#text") {
       if (endOffset >= 0) {
            //end offset here is the original end offset from the beginning of the text, not node
            var unwantedbit = endnode.splitText(parseInt(endOffset)-parseInt(previousNodeEnd));
            var endclone = endnode.cloneNode(true);
            spannode.appendChild(endclone);
            endnode.parentNode.replaceChild(spannode, endnode);
       }
   } else if (endnode.nodeName == "SPAN") {
       if (endOffset >= 0) {
            var wantTextbit = endnode.childNodes[0].splitText(parseInt(endOffset)-parseInt(previousNodeEnd));
            spannode.appendChild(wantTextbit);
            wantTextbit.parentNode.parentNode.insertBefore(spannode, endnode);
       }
   }
   if (startnode.textContent.length < 1){
    startnode.parentNode.removeChild(startnode);
   }
   if (endnode.textContent.length < 1){
       endnode.parentNode.removeChild(endnode);
   }
}

jQuery.fn.removeHighlight = function() {
 return this.find("span.entity").each(function() {
  this.parentNode.firstChild.nodeName;
  with (this.parentNode) {
   replaceChild(this.firstChild, this);
   normalize();
  }
 }).end();
};

function contains(a, b){
      return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16);
} 
jQuery.fn.highlight=函数(startOffset、endOffset、type){
函数innerHighlight(节点、startOffset、endOffset){
var calledStartOffset=parseInt(startOffset);
var startOffsetNode=getchildnodeforofset(node,parseInt(startOffset));
var endOffsetNode=getchildnodeforofset(节点,parseInt(endOffset));
startOffset=resizeOffsetForNode(startOffsetNode,parseInt(startOffset));
if(startOffsetNode==endOffsetNode){
endOffset=resizeOffsetForNode(endOffsetNode,parseInt(endOffset));
highlightSameNode(startOffsetNode、parseInt(startOffset)、parseInt(endOffset)、type、calledStartOffset);
}否则{
highlightDifferentNode(startOffsetNode、endOffsetNode、parseInt(startOffset)、parseInt(endOffset)、type、calledStartOffset);
}
}
返回此值。每个(函数(){
内部高光(此、开始偏移、结束偏移);
});
};
函数resizeOffsetForNode(offsetNode,offset){
如果(offsetNode.id>=0){
offset=parseInt(offset)-parseInt(offsetNode.id);
}else if(offsetNode.previousSibling!=null&&offsetNode.previousSibling.id>0){
offset=parseInt(offset)-parseInt(offsetNode.previousSibling.id)-parseInt(offsetNode.previousSibling.textContent.length);
}  
返回偏移量;
}
函数getChildNodeForOffset(testNode,偏移量){
if(testNode.nodeType==1&&testNode.childNodes&&!/(脚本样式)/i.test(testNode.tagName)){
var offsetNode=null;
无功电流节点;
对于(变量i=0;i=0&&parseInt(currentNode.id)=parseInt(offset))){
offsetNode=currentNode;
打破
}如果(currentNode.id>=0&&parseInt(currentNode.id)>parseInt(offset))则为else{
offsetNode=currentNode.previousSibling;
打破
}
}
if(offsetNode==null){
offsetNode=testNode.childNodes[testNode.childNodes.length-1];
}
返回offsetNode;
}
}
函数highlightSameNode(节点、STARTOFSET、endOffset、类型、调用的startOffset){
var-skip=0;
if(node.nodeType==3){
如果(startOffset>=0){
var spannode=document.createElement('span');
spannode.className='entity'+类型;
spannode.id=被调用的起始偏移量;
var middlebit=node.splitText(startOffset);
var endbit=middlebit.splitText(endOffset startOffset);
var middleclone=middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode,middlebit);
}
}else if(node.nodeType==1&&node.childNodes&&!/(脚本样式)/i.test(node.tagName)){
var childnode=node.childNodes[0];
highlightSameNode(childnode、startOffset、endOffset、type、calledStartOffset);
}
}
函数HighlightDifferentitNode(startnode、endnode、startOffset、endOffset、type、calledStartOffset){
var-skip=0;
if(startnode.nodeName==“#文本”){
如果(startOffset>=0){
var spannode=document.createElement('span');
spannode.className='entity'+类型;
spannode.id=被调用的起始偏移量;
var endbit=node.splitText(startOffset);
var endclone=endbit.cloneNode(true);
spannode.appendChild(endclone);
endbit.parentNode.replaceChild(spannode,endbit);
}
}else if(startnode.nodeName==“SPAN”){
如果(startOffset>=0){
var spannode=document.createElement('span');
spannode.className='entity'+类型;
spannode.id=被调用的起始偏移量;
var endTextbit=startnode.childNodes[0]。拆分文本(startOffset);
spannode.appendChild(endTextbit);
startnode.parentNode.insertBefore(spannode,startnode.nextSibling);
}
}
var currentTestNode=startnode.nextSibling;
while(currentTestNode!=endnode){
如果(currentTestNode.nodeName==“#文本”){
var spannode=document.createElement('span');
spannode.className='entity'+类型;
spannode.id=parseInt(currentTestNode.previousSibling.id)+parseInt(currentTestNode.previousSibling.textContent.length);
var currentNodeClone=currentTestNode.cloneNode(真);
spannode.appendChild(currentNodeClone);
endbit.parentNode.replaceChild(spannode,currentTestNode);
}else if(currentTestNode.nodeName==“SPAN”){
currentTestNode.className='实体重叠';
}
currentTestNode=currentTestNode.nextSibling;
}
var previousNodeEnd=parseInt(endnode.previousSibling.id)+parseInt(endnode.previousSibling.textContent.length);
var spannode=document.createElement('span');
spannode.className='entity'+类型;
spannode.id=先前的nodeend;
if(endnode.nodeName==“#文本”){
如果(内偏移量>=0){
//“结束偏移”此处是从文本开始的原始结束偏移,而不是节点
var unwantedbit=endnode.splitText(parseInt(endOffset)-parseInt(previousNodeEnd));
var endclone=endnode.cloneNode