James
James

Reputation: 631

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>

Upvotes: 1

Views: 166

Answers (3)

Roko C. Buljan
Roko C. Buljan

Reputation: 206078

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');

Upvotes: 1

Twisty
Twisty

Reputation: 30893

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>

Upvotes: 1

Barmar
Barmar

Reputation: 780899

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>

Upvotes: 1

Related Questions