Search code examples
javascriptregexoverlapping-matches

Overlapping regex matches with replace method


Regex newbie here! Lets say i have two arrays of text and I am searching through a text which says.

let text = This is a cool story.
I am looking for these phrases in the text.

ArrBlue = ["cool story"] 
ArrGreen = ["This is a cool"] 

And i want to highlight words in the array with the corresponding color. So all the words in ArrBlue will result in text that is blue and ArrGreen in green. I created two new RegExp like so..

let regexBlue = new RegExp(arrBlue.join('|'), "ig)  
let regexGreen = new RegExp(arrGreen.join('|'), "ig)

and then i use these new variables to then replace text like so attaching a span tag to the beginning and end of the matched expression.

let newText = text.replace(regexBlue, "<span class='blue'>$&</span>")    
.replace(regexGreen, "<span class='green'>$&</span>")

The issue that i am having is I want my html to look like so..

<span class="blue">This is a<span class="green" cool story </span> </span>

But in actuality what im getting is

This is a <span class="green">cool story</span>

Heres my quick snippet to better understand my situation.

let greenListArray = ["cool story"];
let blueListArray = ['This is a cool'];

$("#myform").submit(function(event){
   event.preventDefault();
   $('#results').html('');
   let text = $('textarea#textEntered').val();
   highlightText(text); 
});

function highlightText(text){

let regexGreen = new RegExp(greenListArray.join('[,!?.]?|'), "ig");
let regexBlue = new RegExp(blueListArray.join('[,!?.]?|') + "ig");

let newText = text.replace(regexGreen, "<span class='green'>$&</span>")
.replace(regexBlue, "<span class='blue'>$&</span>");

$('#results').html(newText);
}
.blue{
  background-color: red;
  font: red;
}
.green{
  background-color: green;
}


.greyHighlight:hover{
  background-color: grey;
  color: white;
  
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
 <form id="myform">
      <fieldset>
        <textarea name='textEntered' id='textEntered' />This is a cool story.</textarea>
        <button type='submit' class="bttn">Enter</button>
      </fieldset>
    </form>
   
    <div class="results-container"> <span class="results-title">Highlighted Text:</span> <div id="results"> </div> <br> </div>


<div class="wantedResults">
Results I wish to have <br>
<span class="blue">This is a</span><span class="green">cool story</span> 
</div>


Solution

  • This works for basic implementation. Overlapping more than 2 times will not work properly. And also need to handle white spaces.

    var arr = [
      {str:"cool story",
       color: "green"},
       {str:"This is a cool",
       color: "blue"},
       {str:"two best friends",
       color: "red"},
       {str:"about two best",
       color: "yellow"},
    ];
    
    $("#myform").submit(function(event){
       event.preventDefault();
       $('#results').html('');
       let text = $('textarea#textEntered').val();
       highlightText(text); 
    });
    
    function highlightText(text)
    {
        for(var index=0;index<arr.length;index++)
        {
            var matches=text.match(arr[index].str.split(" ").join("\\s*(<.*>)*\\s*"));
            if(matches)
            {
                for(var i=1;i<matches.length;i++)
                {
                    if(!matches[i]) continue;
                    if(matches[i].indexOf("/")==-1)
                    {
                        text = text.replace(matches[0],matches[0].replace(matches[i],"")+matches[i]);
                    }
                    else
                    {
                    
                        text = text.replace(matches[0],matches[i]+matches[0].replace(matches[i],""));
                    }
                }
            }
            text = text.replace(arr[index].str, "<span class='"+arr[index].color+"'>$&</span>");
        }
        $('#results').append($(text))
    }
    .blue{
      background-color: blue;
    }
    .green{
      background-color: green;
    }
    .red{
      background-color: red;
    }
    .yellow{
      background-color: yellow;
    }
    .grey{
      background-color: grey;
    }
    
    .greyHighlight:hover{
      background-color: grey;
      color: white;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <form id="myform">
          <fieldset>
            <textarea name='textEntered' id='textEntered'>This is a cool story about two best friends.</textarea>
            <button type='submit' class="bttn">Enter</button>
          </fieldset>
      </form>
       
        <div class="results-container"> <span class="results-title">Highlighted Text:</span> <div id="results"> </div> <br> </div>
    
    
    <div class="wantedResults">
    Results I wish to have <br>
    <span class="blue">This is a</span><span class="green">cool story</span> 
    </div>