adamdehaven
adamdehaven

Reputation: 5920

How to use this function in jQuery

I have the following jQuery function which is supposed to detect when an element first scrolls into view on a page:

function isScrolledIntoView(elem) {
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

My mind is mush today... how can I use this function?

Assume I want to detect when $('.guardrail360') comes into view.

Upvotes: 1

Views: 559

Answers (3)

Jens Roland
Jens Roland

Reputation: 27770

There are several ways to do it. Just don't use a naive window.scroll implementation if you are concerned with user experience and/or performance.

It's a very, very, bad idea to attach handlers to the window scroll event. Depending upon the browser the scroll event can fire a lot and putting code in the scroll callback will slow down any attempts to scroll the page (not a good idea). Any performance degradation in the scroll handler(s) as a result will only compound the performance of scrolling overall. Instead it's much better to use some form of a timer to check every X milliseconds OR to attach a scroll event and only run your code after a delay (or even after a given number of executions - and then a delay).

-John Resig, creator of jQuery, on ejohn.org

Method 1: setInterval

First, there is the naive approach using timers:

var $el = $('.guardrail360');

var timer = setInterval(function() {
    if (isScrolledIntoView($el)) {
        // do stuff

        // to run this block only once, simply uncomment the next line:
        //clearInterval(timer);
    }
}, 150);

Method 2: window.scroll event

Then there is the trivial, yet crazy inefficient way using the scroll event (depending on the browser, the scroll event will fire hundreds of times per second, so you do NOT want to run a lot of code in here, particularly not code that triggers browser reflows/redraws).

Ever visited a site where scrolling down the page felt sluggish and jittery? That is often caused by a piece of code like this one right here:

var $el = $('.guardrail360');

$(window).on('scroll', function() {
    if (isScrolledIntoView($el)) {
        // do stuff
    }
});

Method 3: best of both worlds

The nifty hybrid approach for high traffic sites, as proposed by John Resig in the aforementioned blog post:

var $el = $('.guardrail360'),
    didScroll = false;

$(window).scroll(function() {
    didScroll = true;
});

var timer = setInterval(function() {
    if ( didScroll ) {
        didScroll = false;
        if (isScrolledIntoView($el)) {
            // do stuff

            // to run this block only once, simply uncomment the next line:
            //clearInterval(timer);
        }
    }
}, 250);

Method 4: Throttling / Debouncing

Throttling (minimum N milliseconds between invocations) or debouncing (only one invocation per 'burst') patterns can also be used to efficiently limit the rate at which your inner code executes. Assuming you'd be using Ben Alman's jQuery throttle/debounce plugin, the code looks like this:

var $el = $('.guardrail360');

// Throttling
$(window).on('scroll', $.throttle( 250, function(){
    if (isScrolledIntoView($el)) {
        // do stuff
    }
}));

// Debouncing
$(window).on('scroll', $.debounce( 250, function(){
    if (isScrolledIntoView($el)) {
        // do stuff
    }
}));

(Note that debouncing acts slightly differently from the other implementations, but that can sometimes be what you want, depending on your user experience scenario)

Upvotes: 2

David G
David G

Reputation: 96790

if ( isScrolledIntoView('.guardrail360') ) {

}

As suggested by the other answers, you should use act upon $(window).scroll(). In addition, in order to make the if statement run the first time the element is scrolled into view, I created this run_once function for you:

$('window').on('scroll', function() {

    if ( isScrolledIntoView('.guardrail360') ) run_once(function() {
            // ...
    });

});

function run_once( callback ) {

    var done = false;

    return function() {

        if ( !done ) {

            done = true;

            return callback.apply( this, arguments );

        }

    };

}

Upvotes: 0

AJak
AJak

Reputation: 3873

Seems like you need to bind the scroll event and do the detection when that event fires.

$(window).scroll(function () { 
  isScrolledIntoView('.guardrail360');
});

Upvotes: 2

Related Questions