1

I'm playing around with some javascript and JQuery. I'm trying to do something specific each time the user scrolls. It works fine when I use a mouse with a scollwheel. But when I use the trackpad on my laptop it goes incredibly fast. I think it's because it executes the mousewheel function many times when scrolling. So I want to limit how often you can execute the function. Like with a 500ms delay between each call if the user keeps scrolling. It shouldn't delay the functions itself but run immediately and then wait 500ms before it can be executed again. Hope you understand.

Here's my code

$(window).bind('mousewheel', function(event) { // My mousewheel function.
    if (event.originalEvent.wheelDelta >= 0) {
        scroll(-1);
    } else {
        scroll(1);
    }
});

/* Functions */
function scroll(dir) {
    if (dir == -1) {
        if (current > 0) {
            current--;
        }
    } else {
        if (current < list.size() - 1) {
            current++;
        }
    }
    var number = 100 * current;
    var value = "translateY(-" + number + "vh)";
    main.css("transform", value);
    for (var i = 0; i < list.size(); i++) {
        $('#nav li:nth-child(' + (i + 1) + ')').removeClass('active');
    }
    $('#nav li:nth-child(' + (current + 1) + ')').addClass('active');
}
Phoenix1355
  • 1,589
  • 11
  • 16
  • jquery `delay()`? jquery `setInterval()`? – odedta Jun 21 '15 at 12:45
  • I've tried that. But that delays the functions itself. And that is not what I need. I need to add a delay after the function so if the function should be called multiple times in a second or so, it would have to wait the delay before executing. – Phoenix1355 Jun 21 '15 at 12:49
  • Then you need to use chaining. http://www.w3schools.com/jquery/jquery_chaining.asp - http://stackoverflow.com/questions/7475336/how-does-jquery-chaining-work – odedta Jun 21 '15 at 12:55

2 Answers2

1

What you need is a throttle function. This function wraps around other functions and checks the delay in ms and the id of the event.

/**
 * @description delay events with the same id, good for window resize events, scroll, keystroke, etc ...
 * @param {Function} func : callback function to be run when done
 * @param {Integer} wait : integer in milliseconds
 * @param {String} id : unique event id
 */
var throttle = (function () {
    var timers = {};

    return function (func, wait, id) {
        wait = wait || 200;
        id = id || 'anonymous';

        if (timers[id]) {
            clearTimeout(timers[id]);
        }

        timers[id] = setTimeout(func, wait);
    };
})(),

You can use it like this:

$(window).on('mousewheel', function () {
    throttle(function(){
        var isScrollUp = event.originalEvent.wheelDelta >= 0 ? -1 : 1;
        scroll(isScrollUp);
    }, 500, 'my mousewheel event');
});

A nice example of underscore throttle -vs- debounce.

Tim Vermaelen
  • 6,869
  • 1
  • 25
  • 39
1

You need to define a variable that indicate when to run the function or not. in this case is the "isScrolling" variable.

 $(window).bind('mousewheel', function(event) { // My mousewheel function.
            if (event.originalEvent.wheelDelta >= 0) {
                scroll(-1);
            } else {
                scroll(1);
            }
        });

        /* Functions */
        var isScrolling = false; // This variable define when to run the function

        function scroll(dir) {

            if(isScrolling){
                return;
            }
            isScrolling = true;

            if (dir == -1) {
                if (current > 0) {
                    current--;
                }
            } else {
                if (current < list.size() - 1) {
                    current++;
                }
            }
            var number = 100 * current;
            var value = "translateY(-" + number + "vh)";
            main.css("transform", value);
            for (var i = 0; i < list.size(); i++) {
                $('#nav li:nth-child(' + (i + 1) + ')').removeClass('active');
            }
            $('#nav li:nth-child(' + (current + 1) + ')').addClass('active');


            setTimeout(function(){
                isScrolling = false;
            },500) // -> Here you can modify the time between functions call
        }
Nahum
  • 101
  • 6
  • That seems to do the trick. But now I've stumbled upon another problem. When I use my trackpad on my laptop, it has a sort of smooth scrolling that can last more than the 500ms. So then the function is done and it has waited the 500ms, the trackpad scrolling is still going and it runs the whole functions again. Is there a way to prevent that smooth scrolling? – Phoenix1355 Jun 21 '15 at 13:24