Fenster.Resize-Ereignis wird im Internet Explorer ausgelöst

76

Wie Sie wissen, wird in Internet Explorer das Ereignis window.resize ausgelöst, wenn die Größe eines Elements auf der Seite geändert wird. Es spielt keine Rolle, ob die Größe des Seitenelements durch Zuweisen / Ändern seiner Höhe oder seines Stilattributs, durch einfaches Hinzufügen eines untergeordneten Elements oder was auch immer geändert wird - auch wenn die Größenänderung des Elements keine Auswirkungen auf die Abmessungen des Ansichtsfensters selbst hat.

In meiner Anwendung führt dies zu einer unangenehmen Rekursion, da ich in meinem window.resize-Handler die Größe einiger <li> -Elemente ändere, wodurch wiederum window.resize usw. neu ausgelöst wird. Auch dies ist nur ein Problem im IE.

Gibt es eine Möglichkeit zu verhindern , dass window.resize im IE als Reaktion auf Elemente auf der Seite ausgelöst wird, deren Größe geändert wird?

Ich sollte auch erwähnen, dass ich jQuery verwende.

MissingLinq
quelle
2
Interessant, das wusste ich nicht. Ich bin mit JQuery nicht vertraut, aber es sollte möglich sein, das Ereignis zu stoppen, wenn sein Quellelement nicht das Fenster selbst ist. Ich bin sicher, jemand wird eine codierte Lösung finden.
Pekka
In welcher Version von IE ist dies und können Sie Code bereitstellen, der tatsächlich die Größenänderung eines Elements zeigt, das window.resize auslöst?
DEfusion
Nicht über andere Versionen sollte, aber es passiert in IE 8
Cocowalla
1
Ich kann dir nicht genug für diese Frage danken. Ich zog mir immer wieder die Haare aus: "WARUM IST MEINE SEITE SO LANGSAM?" Es stellte sich heraus, dass ie8 immer wieder window.resize auf jedem Frame auslöste und dann mein Resize-Handler alles immer wieder neu positionieren musste
user151496
Danke dafür. Kann bestätigen, dass es sich auch um ein Problem mit IE9 handelt.
SAGExSDX

Antworten:

60

Ich habe gerade ein anderes Problem entdeckt, das Ihnen helfen könnte.

Ich verwende jQuery und habe das Ereignis window.resize, um eine Funktion aufzurufen, die das an den Body angehängte div neu positioniert.

Wenn ich nun die LEFT-CSS-Eigenschaft dieses angehängten Divs festlege, wird das window.resize-Ereignis für NO GOOD REASON ausgelöst.

Dies führt zu einer Endlosschleife, die immer wieder die Größe des Fensters auslöst.

Der Code ohne 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);
});

Lösung:

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;
});

Im Grunde wird also geprüft, ob die Höhe oder Breite geändert wird (was NUR dann geschieht, wenn Sie die Größe tatsächlich mit dem Fenster ändern).

Aamir Afridi
quelle
Aamir, sieht so aus. Lass es mich versuchen und ich komme zurück und lass dich wissen, wie es funktioniert hat.
MissingLinq
1
Vielen Dank für die Idee, zu überprüfen, ob sich die Breite / Höhe des Fensters geändert hat, um festzustellen, ob die Größe des Fensters tatsächlich geändert wurde oder nicht!
Bryan Denny
ist onResize absichtlich global oder haben Sie die Variable vergessen?
Jethro Larson
Tolle Lösung - hatte die gleiche Endlosschleifensituation, die mit diesem Fix behoben wurde.
Prembo
Es bleibt zwar eine gute Idee zu überprüfen, ob sich die Breite oder Höhe geändert hat, dies löst jedoch nicht das Szenario, in dem der resizeHandler kontinuierlich ausgelöst wird, obwohl Breite und Höhe gleich bleiben. In meinem Fall war es das documentObjekt, das den Handler auslöste und zu einer Endlosschleife führte.
WynandB
25

Dies ergab für mich einen Sinn und scheint in IE7 und höher zu funktionieren:

    //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();


        }
    });
Sabrina Leggett
quelle
19

Binden Sie Ihren Größenänderungs-Listener .one()so, dass er sich nach dem Brennen löst. Dann können Sie alles tun, was Sie wollen, solange Sie am Ende den Listener für die Größenänderung neu binden. Ich fand den einfachsten Weg, dies zu tun, indem ich den Größenänderungs-Listener in eine anonyme Funktion wie folgt versetzte:

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

    //resize things

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

Sie brauchen das technisch nicht setTimeoutumwickelt, resizeListener()aber ich habe es als Just-in-Case und für zusätzliche Drosselung hineingeworfen.

Brentonstrin
quelle
3
Hervorragende Lösung. Denken Sie daran , dass Funktionen sind vollwertige Objekte in JavaScript, so resizeListenerkann direkt übergeben werden , um setTimeout()stattdessen die Stringliteral verwenden "resizeListener();".
quietmint
Vielen Dank für diesen Tipp, @ user113215. Ich habe den Code basierend auf Ihrem Vorschlag aktualisiert.
Brentonstrine
Toller Ansatz ohne zusätzliche Variablen oder if-Anweisungen
Ergec
@brentonstrine Dies löste mein Problem $(window).resize(), an IE8 zu hängen. Klappt wunderbar. Vielen Dank!
Sithu
5

Ich habe es gelöst, indem ich die Größenänderungsfunktion aufgehoben, die Seite neu erstellt und dann die Größenänderungsfunktion erneut gebunden habe:

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

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

BEARBEITEN

Binden und Aufheben der Bindung passt nicht gut zu IE8. Obwohl Microsoft IE8 sogar aufgegeben hat, möchten Sie dies vielleicht versuchen (ungetestet!):

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

window.resizing=false;
document.body.onresize=rebuild;
Patrick
quelle
Dies schien die eleganteste Lösung zu sein, scheint aber leider nicht wirklich für mich zu funktionieren. Ich teste in IE 8 unter Windows XP und Chrome 36 unter OS X 10.9.
Sina
Ja, das Binden und Aufheben der Bindung von jQuery passt nicht gut zu IE8. Ich bezweifle, dass sie (jQuery) das Problem beheben werden, da selbst Microsoft IE8 / XP seit dem 8. April 2014 nicht mehr unterstützt ...
Patrick
1
Eine Problemumgehung könnte darin bestehen, zu Beginn der Funktionswiederherstellung einen globalen Parameter festzulegen, auf den Sie vor dem Ändern der Größe prüfen: function rebild () {if (window.resizing) return false; window.resizing = true; / * mach hier was * / window.resizing = false;); => bearbeitet die Antwort für die Lesbarkeit
Patrick
4

Die Antwort von @ AamirAfridi.com hat mein Problem gelöst.

Es ist eine gute Idee, eine gemeinsame Funktion zu schreiben, um solche Probleme zu lösen:

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();
        }
    });
}

Verwenden Sie es so, und Sie müssen sich keine Gedanken mehr über das unterschiedliche Verhalten im IE machen:

onWindowResize(function() {
    // do something
});
Dong
quelle
1
Überprüfen Sie besser den Rückruf mit setTimeout, um sicherzustellen, dass der Benutzer die Größe des Fensters geändert hat
Aamir Afridi
1

Ich bin heute auf dieses Problem gestoßen und habe beschlossen, Folgendes oben in meine globale Javascript-Datei aufzunehmen:

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;
});

Das erfordert übrigens Prototype.

Nick
quelle
1

Eine Mischung der unbind/ bind-Methode mit einem verzögerten Aufruf. Es funktioniert in Internet Explorer 8 und niedriger, verhindert böse Schleifen und hängt an den Versionen 6 und 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 );
Raohmaru
quelle
1

Sie können dies versuchen:

Konstrukteur:

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

Einige Funktionen:

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 ...
} 

Für Internet Explorer, Chrome, Firefox, Opera und Safari:

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

Für Internet Explorer 8, 7, 6, 5:

document.documentElement.clientHeight
document.documentElement.clientWidth
    or
document.body.clientHeight
document.body.clientWidth
1ubos
quelle
0
(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;
     });
})();

macht den Trick für mich ...

David Moldenhauer
quelle
0
<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++);
}

Ascis
quelle
0

So gehe ich damit um, herauszufinden, ob das Größenänderungsereignis von einem Element ausgelöst wurde oder das Fenster wirklich in der Größe geändert wurde:

Wenn der target.nodeType des Ereignisses nicht vorhanden ist, handelt es sich höchstwahrscheinlich um das Fenster, da jedes andere Element auf der Seite einen nodeType haben würde.

Hier ist also der Pseudocode (mit jQuery) mit der hinzugefügten Prüfung:

$(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
    }
});
zıəs uɐɟəʇs
quelle
-1

Ich konnte das Größenänderungsereignis nicht auslösen, wenn die Größe eines Elements geändert wurde (allerdings nur in IE8 versucht).

Was ist jedoch targetauf dem Ereignisobjekt, wenn dieses Problem auftritt?

$(window).resize(function(e) {
    if( e.target != window ) return;
    // your stuff here
});
DEfusion
quelle
2
Dies funktioniert nicht, da das Ziel in window.resize immer window ist, wenn ein Element die Datei window.resize auslöst. Aus diesem Grund beginne ich zu vermuten, dass dies tatsächlich nicht möglich ist ...
MissingLinq
-1

Mein Patch:

<!--[if lte IE 7]>
<script type="text/javascript">
  window.onresize = null;       // patch to prevent infinite loop in IE6 and IE7
</script>
<![endif]-->
MiKL
quelle
Ich würde niemals empfehlen, auf diese Weise mit Windows-Objekten herumzuspielen.
Aamir Afridi
-2

Es hängt davon ab, wie der Inhalt des Größenänderungsereignisses ist.

Ich habe die obigen Lösungen nur herausgefunden, wenn eine Seite aus statischen Inhalten besteht, nicht aus dynamisch gerenderten. In dem dynamischen Fall, in dem der vorhandene Inhalt durch ein Auslöseereignis wie eine Funktion zum erneuten Laden von Inhalten neu gerendert wird, müssen wir stattdessen $ (document) .width () oder $ (document) .height () verwenden.

Dies liegt an der Bildlaufleiste des Fensters. Wenn eine Seite über eine Bildlaufleiste verfügt und der Hauptinhalt durch Klicken auf die Schaltfläche „Neu laden“ neu gerendert wird, verschwindet die Bildlaufleiste beim Ereignis. In diesem Fall wird $ (Fenster) .width () oder $ (Fenster) .height () durch das Rendern des Inhalts geändert, nicht durch die tatsächliche Fenstergröße.

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

Yosuke Sato
quelle
-3
$(window).resize(function(event)
{
    if (typeof event.target.tagName == 'undefined')
    {
        // ...
    }
});
Enibeniraba
quelle
Was ist mit dieser Antwort, die die anderen hoch bewerteten Antworten hinzufügt / verbessert? Eine Nur-Code-Antwort ist nicht gut. Erklären Sie.
random_user_name