37
votes

I'm creating a scrolling effect using JQuery and I'm wondering if it's possible to distinguish between the user scrolling vs. programmatically scrolling.

I have something like this:

$('#element').on('scroll',function(e){
    $('#element').stop(true); // stop previous scrolling animation
    $('#element').animate({ // start new scrolling animation (maybe different speed, different direction, etc)
        scrollTop:...
    });
});

However, this event is triggered during every step of the animation. How can I tell if this event was triggered by the user or by the animation?

3
You are looking for event.originalEvent, see event object documentation under Other properties and this fiddle for an example. - Eric Martinez
You could try distinguishing it with the wheel event. A user can fire both wheel and scroll events, whereas jQuery probably only fires the scroll event. - Sebastian Simon
Instead of trying to determine the source of the scroll event, unsubscribe from the event before animate (after stop) and subscribe to scroll event again after animate. - Adam Moszczyński
@AdamMoszczyński The user must be able to stop the scroll animation by scrolling. - Leo Jiang

3 Answers

6
votes

Use a variable to determine when you are scrolling programmatically

Example:

var programScrolling = false;

$('#element').on('scroll',function(e){
    if (programScrolling) {
        return;
    }

    $('#element').stop(true); // stop scrolling animation

    programScrolling = true;

    $('#element').animate({
        scrollTop:...
    });

    programScrolling = false;
});

Not sure if that is exactly what you want, but the concept should work.

4
votes

I would make functions for different kinds of scrollings to detect them and call a scroll handler for all of them, like so:

JS Fiddle

$(window).bind('mousewheel DOMMouseScroll', function(event){
    var direction;
    if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
        direction = 'up';
    }
    else {
        direction = 'down';
    }
    scrollHandler(direction, 'mouseWheel');
    event.preventDefault();
});

var scrollHandler = function(direction, origin) {
    var height = $(document).scrollTop();
    var movement = (direction == 'up') ? -100 : 100;
    console.log(origin);
    $('body').stop(true);
    $('body').animate({
        scrollTop: height + movement
    }, 250);
};

Then you can do different stuff according to the origin of the event!
You could also check if the user scrolls to the same direction that the screen is scrolling and do something different, or whatever you want with the info passed by the mousewheel event.

Original mousewheel event function copied from THIS answer

-1
votes

I would suggest possibly using the .originalEvent method. The downside is, this is very browser dependent. See here. Hopefully the following helps:

$('#element').scroll(function(e){
    var humanScroll = e.originalEvent === undefined;
    if(humanScroll) {
        $(this).stop(true);
    }
})