window.resize активація подій в Internet Explorer


76

Як вам відомо, в Internet Explorer подія window.resize запускається, коли будь-який елемент на сторінці змінюється. Немає значення, чи буде змінено розмір елемента сторінки шляхом присвоєння / зміни його атрибута висоти або стилю, шляхом простого додавання до нього дочірнього елемента або чого завгодно - навіть якщо розмір елемента не впливає на розміри самого вікна перегляду.

У моєму додатку це спричиняє неприємну рекурсію, оскільки в моєму обробнику window.resize я змінюю розмір деяких елементів <li>, що, у свою чергу, повторно запускає window.resize тощо. Знову ж, це лише проблема в IE.

Чи є спосіб запобігти запуску window.resize в IE у відповідь на елементи на сторінці, що змінюється?

Слід також зазначити, що я використовую jQuery.


2
Цікаво, я цього не знав. Я не знайомий з JQuery, але повинна бути можливість зупинити подію, якщо її вихідним елементом є не саме вікно. Я впевнений, що хтось придумає кодоване рішення.
Pekka

У якій версії IE це, і чи можете ви надати код, який фактично показує зміну розміру елемента, що запускає window.resize?
DEfusion

Про інші версії не слід, але це трапляється в IE 8
Коковалла

1
я не можу вам подякувати за це запитання. я постійно стягував волосся: "ЧОМУ МОЯ СТОРІНКА ТАКА ПОВІЛЬНА?" виявляється, ie8 продовжував стріляти window.resize на кожному кадрі, а потім моєму обробнику зміни розміру довелося б переміщати все знову і знову
user151496

Дякую за це. Може підтвердити, що це проблема і на IE9.
SAGExSDX

Відповіді:


60

Я щойно виявив ще одну проблему, яка може вам допомогти.

Я використовую jQuery, і у мене є подія window.resize для виклику функції, яка змінить позицію div, додану до тіла.

Тепер, коли я встановлюю властивість LEFT css для доданого div, подія window.resize отримує тригер для NO GOOD REASON.

Це призводить до нескінченного циклу, що запускає window.resize знову і знову.

Код без виправлення:

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

Рішення:

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

Отже, він в основному перевірятиме, чи змінюється висота чи ширина (що відбуватиметься ТІЛЬКИ тоді, коли ви фактично зміните розмір за допомогою вікна).


Аамір, схоже, це робить трюк. Дозвольте спробувати, і я повернусь і повідомлю вам, як це працювало.
MissingLinq

1
Дякуємо за ідею перевірити, чи не змінилася ширина / висота вікна, щоб побачити, чи насправді змінено розмір вікна чи ні!
Брайан Денні,

це onResize глобально спеціально або ви забули var?
Джетро Ларсон,

Чудове рішення - мала таку саму ситуацію з нескінченним циклом, яку виправили ці виправлення.
Прембо

Хоча залишається гарною ідеєю перевірити, чи не змінилася ширина чи висота, це не вирішує сценарій, при якому resizeобробник постійно запускається, навіть незважаючи на те, що ширина та висота залишаються однаковими. У моєму випадку це був documentоб’єкт, що спричинив спрацьовування обробника, що призвело до нескінченного циклу.
WynandB

25

це мало сенс для мене і, схоже, працює в IE7 і вище:

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


        }
    });

19

Зв’яжіть слухач зміни розміру, .one()щоб він відв’язав себе після спрацьовування. Тоді ви можете робити все, що завгодно, доки в кінці ви перев’яжете слухач зміни розміру. Я знайшов найпростіший спосіб зробити це, поставивши слухач зміни розміру в анонімну функцію приблизно так:

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

    //resize things

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

Вам технічно не потрібно setTimeoutобгортання навколо, resizeListener()але я кинув його туди як про всяк випадок і для додаткового регулювання.


3
Відмінне рішення. Пам'ятайте, що функції є повноцінними об'єктами в JavaScript, тому resizeListenerїх можна передавати безпосередньо setTimeout()замість використання рядкового літералу "resizeListener();".
тиха мента

Дякую за підказку, @ user113215. Я оновив код на основі вашої пропозиції.
brentonstrine

чудовий підхід без використання зайвих змінних чи операторів if
Ergec

@brentonstrine Це вирішило мою проблему $(window).resize()зависання на IE8. Працює як шарм. Дякую!
Сітху

5

Я вирішив це, розв’язавши функцію зміни розміру, відновивши сторінку, а потім знову прив’язавши функцію зміни розміру:

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

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

РЕДАГУВАТИ

Прив’язування та відв’язування погано поєднуються з IE8. Хоча Microsoft навіть відмовилася від IE8, ви можете спробувати це (неперевірене!):

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

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

Це здавалося найелегантнішим рішенням, але, на жаль, насправді це не працює для мене. Я тестую в IE 8 на Windows XP та Chrome 36 на OS X 10.9.
Сіна

Так, jQuery bind і unbind погано поєднуються з IE8. Я сумніваюся, що вони (jQuery) це виправлять, оскільки навіть Microsoft більше не підтримує IE8 / XP з 8 квітня 2014 року ...
patrick

1
Обхідним шляхом може бути встановлення глобального параметра на початку відновлення функції, який ви перевіряєте перед зміною розміру: function rebuild () {if (window.resizing) return false; window.resize = true; / * робити тут речі * / window.resizing = false;); => редагував відповідь щодо читабельності
patrick

4

Відповідь @ AamirAfridi.com вирішила мою проблему.

Це гарна ідея написати загальну функцію для вирішення таких питань:

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

Використовуйте його таким чином, і вам більше не доведеться турбуватися про різну поведінку в IE:

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

1
Краще перевірити використання зворотного виклику з setTimeout лише для того, щоб переконатися, що користувач закінчив змінювати розмір вікна
Aamir Afridi

1

Я зіткнувся з цією проблемою сьогодні і вирішив розмістити наступне у верхній частині мого глобального файлу JavaScript:

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

Для цього, до речі, потрібен прототип.


1

Поєднання методу unbind/ bindіз затримкою дзвінка. Він працює в Internet Explorer 8 і старіших версіях, запобігаючи злому циклу та зависанням версій 6 та 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 );

1

Ви можете спробувати це:

Конструктор:

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

Деякі функції:

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

Для Internet Explorer, Chrome, Firefox, Opera та Safari:

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

Для Internet Explorer 8, 7, 6, 5:

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

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

робить трюк для мене ...


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


0

Ось як я маю справу з з’ясуванням того, чи відбулася подія зміни розміру елементом або дійсно змінивши розмір вікна:

Якщо цільової події target.nodeType не існує, швидше за все це вікно, оскільки будь-який інший елемент на сторінці матиме nodeType.

Отже, ось псевдокод (з використанням jQuery) з доданою перевіркою:

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

-1

Я не зміг запустити подію зміни розміру, коли елемент змінив розмір (хоча це спробувалося лише в IE8).

Однак що таке targetоб’єкт події, коли ви стикаєтесь із цією проблемою, чи можете ви зробити це:

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

2
Це не працює, тому що коли елемент запускає window.resize, ціллю на window.resize завжди є window. Ось чому я починаю підозрювати, що цього насправді не можна зробити ...
MissingLinq

-1

Мій патч:

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

Я ніколи не рекомендував би возитися з такими об'єктами Windows.
Aamir Afridi

-2

Це залежить від того, яким буде вміст події зміни розміру.

Я з’ясував, що вищевказане вирішує лише тоді, коли сторінка складається зі статичного вмісту, а не динамічно відтворюваного. У динамічному випадку, коли наявний вміст буде повторно відтворений якоюсь подією тригера, як функція перезавантаження вмісту, нам потрібно використовувати замість цього $ (document) .width () або $ (document) .height ().

Це пов’язано з смугою прокрутки вікна. Якщо на сторінці є смуга прокрутки, а основний вміст буде відтворений повторно, натиснувши кнопку «Перезавантажити», смуга прокрутки зникає під час події. У цьому випадку $ (window) .width () або $ (window) .height () змінюється за допомогою візуалізації вмісту, а не за фактичним зміною розміру вікна.

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


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

Що щодо цієї відповіді додає / покращує інші високо оцінені відповіді? Відповідь лише на код - це не добре. Надайте пояснення.
random_user_name
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.