Mini Help System with jQuery

Demo Download

In this tutorial, we are going to create a mini help system with jQuery. This will be a small widget which will display help text or a guide to users of your web application. The widget content is going to be searchable in real time, and all matching terms will be highlighted.

The Idea

For this example to work, here is what we have to do:

  • We have to listen for the input event on the text box. I prefer this to keypress, as input catches events like cut/paste and undo/redo. It is not supported in older browsers (<IE9) though, so you might want to replace it with keypress if you want this example to work there;
  • We will write a jQuery plugin, aptly named "highlight", that will replace the matched text with <span> elements;
  • We will use the jQuery.scrollTo plugin to smoothly scroll the <span> elements into view.
Let's start with the markup.

The HTML

The first step is to lay down the HTML of the page that we will be working on:

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Mini Help System with jQuery | Tutorialzine </title>

        <!-- Our stylesheet -->
        <link rel="stylesheet" href="assets/css/styles.css" />

    </head>
    <body>

        <div id="widget">

            <div id="header">
                <input type="text" id="search" placeholder="Search in the text" />
            </div>

            <div id="content">
                <!-- Your help text goes here -->
            </div>
        </div>​​

        <!-- JavaScript Includes -->
        <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
        <script src="assets/js/highlight.jquery.js"></script>
        <script src="assets/js/jquery.scrollTo.min.js"></script>
        <script src="assets/js/script.js"></script>
    </body>
</html>

There's nothing out of the ordinary here - we are including a stylesheet in the head (you might want to take a look at it yourself, I won't present it in this tutorial), jQuery and the scrollTo plugin at the bottom, along with two more js files that we will be discussing next. The widget has a text field (inside a #header div) and the #content holder. Inside the latter, you should put the help guide for your application.

mini-help-system.jpg

The jQuery Code

Now we're going to write a jQuery plugin that searches for specific words in the #content element, and replaces the occurrences with span elements. For example searching for javascript in the text javascript is awesome would yield <span class="match">javascript</span> is awesome. We will later style the .match spans with an orange background so they are easily distinguishable.

The plugin will take two arguments - a search term (as a string), and an optional callback function that will be executed when the search/replace process is complete. As you will see later, we will use the callback to hook the scrollTo plugin and scroll the #content div to reveal the matches.

Before you start reading this code, keep in mind that you can't simply fetch the inner html of the div, and call replace() on it to replace the search occurrences with span elements, as this way you will break your markup. If someone entered "div" as a search term this would cause all your <div> elements to be replaced with <<span class="match">div</span>>, witch is just asking for trouble.

The solution is a bit more complex (but not difficult once you get the idea) - we will use the contents() jQuery method to fetch all children of the element, and replace() the text only on the text nodes (they are guaranteed to not contain any html). We will then loop through all the element's non-textnode children recursively, and repeat the steps.

assets/js/highlight.jquery.js

(function($) {

    var termPattern;

    $.fn.highlight = function(term, callback) {

        return this.each(function() {

            var elem = $(this);

            if (!elem.data('highlight-original')) {

                // Save the original element content
                elem.data('highlight-original', elem.html());

            } else {

                // restore the original content
                elem.highlightRestore();

            }

            termPattern = new RegExp('(' + term + ')', 'ig');

            // Search the element's contents
            walk(elem);

            // Trigger the callback
            callback && callback(elem.find('.match'));

        });
    };

    $.fn.highlightRestore = function() {

        return this.each(function() {
            var elem = $(this);
            elem.html(elem.data('highlight-original'));
        });

    };

    function walk(elem) {

        elem.contents().each(function() {

            if (this.nodeType == 3) { // text node

                if (termPattern.test(this.nodeValue)) {
                    // wrap the match in a span:
                    $(this).replaceWith(this.nodeValue.replace(termPattern, '<span class="match">$1</span>'));
                }
            } else {
                // recursively call the function on this element
                walk($(this));
            }
        });
    }

})(jQuery);

And voila, our text is full with pretty highlights! Don't worry if you don't quite understand how this works - it is packaged as an easy to use jQuery plugin, so you can drop it in your project without much thought.

Here is how to use the plugin:

assets/js/script.js

$(function() {

    var search = $('#search'),
        content = $('#content'),
        matches = $(), index = 0;

    // Listen for the text input event
    search.on('input', function(e) {

        // Only search for strings 2 characters or more
        if (search.val().length >= 2) {

            // Use the highlight plugin
            content.highlight(search.val(), function(found) {

                matches = found;

                if(matches.length && content.is(':not(:animated)')){
                    scroll(0);
                }

            });
        } else {
            content.highlightRestore();
        }

    });

    search.on('keypress', function(e) {

        if(e.keyCode == 13){ // The enter key
            scrollNext();
        }

    });

    function scroll(i){
        index = i;

        // Trigger the scrollTo plugin. Limit it
        // to the y axis (vertical scroll only)
        content.scrollTo(matches.eq(i), 800, { axis:'y' } );
    }

    function scrollNext(){
        matches.length && scroll( (index + 1) % matches.length );
    }
});

In the callback, I trigger the scroll(0) function. This animates the #content div so it shows the first match of the series. There is another function for scrolling - scrollNext, which is called when you hit the return key while typing. This will cause the holder to reveal the next match.

With this our mini help system is complete!

Conclusion

You can use this example to enhance your help pages. You can also put the highlight plugin we created here to good use and build a better search functionality, enhance your mobile app or much more. I would love to hear your ideas in the comments!

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

Fernando

Very nice and clean...

But I don't know where to use it?

Maybe in some very large text walls. But the concept is iteresting.

The jquery look simple.. I Like it.

Nice concept, inline linking could make it more useful.

Very nice job! I see I can use it according to listing column of nicknames that are already unavailable to registration.
Little remark... It should be useful to switch off y-scroller if the content div height is smaller than widget height.
Thanx, Martin, your posts are unreally both nice and actual! :)

Helpful, thanks for this!

Very nice!

Binte Abdul Rasheed

Hey Martin,

your tutorials are amazing I was waiting for your new tutorial. They are helping me a lot in my projects.

Thanks.

Awesome! Simply and useful.

Nice work! Simple, creative, I like it.

Great work man!!

Srinivas

Hey Martin, Very good tutorial, I am using this in our Employee search page. It is working fine in I.E 9.0 and other browsers. But It is not working in I.E 8.0.

Maitreya Vyas

Then use IE F12 tools and see what's error is sitting there. :)

flexiload

Its really good. I am looking for such kind of script. its really works fast.
thank you very much.

oh that's cool ! carry on

Karthikeyan

Really Cool :)

Thanks for sharing this tutorial..

Hey Martin,
thanks for this great tut dude! I got it to work on a specific & scrollable content div (like your example) but i tried it also to get worked on my hole content-div, which resulted in highlighted text but a not working scoll-function.
Any ideas?
Thanks & keep it on :)
Greets Jan