For a thing I’m working on, I needed a ‘debounced‘ resize event, as the $(window).resize event keeps firing as long as the user resizes his window. Maximizing the window with a single click just causes 1 event fired, but by dragging the browser window bigger/smaller, the event will fire lots and lots (and lots) of times. If your script depends on operations that need to be executed on a resize, and these operations are intense, this can cause your script to go haywire and hang/crash the browser. Besides that, it’s annoying to have your script do the same stuff over and over again.

In my search for a solution I stumbled across this great post by Paul Irish, where he basically handed me the solution; a debounced resize function. Worked great!

I decided to rewrite it into a function prototype, so regular JavaScript functions could be debounced easily, and to complement this I wrote an additional jQuery wrapper that can be used to debounce jQuery methods:

View/fork on Github: https://gist.github.com/c-kick/4b37addd9e3019e703342d23c4f29b2c

Using this function prototype and jQuery wrapper, you can register new functions on the fly, based on their ‘regular’ counterparts. You will also need to define a timeout value, which specifies the time the function will wait to see if the event has stopped firing, after which it will finally execute the code you provide.

In the example below, I register both smartresize, smartscroll and smartmousemove as the debounced counterparts of resize, scroll and mousemove, and set them to a debounce delay of 100ms:

//register debouncing functions
//jQdeBounce(jQuery,'new eventname', 'original event', timeout);
//Note: keep the jQuery namespace in mind, don't overwrite existing functions!

jQdeBounce(jQuery,'smartresize', 'resize', 100);
jQdeBounce(jQuery,'smartscroll', 'scroll', 100);
jQdeBounce(jQuery,'smartmousemove', 'mousemove', 100);

//You can also debounce your own custom 'MyFunction' function, 
//by using the deBounce function prototype when calling it:
MyFunction.deBounce(100, false); //calls 'MyFunction' debounced/throttled.

After this, usage is simple:

$(window).smartresize(function(e){
    // do stuff as soon as the user stops resizing his browser for longer than 100ms
})

$(window).smartscroll(function(e){
    // do stuff as soon as the user stops scrolling for longer than 100ms
})

$(window).smartmousemove(function(e){
    // do stuff as soon as the user stops moving his mouse for longer than 100ms
})

Creating a ‘touchpause’ event

Another potential use is extending the touchmove event: when the user touches (and moves his/her finger) across the screen, and then pauses, only the touchmove event is fired. The touchend event will only be fired when the user actually lets go of the screen. And since there is no ‘touchpause’ event, there is no easy way of telling if the user has paused sliding his finger across the screen. Using the deBounce wrapper, we can now create just that:

//define touchpause, extending touchmove
jQdeBounce(jQuery,'touchpause', 'touchmove', 100);

// bind it to something
$('#touched_element').touchpause(function(event) {
    //touch event (and thus touchdata) is still available!
    console.log('touchmove has paused!');
});

This way, when the user touches, drags (moves) and then pauses without leaving the screen, the touchpause event is fired, allowing for some optional script execution. The event will also be fired when the user slides, does not pause, and then lets go, so keep that in mind.

Final note: Although this debouncing script is quite handy; if you need to use this for things other than scroll, resize, touchmove and mousemove events, your code logic might require some rethinking 😉 it’s always better to prevent events from firing in sequence lots of times, rather than working around them.