Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event when user stops scrolling

You can make the scroll() have a time-out that gets overwritten each times the user scrolls. That way, when he stops after a certain amount of milliseconds your script is run, but if he scrolls in the meantime the counter will start over again and the script will wait until he is done scrolling again.

Update:

Because this question got some action again I figured I might as well update it with a jQuery extension that adds a scrollEnd event

// extension:
$.fn.scrollEnd = function(callback, timeout) {          
  $(this).on('scroll', function(){
    var $this = $(this);
    if ($this.data('scrollTimeout')) {
      clearTimeout($this.data('scrollTimeout'));
    }
    $this.data('scrollTimeout', setTimeout(callback,timeout));
  });
};

// how to call it (with a 1000ms timeout):
$(window).scrollEnd(function(){
    alert('stopped scrolling');
}, 1000);
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>

<div style="height: 200vh">
  Long div
</div>

Here is a simple example using setTimeout to fire a function when the user stops scrolling:

(function() {        
    var timer;
    $(window).bind('scroll',function () {
        clearTimeout(timer);
        timer = setTimeout( refresh , 150 );
    });
    var refresh = function () { 
        // do stuff
        console.log('Stopped Scrolling'); 
    };
})();

The timer is cleared while the scroll event is firing. Once scrolling stops, the refresh function is fired.

Or as a plugin:

$.fn.afterwards = function (event, callback, timeout) {
    var self = $(this), delay = timeout || 16;

    self.each(function () { 
        var $t = $(this);
        $t.on(event, function(){
            if ($t.data(event+'-timeout')) {
                clearTimeout($t.data(event+'-timeout'));
            }
            $t.data(event + '-timeout', setTimeout(function () { callback.apply($t); },delay));
        })
    });
    return this;
};

To fire callback after 100ms of the last scroll event on a div (with namespace):

$('div.mydiv').afterwards('scroll.mynamespace', function(e) {
        // do stuff when stops scrolling
        $(this).addClass('stopped');
    }, 100
);

I use this for scroll and resize.


Here is another more generic solution based on the same ideas mentioned:

var delayedExec = function(after, fn) {
    var timer;
    return function() {
        timer && clearTimeout(timer);
        timer = setTimeout(fn, after);
    };
};

var scrollStopper = delayedExec(500, function() {
    console.log('stopped it');
});

document.getElementById('box').addEventListener('scroll', scrollStopper);

Why so complicated? As the documentation points out, this http://jsfiddle.net/x3s7F/9/ works!

$('.frame').scroll(function() {
 $('.back').hide().fadeIn(100);
}

http://api.jquery.com/scroll/.


Note: The scroll event on Windows Chrome is differently to all others. You need to scroll fast to get the same as result as in e.g. FF. Look at https://liebdich.biz/back.min.js the "X" function.

Some findings from my how many ms a scroll event test:

  • Safari, Mac FF, Mac Chrome: ~16ms an event.
  • Windows FF: ~19ms an event.
  • Windows Chrome: up to ~130ms an event, when scrolling slow.
  • Internet Explorer: up to ~110ms an event.

http://jsfiddle.net/TRNCFRMCN/1Lygop32/4/.


I had the need to implement onScrollEnd event discussed hear as well. The idea of using timer works for me.

I implement this using JavaScript Module Pattern:

var WindowCustomEventsModule = (function(){

    var _scrollEndTimeout = 30;

    var _delayedExec = function(callback){
        var timer;
        return function(){
            timer && clearTimeout(timer);
            timer = setTimeout(callback, _scrollEndTimeout);
        }
    };

    var onScrollEnd = function(callback) { 
        window.addEventListener('scroll', _delayedExec(callback), false);         
    };

    return {
        onScrollEnd: onScrollEnd
    }
})();

// usage example
WindowCustomEventsModule.onScrollEnd(function(){
    //
    // do stuff
    //
});

Hope this will help / inspire someone


There is no such event as 'scrollEnd'. I recommend that you check the value returned by scroll() every once in a while (say, 200ms) using setInterval, and record the delta between the current and the previous value. If the delta becomes zero, you can use it as your event.