23

If I have this

window.onresize = function() {
  alert('resized!!');
};

My function gets fired multiple times throughout the resize, but I want to capture the completion of the resize. This is in IE.

Any ideas? There are various ideas out there, but not has worked for me so far (example IE's supposed window.onresizeend event.)

UpTheCreek
  • 31,444
  • 34
  • 152
  • 221
blogofsongs
  • 2,527
  • 4
  • 21
  • 26
  • Your version of windows is configured to repaint the screen *while* you resize window. So the event is firing properly. You can adjust this in your advanced performance settings in System Properties. – Josh Stodola Sep 30 '09 at 21:31

7 Answers7

31

In this case, I would strongly suggest debouncing. The most simple, effective, and reliable way to do this in JavaScript that I've found is Ben Alman's jQuery plugin, Throttle/Debounce (can be used with or without jQuery - I know... sounds odd).

With debouncing, the code to do this would be as simple as:

$(window).resize($.debounce(1000, function() {
   // Handle your resize only once total, after a one second calm.
   ...
}));

Hope that can help someone. ;)

Lance
  • 5,655
  • 4
  • 30
  • 32
  • First line is more like $(window).resize($.debounce(1000, true, function(e) { – Philippe Jun 09 '10 at 20:07
  • 1
    @Philppe: That's interesting, because that's not what Ben's sample says, nor is that what I have in my working code. – Lance Jun 09 '10 at 20:47
  • @Lance May : That's odd because if you look the source of his example page http://jsfiddle.net/cowboy/cTZJU/show/, it's exactly as I wrote. Maybe he updated his script? Edit your answer, I'll vote it up. – Philippe Jun 10 '10 at 19:32
  • @Philippe: The link I gave in the post is the only page I've viewed from him on the matter (as it's most certainly clear enough there). The debounce example shown directly on that page shows exactly `$('input:text').keyup( $.debounce( 250, ajax_lookup ) );`, and this is what I have used in my own code as well. The `... true, ...` option that you are down ranking me for is clearly stated as optional and defaulting: "Debounced with at_begin specified as false *or unspecified:*". – Lance Jun 10 '10 at 20:07
  • I have a demo that gives an error with your line but not with mine. The 'new' keyword makes IE7 bark a javascript 'error on object blabla'. If you could edit your post, I will be able to upvote. – Philippe Jun 10 '10 at 20:53
  • @Philippe: Ah! The 'new'. Yeah, basic syntax 101, my bad. It was off the top of my head, and I was referring to the usage of the plugin and thought that was what you were disagreeing with. Misunderstanding. Apologies. – Lance Jun 11 '10 at 12:42
  • Thank you Lance. I'm using your suggestion : Ben Alman's throttle/debounce script and it works nicely. Thank you. – Philippe Jun 15 '10 at 12:46
9

I always use this when I want to do something after resizing. The calls to setTimeout and clearTimeout are not of any noticable impact on the speed of the resizing, so it's not a problem that these are called multiple times.

var timeOut = null;
var func = function() { /* snip, onresize code here */};
window.onresize = function(){
   if(timeOut != null) clearTimeout(timeOut);
   timeOut = setTimeout(func, 100);
}
kapex
  • 28,903
  • 6
  • 107
  • 121
Pim Jager
  • 31,965
  • 17
  • 72
  • 98
5

This is not perfect but it should give you the start you need.

var initialX = null;
var initialY = null;
var lastResize = null;
var waiting = false;
var first = true;
var id = 0;

function updateResizeTime()
{
    if (initialX === event.clientX && initialY === event.clientY)
    {
        return;
    }

    initialX = event.clientX;
    initialY = event.clientY;

    if (first)
    {
        first = false;
        return;
    }

    lastResize = new Date();            
    if (!waiting && id == 0)
    {
        waiting = true;
        id = setInterval(checkForResizeEnd, 1000);
    }
}

function checkForResizeEnd()
{
    if ((new Date()).getTime() - lastResize.getTime() >= 1000)
    {
        waiting = false;
        clearInterval(id);
        id = 0;
        alert('hey!');
    }
}

window.onresize = function()
{
    updateResizeTime();
}
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
4

You get multiple events because there really are multiple events. Windows animates the resize by doing it several times as you drag the window (by default, you can change it in the registry I think).

What you could do is add a delay. Do a clearTimeout, setTimout(myResize,1000) every time the IE event fires. Then, only the last one will do the actual resize.

lod3n
  • 2,893
  • 15
  • 16
  • I don't think you need to worry about the registry. I think it is in the performance settings panel on windows. The one that has the different options like menu animations, shadows, etc. – Arlen Beiler Mar 26 '12 at 15:38
2

simple pure javascript solution, just change the 1000 int value to be lower for more responsiveness

        var resizing = false;
        window.onresize = function() {
            if(resizing) return;
            console.log("resize");
            resizing = true;
            setTimeout(function() {resizing = false;}, 1000);
        };
1-14x0r
  • 1,697
  • 1
  • 16
  • 19
1

Not sure if this might help, but since it seems to be working perfectly, here it is. I have taken the snippet from the previous post and modified it slightly. The function doCenter() first translates px to em and than substracts the width of the object and divides the remainder by 2. The result is assigned as left margin. doCenter() is executed to center the object. timeout fires when the window is resized executing doCenter() again.

function doCenter() {
document.getElementById("menuWrapper").style.position = "fixed";
var getEM = (window.innerWidth * 0.063);
document.getElementById("menuWrapper").style.left = (getEM - 40) / 2 + "em";
}

doCenter();

var timeOut = null;
var func = function() {doCenter()};
window.onresize = function(){
    if (timeOut != null) clearTimeout(timeOut);
    timeOut = setTimeout(func, 100);
};
0

I liked Pim Jager's elegant solution, though I think that there's an extra paren at the end and I think that maybe the setTimeout should be "timeOut = setTimeout(func,100);"

Here's my version using Dojo (assuming a function defined called demo_resize())...

var _semaphorRS = null;
dojo.connect(window,"resize",function(){
 if (_semaphorRS != null) clearTimeout(_semaphorRS);
 _semaphorRS = setTimeout(demo_resize, 500);
 });

Note: in my version the trailing paren IS required.

jfkelley
  • 83
  • 2