jQuery/Javascript: Click event on a checkbox and the 'checked' attribute
The code:
$('input.media-checkbox').live('click', function(e){
e.preventDefault();
var that = $(this);
if (that.attr('checked') == 'checked'){
var m = that.attr('media');
var mid = 'verify_' + m;
that.parents('div.state-container').find('ul.' + mid).remove();
that.attr('checked', false);
} else {
var url = AJAX_URL;
$.ajax({
type: 'GET',
url: url,
dataType: 'html',
success: function(data){
that.parents('li').siblings('li.verification').children('div.media-verification').append(data).fadeIn(500);
that.attr('checked', 'checked');
}
});
}
return false;
});
I am ajaxing in a form, then firing the click event on relevant checkboxes to ajax in another partial if necessary. The form is inserted nicely, and the click events are fired, checking the boxes that need to be checked and firing the second ajax, since the checked
attribute of the checkbox was initially 开发者_如何学Pythonfalse
.
What's curdling my cheese is if I UNCHECK one of those boxes. Despite e.preventDefault()
, the checked
attribute is set to false
BEFORE the test, so the if
statement always executes the else
statement. I've also tried this with $.is(':checked')
, so I'm completely baffled.
It appears that unchecked -> checked state reads the original state, but checked -> unchecked doesn't. Any help?
B.E., I know it has been a year but I think I found the solution,
The issue here is that the click event actually get's called and runs BEFORE the "checked" property is added to the checkbox input. So the function runs, looks to see if the input has the "checked" attribute, and runs the else condition. THEN the element is given the "checked" property.
I just ran into this as well, and my solution was to bind the function to the change function rather than the click function, as change only fires AFTER the checked property has been updated on the input.
Hopefully this help you, and if not, anyone else who happens to stumble upon this post while experiencing a similar issue.
Well, right. You have set the live
event, so I think your script might also be responding to setting it as checked, but I can't totally tell what you're trying for here without seeing markup, but here's my rewrite.
$('input.media-checkbox').live('click', function(e){
if ($(this).is(':checked')) {
var m = $(this).attr('media');
var mid = 'verify_' + m;
$(this).parents('div.state-container')
.find('ul.' + mid)
.remove();
$(this).attr('checked', false);
} else {
var url = AJAX_URL;
var that = this;
$.ajax({
type: 'GET',
url: url,
dataType: 'html',
success: function(data) {
$(that).parents('li')
.siblings('li.verification')
.children('div.media-verification')
.append(data)
.fadeIn(500);
$(that).attr('checked', true);
}
});
}
return false;
});
Try using e.stopPropagation()
instead of e.preventDefault()
and also remove return false
. Returning false
in jQuery is equivalent to e.stopPropagation()
+ e.preventDefault()
. e.preventDefault()
prevents the checkbox from being checked
.
It seems to be a due to asynchronous requests. The execution goes past $.ajax
, before it's success callback fires. When you click the checkbox again, it's state has not yet been updated by the previous request's callback. What you can try is to disable the checkbox control prior to firing the ajax call, and enable it again within the success callback:
that.attr("disabled", "disabled");
var url = AJAX_URL;
$.ajax({
type: 'GET',
url: url,
dataType: 'html',
success: function(data){
that.parents('li').siblings('li.verification').children('div.media-verification').append(data).fadeIn(500);
that.attr('checked', 'checked');
that.removeAttr('disabled');
}
});
That will ensure that two successive clicks will not lead to unpredictable behaviour. The other way would be to use a synchronous request, i.e. async: false
but that will block the entire browser for it's duration.
I think it's due to a weird bug in IE. Check/set attribute defaultChecked along with checked. Try this in your if condition,
if (that.attr('checked')=='checked' || that.attr("defaultChecked")=='checked'){
var m = that.attr('media');
var mid = 'verify_' + m;
that.parents('div.state-container').find('ul.' + mid).remove();
that.attr('checked', false);
that.attr('defaultChecked', false);
} else {
This is probably only a partial answer, but in your test, $(this).attr('checked')
should return true
if checked and false
if not. So just change your conditional to if (that.attr('checked'))
精彩评论