skip to content

JavaScript: Highlighting words using DHTML

If you've arrived at The Art of Web via a search engine you may have noticed that the keywords you searched for appeared highlighted on the landing page. There are two components to this - firstly identifying the keywords, and then highlighting them on the page using JavaScript. This article explains how to implement the second component using DHTML.

Working example

Enter some keywords in the box below and click on Highlight!. Words in the text that match the words you've entered will be instantly highlighted:

To remove highlighting click the Remove button.

How does it work?

First we take the form input (e.g. search keywords) and convert it into a JavaScript regular expression (e.g. \b(search|keywords)\b). That will match either 'search' or 'keywords' followed by a word boundary. In the real word we generate this from search engine referer strings and also exclude innocuous words such as 'is', 'and', 'are', etc, but that's another story.

The next step is to pass a reference to the #content node/element of this page to our highlightWords function which does all the heavy lifting.

The highlightWords traverses the DOM starting with the node we passed, looking for text nodes that match our regular expression. For each level of the document tree (tags inside tags) the function calls itself recursively passing the next child node as the parameter.

When a match is found, the text node in question is split up and a tag with style settings applied to the matching words.

As an enhancement, each word is assigned a colour from the hilite_colors array which is then used throughout the document for that word. If the colours used for highlighting look familiar, it's probably because they've been taken directly from Google Search' Cache View, but that can be easily changed.

Implementing on the page

To implement the example above requires two functions. The first is called when the form is submitted and has the effect of highlighting all matching keywords on the page. The second simply removes the highlighting.

<script type="text/javascript" src="searchhilite.js"></script> <script type="text/javascript"> var hilite; function apply_highlight(input) { remove_highlight(); input = input.replace(/^[^\w]+|[^\w]+$/g, ""); hilite = new RegExp("\\b(" + input.replace(/[^\w'-]+/g, "|") + ")\\b","i"); highlightWords(document.getElementById('content')); return false; } function remove_highlight() { removeHighlight(); } </script>

The highlightWords and removeHighlight functions are presented in the next section. When calling the highlightWords function we are passing the 'content' element of the page which contains this body of text.

JavaScript code for searchhilite.js

All that's required to achieve this affect is to loop through the DOM starting from a specific element, knowing which tags to ignore, and applying an HTML tag and associated style to words inside text nodes that match the supplied regular expression.

For various reasons, we are using the EM tag for this purpose, but you could just as easily use another suitable tag such as SPAN. Whichever tag you use has to be supplied in upper-case.

The variables set at the top of this file define which HTML tag to use to apply highlighting, a list of tags to exclude from the process, and an array of colours which are applied sequentially to different keywords.

// Original JavaScript code by Chirp Internet: www.chirp.com.au // Please acknowledge use of this code by including this header. var hilite_tag = "EM"; var hilite_skip = new RegExp("^(?:" + hilite_tag + "|SCRIPT|FORM)$"); var hilite_colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"]; var hilite_word = []; var hilite_idx = 0; function highlightWords(node) { if(!node || !hilite) return; if(hilite_skip.test(node.nodeName)) return; if(node.hasChildNodes()) for(var i=0; i < node.childNodes.length; i++) highlightWords(node.childNodes[i]); if(node.nodeType == 3) { // NODE_TEXT if((nv = node.nodeValue) && (regs = hilite.exec(nv))) { if(!hilite_word[regs[0].toLowerCase()]) { hilite_word[regs[0].toLowerCase()] = hilite_colors[hilite_idx++ % hilite_colors.length]; } var match = document.createElement(hilite_tag); match.appendChild(document.createTextNode(regs[0])); match.style.backgroundColor = hilite_word[regs[0].toLowerCase()]; match.style.fontStyle = "inherit"; match.style.color = "#000"; var after = node.splitText(regs.index); after.nodeValue = after.nodeValue.substring(regs[0].length); node.parentNode.insertBefore(match, after); } } } // remove highlighted tags from html function removeHighlight() { var arr = document.getElementsByTagName(hilite_tag); while(arr.length && (el = arr[0])) { el.parentNode.replaceChild(el.firstChild, el); } }

The reason for keeping the hilite keyword containing the regular expression outside of the function is to avoid it having to be passed every time as the hightlightWords function loops recursively through all the DOM elements.

Feel free to adapt and use this code as you see fit. We use it to highlight search engine query keywords after the keywords have been extracted from the HTTP Referer using a server-side script, but that's another story.

< JavaScript


User Comments and Notes

wam 25 January, 2011

this is not working for Internet Explorer.How can i fix it?

It looks like you're using Internet Explorer v6. The search highlighting should work in v7 and definitely works in v8 (according to my source).

Send Feedback

Send Feedback (used only for replies) CAPTCHA refresh <- copy the digits from the image into this box

[top]