ntownsend
ntownsend

Reputation: 7630

Why is the resize event constantly firing when I assign it a handler with a timeout?

I assigned a timeout to my window.resize handler so that I wouldn't call my sizable amount resize code every time the resize event fires. My code looks like this:

<script>
function init() {
  var hasTimedOut = false;
  var resizeHandler = function() {
    // do stuff
    return false;
  };

  window.onresize = function() {
    if (hasTimedOut !== false) {
      clearTimeout(hasTimedOut);
    }
    hasTimedOut = setTimeout(resizeHandler, 100); // 100 milliseconds
  };
}
</script>
<body onload="init();">
...
etc...

In IE7 (and possibly other versions) it appears that when you do this the resize event will constantly fire. More accurately, it will fire after every timeout duration -- 100 milliseconds in this case.

Any ideas why or how to stop this behavior? I'd really rather not call my resize code for every resize event that fires in a single resizing, but this is worse.

Upvotes: 2

Views: 3655

Answers (4)

latitov
latitov

Reputation: 481

I stumbled on the same problem, but solved it differenly, and I think it's more elegant than making a timeout....

The context: I have an iframed page, loaded inside the parent page, and the iframe must notify the parent when its size changes, so the parent can resize the iframe accordingly - achieving dynamic resizing of an iframe.

So, in the iframed HTML document, I tried to register a callback on the body tag. First, on the onchange - it didn't work. Then on resize - it did work, but kept firing constantly. (Later on I found the cause - it was apparently a bug in Firefox, which tried to widen my page to infinity). I tried the ResizeObserver - for no avail, the same thing happened.

The solution I implemented was this:

<body onload="docResizePipe()">
<script>
var v = 0;
const docResizeObserver = new ResizeObserver(() => {
    docResizePipe();
});
docResizeObserver.observe(document.querySelector("body"));
function docResizePipe() {
    v += 1;
    if (v > 5) {
        return;
    }
    var w = document.body.scrollWidth;
    var h = document.body.scrollHeight;
    window.parent.postMessage([w,h], "*");
}
setInterval(function() {
    v -= 1;
    if (v < 0) {
        v = 0;
    }
}, 300);
</script>

So how it works: each time the callback fires, we increment a variable v; once in every 300 ms, we decrement it; if it's too big, the the firing is blocked.

The big advantage of this over the timeout-based solution, is that it introduces to lag for a user experience, and also clear in how exactly it does block the recursion. (Well, actually not )))

Upvotes: 0

Chris Nielsen
Chris Nielsen

Reputation: 14758

IE does indeed constantly fire its resize event while resizing is taking place (which you must know, as you are already implementing a timeout for a fix).

I am able to replicate the results you are seeing, using your code, on my test page.

However, the problem goes away if I increase the timeout to 1000 instead of 100. You may want to try with different wait values to see what works for you.

Here is the test page I used: it has a nicely dynamic wait period already set up for you to play with.

Upvotes: 0

andres descalzo
andres descalzo

Reputation: 14967

How to fix the resize event in IE

also, see the answer for "scunliffe" "In your ... properties?

Upvotes: 0

scunliffe
scunliffe

Reputation: 63676

In your //do stuff code, do you manipulate any of the top,left,width,height,border,margin or padding properties?

You may unintentionally be triggering recursion which unintentionally triggers recursion which unintentionally triggers recursion...

Upvotes: 2

Related Questions