I've seen many check/uncheck all checkboxes scripts. But far most does not respect that if I toggled all checkboxes using the "checked all"-checkbox and then uncheck a single one in the list, the "checked all" checkbox is still checked.
Is there an elegant way of handling this case?
I've seen many check/uncheck all checkboxes scripts. But far most does not respect that if I toggled all checkboxes using the "checked all"-checkbox and then uncheck a single one in the list, the "checked all" checkbox is still checked.
Is there an elegant way of handling this case?
Share Improve this question asked Jan 26, 2011 at 13:26 janhartmannjanhartmann 15k17 gold badges87 silver badges140 bronze badges 5- 3 From a UI point of view you probably want a three state checkbox so you can show the some-on-some-off case as something else. But you have to fake these in HTML, or <5 at least. I've used a good implementation before but it's not one of the answers in that question - can't remember where though. The first example there can do this out of the box, although not in jQuery, and using separate images for each state rather than one + CSS. – Rup Commented Jan 26, 2011 at 13:35
- 2 Another alternative example: jsfiddle.net/Raynos/mSFts – Raynos Commented Jan 26, 2011 at 13:37
- @Raynos: Nice, but it doesn't check "check all" when manually checking all checkboxes. – ThiefMaster Commented Jan 26, 2011 at 13:39
- Never thought of three state checkbox. Intersting. :-) – janhartmann Commented Jan 26, 2011 at 13:39
- @ThiefMaster that wasn't requested. – Raynos Commented Jan 26, 2011 at 14:35
4 Answers
Reset to default 14$('#checkAll').click(function() {
if(this.checked) {
$('input:checkbox').attr('checked', true);
}
else {
$('input:checkbox').removeAttr('checked');
}
});
$('input:checkbox:not(#checkAll)').click(function() {
if(!this.checked) {
$('#checkAll').removeAttr('checked');
}
else {
var numChecked = $('input:checkbox:checked:not(#checkAll)').length;
var numTotal = $('input:checkbox:not(#checkAll)').length;
if(numTotal == numChecked) {
$('#checkAll').attr('checked', true);
}
}
});
Demo: http://jsfiddle.net/ThiefMaster/HuM4Q/
As pointed out in the question's comment, a regular checkbox is not perfect for this. My implementation disables the "check all" box as soon as one checkbox is unchecked. So, to uncheck all still-checked checkboxes you'll have to click twice (first to re-check the unchecked ones and then to uncheck all other ones). However, with a tri-state checkbox this might still be necessary as the state order might be unchecked->indefinite->checked->unchecked, so you'd need two clicks to come from indefinite to unchecked.
Since you probably don't want to check ALL checkboxes on your page with "Check All", replace input:checkbox
with e.g. .autoCheckBox
or input.autoCheckBox:checkbox
and give those checkboxes class="autoCheckBox"
.
If you want all checkboxes inside a certain form, simple use #idOfYourForm input:checkbox
or form[name=nameOfYourForm] input:checkbox
You can achieve this by attaching a click handler to each of the target checkboxes, and have that handler un-check the "control" checkbox based on the collective state of those target checkboxes. So, something like this:
// Control checks/unchecks targets
$('#controlcheckbox').click( function(){
$('.targetcheckboxes').attr('checked', this.checked );
});
// Targets affect control
$('.targetcheckboxes').click( function(){
if( $('.targetcheckboxes:not(:checked)').length ){
$('#controlcheckbox').attr('checked',false);
}
});
Even better -- you could attach this logic to an enclosing container element, and watch for the event using .delegate()
:
$('#some_container').delegate('.targetcheckboxes','click',function(){...} );
$("#selectall").click(function(){
var checked = $("#selectall").attr("checked");
$(".selectone").attr("checked",checked);
});
For setting select all
$(".selectone").click(function(){
var net = $(".selectone").map(function(){ return jQuery(this).attr("checked");}).get();
var flg = true;
if(jQuery.inArray(false, net)){
flg= false;
}
$("#selectall").attr("checked",flg);
});
Perhaps something like this:
$('tbody input:checkbox').change(function(){
if ($(this).closest('tbody').find('input:checkbox').not(':checked').length) {
$('#checkAll')[0].checked = false;
}
});
This assumes that #checkAll
is in the thead
section of your table.