Highlight Search Terms

Topics: Themes
Apr 4, 2013 at 5:15 PM
Edited Apr 4, 2013 at 11:14 PM
Hi Folks,
Was reworking my search page and thought search term highlighting might not be a bad thing.
So for anybody interested, here's how it looks, example.

This is pretty easy to implement, I picked up the highlight code on the web (Bartek Szopka) and added the neccessaries to work with BE. I haven't noticed any side effects as yet, but that doesn't preclude there being any, anyway ... here's what you need.

Two steps:
  1. Add the script (as new file or append to a suitable existing script).
  2. Add a function call in your site master page.
The function call requires you to provide 3 parameters, the class or id name of the wrapper element for post items, comments and page, for example:
 <script type="text/javascript">
    //<![CDATA[

        $(document).ready(function () {
            highlightSearchTerms({postWrapper:".postItem", commentWrapper:"#comments", pageWrapper:"#page" });                                                      
        });        
                    
    //]]>
    </script>
For these parameters, be sure to include the preceding dot if the wrapper element is a class or hash if an id.

The actual script code is as follows:
function highlightSearchTerms(options) {
            
            var searchQueryPos = document.referrer.indexOf("?q=");                    
            if (searchQueryPos > 0) {
                    
                    var settings = {postWrapper:".postItem", commentWrapper:"#comments", pageWrapper:"#page"};
                    jQuery.extend(settings, options);   
        
                    var keyValuePairs = {};                 
                    var queryVars = document.referrer.substring(searchQueryPos + 1).split("&");
                    var keyValuePair;
                    for(var queryItem = 0 ; queryItem < queryVars.length; queryItem++) {
                        keyValuePair = queryVars[queryItem].split("=");
                        keyValuePairs[unescape(keyValuePair[0])] = (keyValuePair.length > 1) ? unescape(keyValuePair[1]) : "";
                    }
                    var searchTerms = keyValuePairs.q.split(" ");
                    var includeComments = keyValuePairs.comment;
                    
                    var isPage = $(settings.pageWrapper).length > 0;                                        
                    
                    if(isPage) {
                        $(settings.pageWrapper).highlight(searchTerms);
                    }                    
                    else {
                        if(includeComments) {
                            var highlightAreas = settings.postWrapper + ", " + settings.commentWrapper;
                            $(highlightAreas).highlight(searchTerms);   
                        } else {
                            $(settings.postWrapper).highlight(searchTerms); 
                        }
                    }                                                   
            }
}

jQuery.extend({
    highlight: function (node, re, nodeName, className) {
        if (node.nodeType === 3) {
            var match = node.data.match(re);
            if (match) {
                var highlight = document.createElement(nodeName || 'span');
                highlight.className = className || 'highlight';
                var wordNode = node.splitText(match.index);
                wordNode.splitText(match[0].length);
                var wordClone = wordNode.cloneNode(true);
                highlight.appendChild(wordClone);
                wordNode.parentNode.replaceChild(highlight, wordNode);
                return 1; //skip added node in parent
            }
        } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
                !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
                !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
            }
        }
        return 0;
    }
});


jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);
    
    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(word, i){
      return word != '';
    });
    words = jQuery.map(words, function(word, i) {
      return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);
    
    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className);
    });
};
One thing I forgot, you will need to add a class to your CSS stylesheet.
.highlight {
    background-color:#FFFF96;
}