Emulating a Resize Stop Event in Raw JavaScript or jQuery

July 21, 2011

All major browsers fire a "resize" event on the window object when the browser is resized. This can be extremely useful for managing complex layouts that might not be possible with pure CSS. The problem is that certain browsers fire multiple resize events while the user resizes the window. Generally, this is harmless or even desirable, but if you have to do expensive DOM manipulation on resize, then it becomes quite undesirable. Unfortunately, browsers do not implement a "resizestop" event - which would be handy. Thankfully, we can sort of emulate a "resizestop" event using JavaScript.

I have written two versions of this and both can be found on my GitHub account. There are two versions - a raw JavaScript version and a jQuery "special event" version.

The basic premise of this solution is to listen for the normal window resize event and fire a "resizestop" event when a certain number of milliseconds has passed since the last resize event was fired.

Raw JavaScript Object - window.resizeStop

When using the raw JavaScript version, an object is created on the window object called resizeStop. This object has three methods:

bind
Takes one argument - a callback function - which will fire when it looks like the user has stopped resizing the window. Returns either the index of the callback in the internal cache or Boolean false if the callback was not a function.
unbind
Takes one argument - a number or pointer to a function - which represents the index of a callback in the internal cache (the number returned by bind) or the callback function itself. Returns a Boolean indicating whether the callback was removed from the cache or not.
setThreshold
Takes one argument - a number - which changes the number of milliseconds at which the script decides the user has stopped resizing. This defaults to 500ms.
// Bind a callback and store the index.
var index = window.resizeStop.bind(function () {
    console.log("Stopped resizing!");
});

// Bind a named function and don't store the index.
function stoppedResizing() {
    console.log("Also stopped resizing.");
}

window.resizeStop.bind(stoppedResizing);

// Unbind a callback based on an index.
window.resizeStop.unbind(index);

// Unbind a callback.
window.resizeStop.unbind(stoppedResizing);

// Change the threshold
window.resizeStop.setThreshold(400);

That's all there is to it. Note that the raw JavaScript version does not account for browser deficiencies - namely, it assumes support for Date.now, Array.prototype.indexOf, and window.addEventListener.

jQuery Special Event - "resizestop"

The jQuery version has the same basic functionality - with a little bit of convenience thrown in for good measure!

Additionally, as part of the event data that gets passed to the eventual handler function, the resizestop special event passes the size of the window in an object called "size".

$(window).bind('resizestop', function (e) {
    console.log(this, e.data.size); // window, {width: ???, height: ???}
});

Besides the size of the window getting passed, this jQuery version has the added benefit of being able to be bound to any element or collection of elements:

$('h1').bind('resizestop', function (e) {
    $(this).text('The window is ' + e.data.size.width + ' pixels wide!');
});

In the jQuery version, there is no setThreshold method. Instead, there is a public property which can be changed - $.resizestop.threshold. Again, this defaults to 500ms.

Get the "resizestop" code on my GitHub account