2

I'd like to highlight certain words if they're found within a title by wrapping those words in a span class. Is there a way of writing a list of words to check for and then using the same command to wrap any of those words with the span class?

For example:

<h1>This title contains the word Balloon</h1>
<h1>This title contains the word Oranges</h1>
<h1>This title doesn't contain either of those terms</h1>

Something to check each of those three elements (but there would be 20 or so) for the words Balloon or Oranges and then wrap just those words in a span color.

I could use:

$('h1').html($('h1').html().replace(/(balloon)/g,'<span class="red">balloon</span>'));

but I'd have to write that query for every word, whereas I'd like something a little simpler, if possible.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
Jerpl
  • 169
  • 1
  • 3
  • 16
  • 1
    Note that the other problem with your example using `html` is that if you do that, you wipe out and recreate the elements, losing any event handlers or other state they have. – T.J. Crowder Jul 09 '16 at 10:26
  • Use `$('h1').html(function(){})` – Mohammad Jul 09 '16 at 10:26
  • How about creating an array with the words you want to check and then loop through them with the snippet you posted? – Chris Satchell Jul 09 '16 at 10:28
  • Have a look at https://markjs.io – dude Jul 09 '16 at 10:55
  • Define what you mean by word? Any substring or boundary ones? – A. Wolff Jul 09 '16 at 11:01
  • Possible duplicate of [JQuery search in static HTML page with highlighting of found word](http://stackoverflow.com/questions/10011385/jquery-search-in-static-html-page-with-highlighting-of-found-word) – dude Jul 09 '16 at 11:17

4 Answers4

6

You can keep an array of words, then iterate and replace the words in each header

var words = [
    "balloon",
    "either"
];

$('h1').html(function(_,html) {
    var reg = new RegExp('('+words.join('|')+')','gi');
    return html.replace(reg, '<span class="red">$1</span>', html)
});
.red {color : red}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h1>This title contains the word Balloon</h1>
<h1>This title contains the word Oranges</h1>
<h1>This title doesn't contain either of those terms</h1>
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • can i asked `return html.replace(reg, '$1', html)` where `$1` is from. can you add more explanation thank you – guradio Jul 09 '16 at 10:34
  • Again, this is replacing substring, not word. What if you have the word 'string' to replace and your text contains the word 'substring'. I'm not sure what is OP's expected behaviour – A. Wolff Jul 09 '16 at 11:05
  • 1
    @A.Wolff - indeed it is, but that could be solved by adding word boundaries to the regex, if the op needs to match whole words only. – adeneo Jul 09 '16 at 15:45
  • @adeneo Ya, exactly – A. Wolff Jul 09 '16 at 15:48
  • @guradio - the `$*` is "replacement", it remembers the matches in the regex, so you don't have to write them out literally, and acts sorta like a variable. – adeneo Jul 09 '16 at 15:52
0

Loop through your element set, like so, and replace it with anything in an array of keywords:

<h1>This title contains the word Balloon</h1>
<h1>This title contains the word Oranges</h1>
<h1>This title doesn't contain either of those terms</h1>
<h1>This title contains both Balloon and Oranges</h1>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<script>
var wordsToHighlight = ['Balloon', 'Oranges'];
$('h1').each(function() {
  for (var i = 0, l = wordsToHighlight.length; i < l; i++) {
    if ($(this).html().indexOf(wordsToHighlight[i]) !== -1) {
      var newValue = $(this).html().replace(wordsToHighlight[i], 
          '<span>' + wordsToHighlight[i] + '</span>');
      $(this).html(newValue);
    }
  }
});
</script>
1sloc
  • 1,180
  • 6
  • 12
0

While the answers provided here are theoretically correct, they will use innerHTML which is evil. It will destroy events and triggers DOM generation over and over again. Also, you'll probably need to remove highlights at a time, so you are reinverting the wheel.

There's a plugin that solves your problem: mark.js

Usage can be done e.g. the following way:

$(function(){
  // pass an array to highlight or a simple string term
  $("h1").mark(["Balloon", "Oranges"]);
});
mark{
  background: orange;
  color: black;
}
<script src="https://cdn.jsdelivr.net/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/mark.js/7.0.0/jquery.mark.min.js"></script>
<h1>This title contains the word Balloon</h1>
<h1>This title contains the word Oranges</h1>
<h1>This title doesn't contain either of those terms</h1>
dude
  • 5,678
  • 11
  • 54
  • 81
-1

You can have an object containing all the words you want wrapped (including another specifications eg class or the tag used) and then just iterate over all fields of the object while using your command that just constructs the string to be used.

Péťa Poliak
  • 393
  • 1
  • 3
  • 11