I have a similar question to Uncheck parent node if all children unchecked in JQuery (with this solution) and have tried to modify it so that the children will also all uncheck if the parent is unchecked (which the above/below fails to do).
JSFiddle for the above (/)
jQuery.each(jQuery('#treeList ul li').find(':checkbox'), function(){
jQuery(this).change(function (){
if (jQuery(this).is(':checked')) {
jQuery(this).parentsUntil('#treeList').siblings().filter('input:checkbox').attr('checked', true).trigger('change');
}else{
jQuery(this).parents('ul:first').siblings('input:checkbox').prop('checked', $(this).parent().siblings().children('input:checked').length).trigger('change');
}
});
});
Though I'm not sure why, but I had to change prop
from the last line to attr
in order for it to correctly work as JSFiddle locally for some reason...
Basically I have a 3 level setup:
Grand-Parent
- Parent
-- Child
- If the
grandparent
is checked/unchecked, then its children and grandchildren should all be checked/unchecked too. - If the
parent
is checked/unchecked, its children should be checked/unchecked as well as its parent. - If the
children
are checked, then its parent and grandparent should be checked (if no children are checked then parent shouldn't be checked).
I'm trying to change this to Continent, Country, Region - I think you will understand if I were to just say this....
Thanks
I have a similar question to Uncheck parent node if all children unchecked in JQuery (with this solution) and have tried to modify it so that the children will also all uncheck if the parent is unchecked (which the above/below fails to do).
JSFiddle for the above (http://jsfiddle/fRxVs/)
jQuery.each(jQuery('#treeList ul li').find(':checkbox'), function(){
jQuery(this).change(function (){
if (jQuery(this).is(':checked')) {
jQuery(this).parentsUntil('#treeList').siblings().filter('input:checkbox').attr('checked', true).trigger('change');
}else{
jQuery(this).parents('ul:first').siblings('input:checkbox').prop('checked', $(this).parent().siblings().children('input:checked').length).trigger('change');
}
});
});
Though I'm not sure why, but I had to change prop
from the last line to attr
in order for it to correctly work as JSFiddle locally for some reason...
Basically I have a 3 level setup:
Grand-Parent
- Parent
-- Child
- If the
grandparent
is checked/unchecked, then its children and grandchildren should all be checked/unchecked too. - If the
parent
is checked/unchecked, its children should be checked/unchecked as well as its parent. - If the
children
are checked, then its parent and grandparent should be checked (if no children are checked then parent shouldn't be checked).
I'm trying to change this to Continent, Country, Region - I think you will understand if I were to just say this....
Thanks
Share Improve this question edited May 23, 2017 at 11:58 CommunityBot 11 silver badge asked Oct 31, 2011 at 14:26 MrJMrJ 1,9382 gold badges17 silver badges30 bronze badges 4- Have a look at this question on Code Review codereview.stackexchange./questions/4939/… – John Hartsock Commented Oct 31, 2011 at 14:35
- Just took a look at that, and tried the JSFiddle for it - but that only makes the child's parent check if both (I imagine it ends up being all) children have been checked - I'd like it so that just one child feeds up the tree. – MrJ Commented Oct 31, 2011 at 14:38
- I'm having a look at it. I've just optimized the code, moving onwards to fixing it ;) – Rob W Commented Oct 31, 2011 at 14:41
- Thanks @RobW! Look forward to seeing your solution, hope I can increase my understanding of jQuery through it :) – MrJ Commented Oct 31, 2011 at 14:43
2 Answers
Reset to default 6Here's the solution: Fiddle: http://jsfiddle/fRxVs/55/
$('#treeList :checkbox').change(function (){
$(this).siblings('ul').find(':checkbox').prop('checked', this.checked);
if (this.checked) {
$(this).parentsUntil('#treeList', 'ul').siblings(':checkbox').prop('checked', true);
} else {
$(this).parentsUntil('#treeList', 'ul').each(function(){
var $this = $(this);
var childSelected = $this.find(':checkbox:checked').length;
if (!childSelected) {
$this.prev(':checkbox').prop('checked', false);
}
});
}
});
Modifications and explanations
$
is exactely the same asjQuery
. Be consistent when using it:jQuery
should only be used when you're not sure whether$ === jQuery
(is$
overwritten?).:checkbox
is a selector which matches everyinput[type="checkbox"]
. It's obsolete to specifyinput:checbkox
, since a checkbox element is always an input element..find(..)
seeks for any element which is a child (not necessery the direct child) of the matched selector."#treeList :checkbox"
is faster, and has the equivalent result as$('#treeList').find(':checkbox')
.- When a property/method/event is added to a jQuery object, all elements which match the selector will be modified. Therefore, you don't have to loop through each element individually:
jQuery.each(jQuery('#treeList :checkbox'), function(){ jQuery(this).change(...)})
can be shortened tojQuery('#treeList :checkbox').change(...)
. - You don't have to trigger
change
after changing a checkbox check state, because the function already takes care of the full tree.
Old question but you could just do it like this:
$('input[type=checkbox]').change(function(){
$(this).next().find('input[type=checkbox]').prop('checked', this.checked);
$(this).parents('ul').prev('input[type=checkbox]').prop('checked', function(){
return $(this).next().find(':checked').length;
});
});
Fiddle: http://jsfiddle/ojc1qg1f/