Eric Strom
Eric Strom

Reputation: 725

jQuery scroll event fires twice

I'm working on making an infinite scroll function for a page and am running into an issue where it appears that the $( window ).scroll() function is firing twice. I've seen similar questions on stackoverflow, but they seem to be related to fast scrolls and not having something in place to check weather the request has already been sent. Here's the code that I'm working with right now, I imagine that its something easy that I'm missing here.

var loading = false;
var scrollcount = 0;

$( window ).scroll( function(){
    scrollcount++;
    var scrolling = $( document ).scrollTop();
    var position = $( "#ajax-load" ).offset();
    if( scrolling + $( window ).height() > position.top - 200 && loading == false ){
        console.log( loading ); //returns 2 falses
        console.log( scrollcount ); //returns 2 of the same number
        console.log( $( document ).scrollTop() ); //returns same number
        loading = true;
        $( "#ajax-load" ).css( "display", "block" );
        $.get( "url/to/my/script", info )
        .done( function( data ){
            //here's where the items are appended to the document
            setTimeout( function(){
                loading = false;
            }, 5000 );
        });
    }
});

The face that when I log out the scrollcount variable and the return from scrollTop() I get the same number twice seems to tell me that the event is actually firing twice at the same time for some reason. It seems that if it were firing twice, one after the other, the loading variable would be set to false and not fire that second time. Like I said, I imagine that it's something super simple that I'm missing. Thanks for your help!

Upvotes: 1

Views: 6024

Answers (3)

ParanoidCoder
ParanoidCoder

Reputation: 144

I tinkered with this and tried some of the above solutions. None work 100% with major browsers for my use case (which was a simple scroll loader). To avoid using setTimeout and ONLY execute a specific function within a set duration, create this function object literal:

var hlpr = {
        lastExec: new Date().getTime(),
        isThrottled: function (timeout) {
            if ((new Date().getTime() - this.lastExec) < timeout) {
                console.log('returned');
                return false;
            }
            this.lastExec = new Date().getTime();
            return true;
        }
};

And then add this to the function you have bound to your scroll event:

if (!hlpr.isThrottled(500))
     return;

This way, the scrollbar event can fire off as weirdly as it wants but your attached function will never execute twice within a certain interval. The double-firing of the scroll event happens much faster than 500ms but since my usage was for a scroll loader, all I needed to ensure was that the function fired once within a 500ms window.

Upvotes: 2

Hardik Patil
Hardik Patil

Reputation: 97

var timeout;

$(window).scroll(function() {
    clearTimeout(timeout);  
    timeout = setTimeout(function() {
        // do your stuff
    }, 50);
});

Use this code.

Upvotes: 3

user3587083
user3587083

Reputation: 71

My first guess is you have the event listener applied twice, wherever this code is.

Try adding $(window).unbind('scroll'); before $(window).scroll

The loading variable would be false for when it fires twice because false is set on a timeout, after an async call

Upvotes: 6

Related Questions