Событие Mootools вызывает бесконечный цикл в IE7/IE8

Мне трудно заставить это работать в IE7 (и IE8). Это ОЧЕНЬ сокращенная часть гораздо более сложного сценария. Так что имейте в виду, что методы и структура не могут измениться слишком сильно.

В IE7 я получаю бесконечный цикл при выборе одного из типов. В FF, Chrome и IE9 работает нормально. Он также отлично работал с библиотекой mootools 1.1 в IE7/IE8, но поскольку я преобразовал ее в Mootools 1.4, у меня возникла проблема с циклом.

Возможно, какое-то изменение делегирования событий в рамках. Я действительно не знаю. Любая помощь приветствуется!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <title>eventz</title>
    <script src="https://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed.js" type="text/javascript"></script>  

    <script type="text/javascript">
        var eventz = new Class({
            options: {      

            },  
            initialize: function(options) {
                this.setOptions(options);               
                this.setup();
                this.jx = 0;    

            },
            setup: function() {
                this.makeEvents();
                // ...
            },

            makeEvents : function() {
                alert("init");

                var finputs =   $$('.trig');

                finputs.removeEvents('change');
                finputs.removeEvents('click');

                finputs.each(function(r) {                  

                    $(r).addEvents({
                        'change': function(e) {                 
                            //e.preventDefault();
                            alert(r.name);                                          

                            new Event(e).stop();                                    
                            this.refresh(r);  // this needs to stay as refresh calls some ajax stuff            
                        }.bind(this)
                    });     
                }.bind(this)); 

                // ...
            },

            // refresh is called from various methods
            refresh : function(el) {    

                if(el) {
                    // count types checkboxes
                    var ob_checked = 0;
                    $$('.otypes').each(function(r) {
                        // uncheck all if clicked on "All"
                        if(el.id == 'typ-0') {
                            r.checked = false;
                        }
                        r.checked == true ? ob_checked++ : 0 ;
                    })

                    // check "All" if non selected
                    if(ob_checked == 0) {
                        $('typ-0').checked = true;
                    }
                    // uncheck "All" if some selected
                    if(el.id != 'typ-0' && ob_checked != 0) {
                        $('typ-0').checked = false;
                    }

                    // ajax call ...
                }
            }
        });
        eventz.implement(new Options);  

        window.addEvent('domready', function(){
            c = new eventz();
        });

    </script>

  </head>
  <body>
    <fieldset class="types">        
        <input type="checkbox" class="trig" name="otypes[]" value="0" id="typ-0" checked="checked">All
        <input id="typ-14" value="14" name="otypes[]" type="checkbox" class="otypes trig">Type A
        <input id="typ-17" value="17" name="otypes[]" type="checkbox" class="otypes trig">Type B
    </fieldset> 
  </body>
</html>

person Mike    schedule 16.04.2012    source источник


Ответы (1)


По сути, в MooTools 1.4.4+ события изменений были «нормализированы» в IE:

который отслеживает первоначальные коммиты и исправления.

Что касается вашего кода, необходимо внести некоторые изменения:

  1. new Event(e).stop(); необходимо переписать на: e.stop();
  2. Метод implements теперь является ключом-мутатором: Implements

Все можно сильно упростить. Вот пример рефакторинга, несколько оптимизированный для повышения производительности и с более четкой логикой.

http://jsfiddle.net/M2dFy/5/

что-то типа:

var eventz = new Class({
    options: {

    },

    Implements: [Options],

    initialize: function(options) {
        this.setOptions(options);
        this.setup();
        this.jx = 0;

    },
    setup: function() {
        this.makeEvents();
        // ...
    },

    makeEvents: function() {
        var finputs = $$('.trig');

        finputs.removeEvents('change');
        finputs.removeEvents('click');

        var self = this;
        this.type0 = $('typ-0');
        this.otypes = $$('.otypes');
        this.pause = false; // stop flag because of IE

        finputs.each(function(r) {

            r.addEvents({
                click: function(e) {
                    this.pause || self.refresh(r); // this needs to stay as refresh calls some ajax stuff            
                }
            });
        });

        // ...
    },

    // refresh is called from various methods
    refresh: function(el) {
        this.pause = true;
        if (el !== this.type0) {
            // count types checkboxes
            this.type0.set('checked', !this.otypes.some(function(other) {
                return !!other.get("checked");
            }));



            // ajax call ...
        }
        else {
            this.otypes.set('checked', false);
        }
        this.pause = false;
    }
});

теперь, с учетом кода, который у вас был, когда вы меняете .checked, он запускает propertychange, который попытается создать всплывающее окно события.

Я бы рекомендовал изменить весь доступ к checked с помощью методов .set и .get, например. el.set('checked', true); / el.get('checked') — аналогичное использование для id или любого другого свойства.

Надеюсь, этого достаточно, чтобы направить вас на правильный путь. Если вы создадите пример этого в jsfiddle с минимальным DOM, который работает, я буду рад просмотреть его еще раз.

У меня здесь нет IE (mac), но я подозреваю, что он может сломаться при нажатии на не все флажки, так как это сработает.

Я бы порекомендовал перейти к событиям кликов, хотя это сделает метки недействительными: http://jsfiddle.net/M2dFy/4/

person Dimitar Christoff    schedule 17.04.2012
comment
Спасибо за Ваш ответ! Я начну работать над этим позже. использование набора и получения доступа не запускает пузырь событий? - person Mike; 17.04.2012
comment
Я проверю это позже, спасибо. Весь код также использует поля ввода и поля выбора. Поэтому мне пришлось использовать оба события (щелчок и изменение), чтобы заставить его работать. - person Mike; 17.04.2012
comment
хм изменение будет раздражать. вы можете проверить event.type в функции и обойти тот факт, что это также может быть изменение свойства. проверьте это в обычном браузере по сравнению с ie7/8 - jsfiddle.net/8VMQs/1 - я собираюсь опубликовать это в проблемах mootools, но поскольку ibolmo отсутствует, не уверен, когда на это обратят внимание. - person Dimitar Christoff; 17.04.2012
comment
добавлена ​​ошибка на трекере - github.com/mootools/mootools-core/issues/2352 - хотя я не могу придумать, как отличить реальное событие от псевдопузырькового события, объекты события идентичны в ie и ff для изменения :( - person Dimitar Christoff; 17.04.2012
comment
Спасибо. Теперь я расширил пример текстовым полем и наблюдателем для него. Вы также можете увидеть оба события и то, что я сделал, чтобы заставить его работать. Не работает в jsfiddle, так что вот: pastebin.com/NKSdVEF6. Не уверен, что это правильный способ сделать это... - person Mike; 17.04.2012