1

I wanna highlight text in an html element based on start position and end position of the plain text (without html).

For example if we have a sentence "Hello, how are you?" and I wanted to highlight the word "Hello", the startPos is 0 and endPos is 5. This is working fine in my code for #text1.

<div id="segment">
  <div id="text1">Hello, <b>how</b> are you?</div>
  <div id="text2"><b>Hello</b>, how are you?</div>
</div>

var text1 = document.querySelector('#text1').innerHTML;
document.querySelector('#text1').innerHTML = highlightLetters(text1, 0,5);

function highlightLetters(segmentHTML, startPos, endPos) {
   return "<span style='background-color:pink;'>" + 
   segmentHTML.slice(startPos, endPos) + "</span>" + 
   segmentHTML.slice(endPos);
}

The issue is visible in #text2 where the word Hello is wrapped between html tags. Running highlightLetters() would wrap the highlight span even between html tags.

The expected result after running the highlight function on #text2 should be like this:

<div id="text2"><span style='background-color:pink;'><b>Hello</b></span>, how are you?</div>

https://jsfiddle.net/mwedL6to/1/

Notes:

  • My highlight start positions and end positions are coming from an external spellcheck API.
  • The #text1 or #text2 could contain really random html tags, so the highlight function needs to be able to deal with it.

similar issue here, but the same problem is there too (unsolved) Text highlighting based on positions

So perhaps I need a solution which will somehow calculate my new startPos and endPos based on any additional html tags inside the text?

Linux_cat
  • 45
  • 12

1 Answers1

1

If the task is to highlight single words, you may combine .innerHTML and .innerText in combination to achieve the wanted functionality. First you would extract the to be highlighted word using text-only. Then you search for the word's position inside the HTML version to find its location. Now simply swap that part of the string.

Code:

var html2 = document.querySelector('#text2').innerHTML;
var text2 = document.querySelector('#text2').innerText;
document.querySelector('#text2').innerHTML = highlightLetters(html2, text2, 0,5);

function highlightLetters(segmentHTML, text, startPos, endPos) {
   var highlightText= text.slice(startPos, endPos);
   var textPosition= segmentHTML.indexOf(highlightText);
   var textLength = endPos - startPos;

   return segmentHTML.slice(0, textPosition) + 
     "<span style='background-color:pink;'>" + 
     segmentHTML.slice(textPosition, textPosition + textLength) + "</span>" + 
     segmentHTML.slice(textPosition + textLength);
}

Here is a fiddle showing the highlighting.

Limitations of this version:

  • will not work in case the string to be highlighted contains a closing or opening HTML tag (as .indexOf() will not find the string in the HTML)
SaschaM78
  • 4,376
  • 4
  • 33
  • 42