jQuery problem with change event and IE8
There is a bug in jQuery 1.4.2 that makes change event on select-element getting fired twice when using both DOM-event and a jQuery event, and this only on IE7/8. Here is the test code:
<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>
Update: Another view of the problem, actually this is the real problem we have with our application. Binding a live change event on a selector that isn't even touching the select-element with DOM-event also causes double firing.
<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 actual bug: http://dev.jquery.com/ticket/6593
This causes alot of trouble for us in our application cause we use both ASP.NET-events mixed with jQuery and once you hook up a change event on any element every开发者_如何学JAVA select (dropdown) gets this double firing problem.
Is there anyone who knows a way around this in the meantime until this issue is fixed?
I hate to raise this question from the dead but jquery finally fixed this bug in version 1.7 which was recently released.
I had a play around with the bug and there doesn't appear to be any obvious workaround. In my testing I found that the second change event is triggered by jQuery, so I managed to knock together a quick solution that involves removing the DOM 0 event handler and applying it again on a timer that executes immediately when the thread completes:
jQuery(".myDropDown").change(function() {
if ($.browser.msie) {
var dd = $(this)[0],
oc = dd.onchange;
dd.onchange = null;
window.setTimeout(function () {
dd.onchange = oc;
}, 0);
}
});
This works fine for me in IE8, just one "hello" alert appears, although you might want to add an IE check in there. Or not, it probably won't make a difference It definitely needs that check and I've added it to the sample. Here's my fiddle.
The only other solution would be to remove the DOM 0 handler and use the jQuery handler only.
Clone the control and add the clone immediately after the intended one and assign the event, then remove the control:
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
});
}
something like this?
jQuery(".myDropDown").removeAttr('onchange').change(function() {
alert(0);
});
We actually solve the problem another way, since this is specific to IE, ASP.NET and select element, we use the following code:
$(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(); };
});
});
}
});
- This make sure that the fix is only applied to the select element that has autopostback set to true (onchange) once.
- Basically we rely on jQuery to fire the change event for us, but in order for IE to do that, we need to trigger element blur event when onpropertychange happens.
精彩评论