更改事件和IE8的jQuery问题

时间:2010-06-17 11:10:39

标签: asp.net jquery events

jQuery 1.4.2中存在一个错误,当使用DOM事件和jQuery事件时,select-element上的change事件会被触发两次,这只在IE7 / 8上发生。 这是测试代码:

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

更新: 问题的另一种观点,实际上这是我们的应用程序的真正问题。在一个甚至没有触及带有DOM事件的select元素的选择器上绑定实时更改事件也会导致双击。

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

实际错误的票证:http://dev.jquery.com/ticket/6593

这在我们的应用程序中给我们带来了很多麻烦,因为我们使用混合了jQuery的ASP.NET事件,并且一旦你在任何元素上挂起一个change事件,每个select(下拉列表)都会遇到这个双击问题。

在此问题得到解决之前,有没有人知道解决这个问题的方法?

5 个答案:

答案 0 :(得分:2)

我讨厌从死里复活这个问题,但是jquery最终修复了最近发布的1.7版本中的这个错误。

答案 1 :(得分:1)

我玩过这个bug并且似乎没有任何明显的解决方法。在我的测试中,我发现第二个更改事件是由jQuery触发的,所以我设法将一个快速解决方案组合在一起,该解决方案涉及删除DOM 0事件处理程序并将其再次应用于在线程完成时立即执行的计时器:

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

这在IE8中对我来说很好,只出现一个“你好”警告,虽然你可能想在那里添加一个IE检查。 或者不是,它可能没有区别它肯定需要检查,我已经将它添加到样本中。 Here's my fiddle

唯一的其他解决方案是删除DOM 0处理程序并仅使用jQuery处理程序。

答案 2 :(得分:1)

克隆控件并在预期后立即添加克隆并分配事件,然后删除控件:

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

答案 3 :(得分:0)

这样的事情?

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

 alert(0);
});

答案 4 :(得分:0)

我们实际上是以另一种方式解决问题,因为这是特定于IE,ASP.NET和select元素,我们使用以下代码:

$(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. 这样可确保修复程序仅应用于autopostback设置为true(onchange)一次的select元素。
  2. 基本上我们依靠jQuery来为我们激活更改事件,但是为了让IE这样做,我们需要在onpropertychange发生时触发元素模糊事件。