2010-06-17 18 views
5

W jQuery 1.4.2 występuje błąd, który powoduje, że zdarzenie change na elemencie select jest uruchamiane dwukrotnie podczas używania zdarzenia DOM i zdarzenia jQuery, a to tylko w IE7/8. Oto kod testu:Problem jQuery ze zdarzeniem change i IE8

<html> 

<head> 
    <script src="http://code.jquery.com/jquery-1.4.2.js" type="text/javascript"></script> 

    <script type="text/javascript"> 

     jQuery(document).ready(function() { 

     jQuery(".myDropDown").change(function() { 


     }); 

     }); 

    </script> 

</head> 

<body> 
    <select class="myDropDown" onchange="alert('hello');"> 
      <option>1</option> 
      <option>2</option> 
      <option>3</option> 
      <option>4</option> 
     </select> 
</body> 

</html> 

Aktualizacja: Inny widok problemu, faktycznie jest to prawdziwy problem mamy z naszej aplikacji. Wiązanie zdarzenia zmiany na żywo z selektorem, który nawet nie dotyka elementu select z zdarzeniem DOM, powoduje również podwójne strzelanie.

<html> 

<head> 
    <script src="http://code.jquery.com/jquery-1.4.2.js" type="text/javascript"></script> 

    <script type="text/javascript"> 

     jQuery(document).ready(function() { 

     jQuery(".someSelectThatDoesNotExist").live("change", function() { 


     }); 

     }); 

    </script> 

</head> 

<body> 
    <select class="myDropDown" onchange="alert('hello');"> 
      <option>1</option> 
      <option>2</option> 
      <option>3</option> 
      <option>4</option> 
     </select> 
</body> 

</html> 

Ticket to rzeczywisty błąd: http://dev.jquery.com/ticket/6593

To powoduje wiele kłopotów dla nas w naszej aplikacji przyczyny używamy zarówno asp.net-wydarzenia zmieszane z jQuery i po zahaczyć zdarzenie zmiany na każdym elemencie każde zaznaczenie (rozwijane) powoduje ten podwójny problem zwalniania.

Czy istnieje ktoś, kto zna sposób rozwiązania tego problemu w międzyczasie, dopóki ten problem nie zostanie rozwiązany?

+0

Czy trzeba zdarzenie propagować? –

+0

Niestety, jeśli potrzebujesz zachowania propagacji, itp. ... Nie sądzę, że jest to możliwe, jest to błąd 1.4.2 core/IE8, który będzie wymagał dodatkowego sprawdzenia w jQuery do naprawienia. –

+0

@Nick: Co rozumiesz przez propagowanie? Chcę, aby działał tak jak inne przeglądarki, a wydarzenie jest uruchamiane tylko raz. – Marcus

Odpowiedz

2

Nienawidzę podnosić tego pytania z martwych, ale jquery w końcu naprawił ten błąd w wersji 1.7, która została niedawno wydana.

+0

Fajnie, dziękuję. Wtedy masz szczęście, że dostaniesz odpowiedź sprawdzoną :) – Marcus

0

coś takiego?

jQuery(".myDropDown").removeAttr('onchange').change(function() { 

alert(0); 
}); 
+0

Wtedy to by się nie wystrzeliło :) –

+0

ahhh ... hmmm ... czy możesz mi powiedzieć dlaczego to taki nick? ....;) Cóż, nie próbowałem tego .. – Reigel

+0

Pewnie :) Oto wersja demonstracyjna, możesz wypróbować swój kod: http://jsfiddle.net/jfjBH/ Handler 'onchange' to to, co dwa razy wystrzeliwujesz, jeśli go usuniesz, nie będzie strzelania. Obecny błąd to 2 ostrzeżenia w IE8. Zasadniczo nie traktuj atrybutów jako zdarzeń (nawet jeśli są * zadeklarowane * w ten sposób), nie są * naprawdę * powiązane i działa tylko w IE IIRC. –

1

Miałem zabawy z błędem i nie wydaje się być oczywiste obejścia. Podczas moich testów odkryłem, że drugie zdarzenie zmiany jest wywoływane przez jQuery, więc udało mi się zlikwidować szybkie rozwiązanie, które obejmuje usunięcie obsługi zdarzenia DOM 0 i ponowne zastosowanie go w zegarze, który jest wykonywany natychmiast po zakończeniu wątku:

 jQuery(".myDropDown").change(function() { 
     if ($.browser.msie) { 
      var dd = $(this)[0], 
       oc = dd.onchange; 
      dd.onchange = null; 
      window.setTimeout(function() { 
       dd.onchange = oc; 
      }, 0); 
      } 
    }); 

Działa to dobrze dla mnie w IE8, pojawia się tylko jeden alert "cześć", chociaż możesz chcieć dodać tam kontrolę IE. Czy nie, prawdopodobnie nie będzie to miało żadnego znaczenia Zdecydowanie potrzebuje tego czeku i dodałem go do próbki. Here's my fiddle.

Jedynym innym rozwiązaniem byłoby usunięcie obsługi DOM 0 i użycie tylko obsługi jQuery.

0

My rzeczywiście rozwiązać problem inny sposób, ponieważ jest to specyficzne dla IE, ASP.NET i wybierz elementu, używamy następującego kodu:

$(function() { 
if ($.browser.msie) { 
    var prm = Sys.WebForms.PageRequestManager.getInstance(); 
    prm.add_pageLoaded(function() { 
     $('select[onchange]:not(.iefixed)') 
      .addClass('iefixed') 
      .each(function() { 
       var self = $(this), dd = self[0], action = self.attr('onchange'); 
       self.removeAttr('onchange').change(action); 
       dd.onpropertychange = function() { dd.blur(); }; 
      }); 
    }); 
} 
}); 
  1. to upewnić się, że poprawka jest stosowana tylko do elementu select, który ma autopostback ustawiony na true (onchange) jeden raz.
  2. Zasadniczo polegamy na jQuery, aby wystrzelić dla nas zmianę, ale aby IE to zrobił, musimy wywołać zdarzenie rozmycia elementu, gdy nastąpi zdarzenie.
1

Clone kontroli i natychmiast dodać klona po planowanej jednej i przypisać zdarzenie, a następnie wyjąć sterowania:

if ($.browser.msie && (parseInt($.browser.version, 10) == 8 || parseInt($.browser.version, 10) == 7)) { 
    var btn2 = $(btn).clone(); 
    $(btn).after(btn2); 
    $(btn).remove(); 
    $(btn2).bind("click", function() { 
     //your function here 
    }); 
} 
Powiązane problemy