0

I have a simple JS that would smoothly autoscroll to another div whenever mousewheel is moved up or down.

Here's the script:

    $(document).bind('mousewheel', function(evt) {
        var delta = evt.originalEvent.wheelDelta
        if(delta < 0){
                $('html, body').animate({
                    scrollTop: $("#content-wrapper").offset().top
                }, 3000);
        }
        else {
                $('html, body').animate({
                scrollTop: $("#bgheader").offset().top
                }, 3000);
        }         
    });

My problem is that if i play for a few seconds with the mousewheel it would start scrolling here and there forever, since every move recorded is queued as additional script launch.

Is there any way to put some sort of 'cooldown' to the script? So that after using once it would become avaiable to use again in, let's say' 3 seconds? Or once the animation is finished?

Damian Doman
  • 522
  • 8
  • 19
  • 3
    Google "debouncing". – Barmar Jan 12 '17 at 23:28
  • Possibly related: [how to disable scrolling temporarily](http://stackoverflow.com/questions/4770025/how-to-disable-scrolling-temporarily) – Hodrobond Jan 12 '17 at 23:32
  • Barmar - i've heard about it but as my knowledge about jquery/pure js is kinda limited i'm trying to stay away from UnderScore and other libraries, still debouncing would definitely solve this issue so thank for the contribution! – Damian Doman Jan 12 '17 at 23:57
  • @Hodrobond i'm afraid that's not exactly what i meant, thanks for responding tho. – Damian Doman Jan 12 '17 at 23:58

2 Answers2

1

You can unbind the wheel event listener, and then use jQuery's .animate() callback function to re attach the event listener after it is done, like so:

function scrollHandler (event) {
    $(document).off("mousewheel.custom");
    var delta = event.originalEvent.wheelDelta
    if(delta < 0){
        $('html, body').animate({
            scrollTop: $("#content-wrapper").offset().top
        }, 3000, function () {
            // animation callback function
            $(document).on("mousewheel.custom", scrollHandler);
        }));
    }
    else {
        $('html, body').animate({
           scrollTop: $("#bgheader").offset().top
        }, 3000, function () {
          // animation callback function
          $(document).on("mousewheel.custom", scrollHandler);
        });
    }
}

// namespace the event so we can easily .off() it
$(document).on('mousewheel.custom', scrollHandler);
mhodges
  • 10,938
  • 2
  • 28
  • 46
  • This works perfect, probably it's the best way to solve it without using external libraries like UnderScore.js with it's debounce function. Thank you mhodges! – Damian Doman Jan 12 '17 at 23:55
0

I've used timeouts.

var maxPoll = 3000,
    eventActive = false;

$(document).bind('mousewheel', function(evt) {
    if(eventActive) { 
        return
    } else {
        setTimeout(maxPoll, function() { eventActive = True })
    }
    var delta = evt.originalEvent.wheelDelta
    if(delta < 0){
        $('html, body').animate({
            scrollTop: $("#content-wrapper").offset().top
        }, maxPoll);
    }
    else {
        $('html, body').animate({
            scrollTop: $("#bgheader").offset().top
        }, maxPoll);
    }         
});

It's rough and it uses globals, but it basically turns off your event while the animation is running.

Ogre Codes
  • 18,693
  • 1
  • 17
  • 24
  • Yeah i've tried using timeouts too, but it still launches tons of script runs, they are just delayed by 3sec. Thanks for your reply tho! – Damian Doman Jan 12 '17 at 23:53