2010-10-11 6 views
1

J'ai une page où j'affiche du texte dans un div et j'ai besoin de mettre en évidence ce texte dans certaines parties. J'ai fait cela en entourant le texte que je dois mettre en évidence avec un tag et un style css approprié. E.g. <div> My text will look like this with <span class="highlight">highlighted bits</span> in it. </div>comment surligner le texte sélectionné par l'utilisateur dans un texte déjà mis en surbrillance?

Cela fonctionne très bien. Cependant, une autre exigence pour cette page est que l'utilisateur doit être capable de sélectionner des textes, de cliquer sur un bouton, et le texte sélectionné doit également être surligné. Le problème que j'ai est d'essayer d'identifier la plage du texte sélectionné à attraper (en utilisant window.getSelection.getRangeAt (0)), cela me donne la plage qui se réinitialise après chaque tag <span> dans le texte, pas de le début du texte.

Répondre

1

Pour ceux qui voudraient savoir dans l'avenir, c'est ainsi que je l'ai fait:

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); 
} 
+0

C'est grand, pourriez-vous donner un aperçu de ce que fait chaque bit de code et montrer un exemple en cours d'utilisation (jsfiddle, codepen, tout ce que vous préférez)? Une petite explication des points critiques serait appréciée. – Deviljho

Questions connexes