'How can I dynamically highlight strings on a web page?

I want to create pages with urls such as:

http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver

These particular URLs would all contain the exact same content (the "2015Aug24_Aug28" page), but would highlight all instances of the name tagged on to the end. For example, "http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones" would show every instance of the name "Billy Bones" highlighted, as if a "Find" for that name was executed on the page via the browser.

I imagine something like this is required, client-side:

var employee = getLastURLPortion(); // return "Billy_Bones" (or whatever)
employee = humanifyTheName(employee); // replaces underscores with spaces, so that it's "Billy Bones" (etc.)
Highlight(employee); // this I have no clue how to do

Can this be done in HTML/CSS, or is JavaScript or jQuery also required for this?



Solution 1:[1]

I used the following regex to replace all the matching url to create anchors with highlighted text:

(http://xyzcorp/schedules/(.*?)/)(.*?)( |<|\n|\r|$)

Regular expression visualization

Debuggex Demo

The following code will replace all plain urls. If you don't need them to be replaced to links, just highlight them, remove the tags:

var str = "http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver ";

var highlighted = str.replace( new RegExp("(http://xyzcorp/schedules/(.*?)/)(.*?)( |<|\n|\r|$)","g"), "<a href='$1$3'>$1<span style='background-color: #d0d0d0'>$3</span></a>" );

The content of the highlighted string will be:

<a href='http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins'>http://xyzcorp/schedules/2015Aug24_Aug28/<span style='background-color: #d0d0d0'>Jim_Hawkins</span></a>
<a href='http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones'>http://xyzcorp/schedules/2015Aug24_Aug28/<span style='background-color: #d0d0d0'>Billy_Bones</span></a>
<a href='http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver'>http://xyzcorp/schedules/2015Aug24_Aug28/<span style='background-color: #d0d0d0'>John_Silver</span></a>

UPDATE:

This function will replace the matching names from the input text:

function highlight_names( html_in )
{
    var name = location.href.split("/").pop().replace("_"," ");
    return html_in.replace( new RegExp( "("+name+")", "g"), "<span style='background-color: #d0d0d0'>$1</span>" );
}

Solution 2:[2]

One solution would be, after window is loaded, to traverse all nodes recursively and wrap search terms in text nodes with a highlight class. This way, original structure and event subscriptions are not preserved.

(Here, using jquery, but could be done without):

Javascript:

$(function() {
  // get term from url
  var term = window.location.href.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
  // search regexp
  var re = new RegExp('(' + term + ')', 'gi');
  // recursive function
  function highlightTerm(elem) {
    var contents = $(elem).contents();
    if(contents.length > 0) {
      contents.each(function() {
        highlightTerm(this);
      });
    } else {
      // text nodes
      if(elem.nodeType === 3) {
        var $elem = $(elem);
        var text = $elem.text();
        if(re.test(text)) {
          $elem.wrap("<span/>").parent().html(text.replace(re, '<span class="highlight">$1</span>'));
        }
      }
    }
  }
  highlightTerm(document.body);
});

CSS:

.highlight {
    background-color: yellow;
}

$(function() {
  // get term from url
  //var term = window.location.href.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
  var term = 'http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones/'.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
  // search regexp
  var re = new RegExp('(' + term + ')', 'gi');
  // recursive function
  function highlightTerm(elem) {
    var contents = $(elem).contents();
    if(contents.length > 0) {
      contents.each(function() {
        highlightTerm(this);
      });
    } else {
      // text nodes
      if(elem.nodeType === 3) {
        var $elem = $(elem);
        var text = $elem.text();
        if(re.test(text)) {
          $elem.wrap("<span/>").parent().html(text.replace(re, '<span class="highlight">$1</span>'));
        }
      }
    }
  }
  highlightTerm(document.body);
});
.highlight  {
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <div>
      <div class="post-text" itemprop="text">
        <p>I want to create pages with urls such as:</p>
        <pre style="" class="default prettyprint prettyprinted">
          <code>
            <span class="pln">http</span>
            <span class="pun">:</span>
            <span class="com">//xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins</span>
            <span class="pln">
http</span>
            <span class="pun">:</span>
            <span class="com">//xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones</span>
            <span class="pln">
http</span>
            <span class="pun">:</span>
            <span class="com">//xyzcorp/schedules/2015Aug24_Aug28/John_Silver</span>
          </code>
        </pre>
        <p>These particular URLs would all contain the exact same content (the "2015Aug24_Aug28" page), but would highlight all instances of the name tagged on to the end. For example, "                    <code>http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones</code>

" would show every instance of the name "Billy Bones" highlighted, as if a "Find" for that name was executed on the page via the browser.</p>
        <p>I imagine something like this is required, client-side:</p>
        <pre style="" class="default prettyprint prettyprinted">
          <code>
            <span class="kwd">var</span>
            <span class="pln"> employee </span>
            <span class="pun">=</span>
            <span class="pln"> getLastURLPortion</span>
            <span class="pun">();</span>
            <span class="pln"></span>
            <span class="com">// return "Billy_Bones" (or whatever)</span>
            <span class="pln">
employee </span>
            <span class="pun">=</span>
            <span class="pln"> humanifyTheName</span>
            <span class="pun">(</span>
            <span class="pln">employee</span>
            <span class="pun">);</span>
            <span class="pln"></span>
            <span class="com">// replaces underscores with spaces, so that it's "Billy Bones" (etc.)</span>
            <span class="pln"></span>
            <span class="typ">Highlight</span>
            <span class="pun">(</span>
            <span class="pln">employee</span>
            <span class="pun">);</span>
            <span class="pln"></span>
            <span class="com">// this I have no clue how to do</span>
          </code>
        </pre>
        <p>Can this be done in HTML/CSS, or is JavaScript or jQuery also required for this?</p>
      </div>

Demo: http://plnkr.co/edit/rhfqzWThLTu9ccBb1Amy?p=preview

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