Vasanth Krishnamoorthy

Software Engineer (Http'ster)

inView – jQuery plugin to track elements viewed

Problem:

UI improvements is all about constantly experimenting with the layout/sections and test it against user metrics to see how it performed. Although tools like google analytics help us with page views and clicks, it was still hard to find out if the user had scrolled through the page to view a particular element on the page.

Solution:

I built this simple lightweight jQuery plugin that fires a callback when an element in a web page is viewed. It basically checks if the element being watched is actually in the viewport of the user. If so, the callback function is fired.

Use cases:

  • Log views to a particular element on the page.
  • Show ads based on elements viewed.
  • Add cool site animations eg. Animate the ‘Next’ button at the end of a blog article.

The annotated source code for this plugin is given below:

/**
 *
 * InView jQuery Plugin
 *
 * Watch elements on the page (#id elements) and fire a callback function when it is viewed.
 * @author: Vasanth Krishnamoorthy
 *
 * Do What The F*ck You Want To Public License (WTFPL)
 *
 */

(function ($, window) {
    var cache = [],
        inViewItems = 0,
        $w = $(window);

    $.fn.inView = function (callback) {
        if (typeof callback !== 'function') {
            return;
        }
        var $element = $(this),
        // Used to refer elements being watched on the page.
            selectorName = $element.selector;

        inViewItems++;

        // Custom event handler
        $w.on('scroll.inView', throttle(function () {
            var winHeight = window.innerHeight || $w.height(),    // < IE9 doesn't use window property
                scrollDepth = $w.scrollTop() + winHeight;

            // Unbind scroll after all elements to be watched have been viewed
            if (cache.length >= inViewItems) {
                $w.off('scroll.inView');
                return;
            }

            // Fire callback function
            if ($element.length && $.inArray(selectorName, cache) === -1 && scrollDepth >= $element.offset().top) {
                callback.call(this);
                cache.push(selectorName);
            }
        }));

        //  Rate limit scroll event to fire only once in 500ms
        function throttle(fn) {
            var wait = false;
            return function () {
                if (!wait) {
                    fn.call();
                    wait = true;
                    setTimeout(function () {
                        wait = false;
                    }, 500);
                }
            };
        }
    };
})(jQuery, window);

Github

DROP A COMMENT

Your email address will not be published. Required fields are marked *