简体   繁体   中英

window.resize event firing in Internet Explorer

As you are aware, in Internet Explorer, the window.resize event is fired when any element on the page is resized. It does not matter whether the page element is resized through assigning/changing its height or style attribute, by simply adding a child element to it, or whatever -- even though the element resizing does not affect the dimensions of the viewport itself.

In my application, this is causing a nasty recursion, since in my window.resize handler I am resizing some <li> elements, which in turn re-fires window.resize, etc. Again, this is only a problem in IE.

Is there any way to prevent window.resize from firing in IE in response to elements on the page being resized?

I should also mention that I'm using jQuery.

I just discovered another problem which might help you.

I am using jQuery and I have window.resize event to call a function which will re-position the div appended to the body.

Now when I set the LEFT css property of that appended div, the window.resize event get trigger for NO GOOD REASON.

It results in an infinite loop, triggering the window.resize again and again.

The code without fix:

$(window).resize(function(){
    var onResize = function(){
        //The method which alter some css properties triggers 
        //window.resize again and it ends in an infinite loop
        someMethod();
    }
    window.clearTimeout(resizeTimeout);
    resizeTimeout = window.setTimeout(onResize, 10);
});

Solution:

var winWidth = $(window).width(),
    winHeight = $(window).height();

$(window).resize(function(){
    var onResize = function(){
        //The method which alter some css properties triggers 
        //window.resize again and it ends in an infinite loop
        someMethod();
    }

    //New height and width
    var winNewWidth = $(window).width(),
        winNewHeight = $(window).height();

    // compare the new height and width with old one
    if(winWidth!=winNewWidth || winHeight!=winNewHeight){
        window.clearTimeout(resizeTimeout);
        resizeTimeout = window.setTimeout(onResize, 10);
    }
    //Update the width and height
    winWidth = winNewWidth;
    winHeight = winNewHeight;
});

So basically it will check if the height or width is changed (which will happen ONLY when you actually resize with window).

this made sense to me and seems to work in IE7 and above:

    //variables to confirm window height and width
    var lastWindowHeight = $(window).height();
    var lastWindowWidth = $(window).width();

    $(window).resize(function() {

        //confirm window was actually resized
        if($(window).height()!=lastWindowHeight || $(window).width()!=lastWindowWidth){

            //set this windows size
            lastWindowHeight = $(window).height();
            lastWindowWidth = $(window).width();

            //call my function
            myfunction();


        }
    });

Bind your resize listener with .one() so that it unbinds itself after firing. Then you can do anything you want, so long as at the end you rebind the resize listener. I found the easiest way to do this is by putting the resize listener in an anonymous function like so:

var resizeListener = function(){
  $(window).one("resize",function(){ //unbinds itself every time it fires

    //resize things

    setTimeout(resizeListener,100); //rebinds itself after 100ms
  });
}
resizeListener();

You don't technically need the setTimeout wrapped around the resizeListener() but I'd threw it in there as a just-in-case and for some extra throttling.

I solved it by unbinding the resize function, rebuilding the page and then binding the resize function again:

function rebuild() {
   $(window).unbind('resize');
   /* do stuff here */
   $(window).bind('resize',rebuild);
}

$(window).bind('resize',rebuild);

EDIT

Bind and unbind don't go well with IE8. Though Microsoft even gave up on IE8 you might want to try this (untested!):

function rebuild(){
   if(!window.resizing) return false;
   window.resizing=true;
   /* do stuff here */
   window.resizing=false;
}

window.resizing=false;
document.body.onresize=rebuild;

@AamirAfridi.com's answer solved my problem.

It's a good idea to write a common function to solve such stuff:

function onWindowResize(callback) {
    var width = $(window).width(),
        height = $(window).height();

    $(window).resize(function() {
        var newWidth = $(window).width(),
            newHeight = $(window).height();

        if (newWidth !== width || newHeight !== height) {
            width = newWidth;
            height = newHeight;
            callback();
        }
    });
}

Use it like this, and you don't have to worry about the different behavior in IE any more:

onWindowResize(function() {
    // do something
});

A mix of the unbind / bind method with a delayed call. It works in Internet Explorer 8 and below, preventing evil loop and hangs on versions 6 and 7.

function resizeViewport()
{
    // Unbind and rebind only for IE < 9
    var isOldIE = document.all && !document.getElementsByClassName;

    if( isOldIE )
        $(window).unbind( 'resize', resizeViewport );

    // ...

    if( isOldIE )
    {
        setTimeout(function(){
            $(window).resize( resizeViewport );
        }, 100);
    }
}

$(window).resize( resizeViewport );

You can try this:

Constructor:

this.clientWidth = null;
this.clientHeight = null;

Some function:

var clientWidth = window.innerWidth || document.documentElement.clientWidth; 
var clientHeight = window.innerHeight || document.documentElement.clientHeight;
if (clientWidth != this.clientWidth || clientHeight != this.clientHeight ) {
    this.clientWidth = clientWidth;
    this.clientHeight = clientHeight;

    ... YOUR CODE ...
} 

For Internet Explorer, Chrome, Firefox, Opera, and Safari:

window.innerHeight - the inner height of the browser window
window.innerWidth - the inner width of the browser window

For Internet Explorer 8, 7, 6, 5:

document.documentElement.clientHeight
document.documentElement.clientWidth
    or
document.body.clientHeight
document.body.clientWidth

I ran into this problem today and decided to put the following at the top of my global included javascript file:

var savedHeight = 0;
var savedWidth = 0;
Event.observe(window, 'resize', function (e) {
    if (window.innerHeight == savedHeight && 
        window.innerWidth == savedWidth) { e.stop(); }
    savedHeight = window.innerHeight;
    savedWidth = window.innerWidth;
});

That requires Prototype, by the way.

(function ($){
     //if ie8 -> return;
     var lastHeight = 0;
     var lastWidth = 0;
     $(window).resize(function(event){
         if (window.innerHeight == lastHeight && window.innerWidth == lastWidth)
             { event.stopImmediatePropagation(); }
         lastHeight = window.innerHeight;
         lastHeight = window.innerWidth;
     });
})();

does the trick for me...

<pre>



var cont = 0;
var tmRsize = 100;
var lastWindowWidth = $(window).width();
var lastWindowHeight = $(window).height();

/*****redimensionamiento**********/
$(window).resize(function()
{
    if($(window).width() != lastWindowWidth || $(window).height() != lastWindowHeight)
    {
        clearTimeout(this.id);
        this.tiempo = tmRsize;
        this.id = setTimeout(doResize, this.tiempo);
    }
});

function doResize()
{
    lastWindowWidth = $(window).width();
    lastWindowHeight = $(window).height();

    $('#destino_1').html(cont++);
}

Here's how i deal with finding out if the resize event was fired by an element or by really resizing the window:

If the event's target.nodeType doesn't exist, it is most likely the window, as any other element on the page would have a nodeType.

So here's the pseudo-code (using jQuery) with the added check:

$(window).resize(function(event){
    if ( $(event.target.nodeType).length == 0 ){
        // Anything here is run when the window was resized
        // not executed when an element triggered the resize
    }
});

I couldn't get the resize event to fire when an element resized (only tried in IE8 though).

However what is the target on the event object when you're experiencing this issue, could you do:

$(window).resize(function(e) {
    if( e.target != window ) return;
    // your stuff here
});

My patch:

<!--[if lte IE 7]>
<script type="text/javascript">
  window.onresize = null;       // patch to prevent infinite loop in IE6 and IE7
</script>
<![endif]-->

It is up to the how contents are on the resize event.

I figured out the above solves only when a page consists of static contents, not dynamically rendered ones. In the dynamic case where the existing contents will be re-rendered by some trigger event like a contents reload function, we need to use $(document).width() or $(document).height() instead.

This is because of scroll bar of the window. If a page has the scroll bar and the main contents will be re-rendered by clicking a button “Reload”, the scroll bar disappears on the event. In that case, $(window).width() or $(window).height() is changed by the contents rendering, not by the actual window resizing.

http://www.tech-step.net/?p=466

$(window).resize(function(event)
{
    if (typeof event.target.tagName == 'undefined')
    {
        // ...
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM