'jQuery select words in array

How can I use an array for this instance? I'd like to change both bar and foo's font color.

var colorRed = ['bar', 'foo'];
$(document).ready(function () {
    $(".msg:contains('"+colorRed+"')").each(function () {
        var regex = new RegExp(colorRed,'gi');
        $(this).html($(this).text().replace(regex, "<span class='red'>"+colorRed+"</span>"));
    });
});
.red {
    color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="msg">select bar and foo in this sentence</div>


Solution 1:[1]

Use .join("|") to create a Matching Group with optional | values.

Basically it will create a Regex like /(bar|foo)/ and extract the matching value using $& placeholder:

const words = ["bar", "foo"];
const regex = new RegExp(`(${words.join("|")})`, 'gi');

jQuery(function($) { // Better DOM ready. And $ alias in scope

  $(".msg").html(function() {
    if (regex.test(this.textContent))
      return this.textContent.replace(regex, "<span class='red'>$&</span>");
  });

});
.red { color: red; }
<div class="msg">select bar and foo in this FOO sentence</div>
<div class="msg">Foo enters <b>the bar</b> (HTML is lost)</div>
<div class="msg"><b>Nothing to edit here</b> (HTML is preserved)</div>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Also, no need to use .each() when you need only to update the innerHTML - use directly the jQuery's .html() Method as above.

PS1: :contains is case sensitive, so it makes no sense to use it, specially if afterwards you use the RegExp's i (insensitive) flag.

PS2: if you don't want to highlight bar in bartender use the \b word boundary:

const regex = new RegExp(`\\b(${words.join("|")})\\b`, 'gi');

Solution 2:[2]

Loop through the array with .forEach()

You need to use .html() rather than .text(). Otherwise, you're removing the HTML markup that was added in previous iterations.

You also shouldn't have ' around the word in the :contains() selector.

var colorRed = ['bar', 'foo'];
$(document).ready(function() {
  colorRed.forEach(word =>
    $(".msg:contains(" + word + ")").each(function() {
      var regex = new RegExp(word, 'gi');
      $(this).html($(this).html().replace(regex, "<span class='red'>" + word + "</span>"));
    }));
});
.red {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="msg">select bar and foo in this sentence</div>

Solution 3:[3]

Consider the following example.

$(function() {
  function markText(t, m, c) {
    var regex;
    var results = t;
    $.each(m, function(i, el) {
      regex = new RegExp(el, 'gi');
      results = results.replace(regex, "<span class='" + c + "'>" + el + "</span>");
    });
    return results;
  }
  var colorRed = ['bar', 'foo'];
  $(".msg").each(function(idx, elem) {
    $(elem).html(markText($(elem).text().trim(), colorRed, "red"));
  });
});
.red {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="msg">select bar and foo in this sentence</div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Barmar
Solution 3 Twisty