Search code examples
jqueryonchangesiblingsparents

How not to uncheck parent's checkbox if one of the target checkbox's siblings is checked


How can I not to uncheck parent's checkbox if one of the target checkbox's siblings is checked?

Below is the code I modified from this answer.

$(document).ready(function() {
    $('input.liChild').change(function() {
        if ($(this).is(':checked')) {
            $(this).parents('ul').siblings('input:checkbox').attr('checked', true);
        }
        else
        {
            if($(this).parents('ul').siblings('input:checkbox').not(':checked')) 
                $(this).parents('ul').siblings('input:checkbox').attr('checked', false);
        }
    });
});

The idea is to check all parents' checkboxes no matter how deep the target checkbox is. Then uncheck all parents' checkboxes again if the target checkbox is unchecked.

My trouble is I dont want to uncheck parents' checkboxes if the target checkbox's sibling is checked.

Here is my jsfiddle.

EDIT:

I worked out my own solution, thanks guys for the help.

 $('input.liChild').change(function() {
        if ($(this).is(':checked')) {
            $(this).parents('ul').siblings('input:checkbox').attr('checked', true);
            //alert($(this).parents().siblings().find('input:checkbox:checked').length);
            //$(this).parents().siblings().css({background:'red'});
            //$(this).parent().children().css({background:'red'});
        }
        else
        {
            $(this).parent().children().find('input:checkbox:checked').attr('checked', false);

            if($(this).parents().siblings().find('input:checkbox:checked').length == 0) 
                $(this).parents('ul').siblings('input:checkbox').attr('checked', false);


        }
    });

Solution

  • A little something like this:

    $('input.liChild').change(function() {
        $(this).closest('ul')
               .siblings('input:checkbox')
               .prop('checked', $(this).closest('ul')
                                       .children()
                                       .children('input:checkbox')
                                       .is(':checked'))
               .first().change();
    });
    

    Demo: http://jsfiddle.net/D6wky/4/

    The changed checkbox's parent is found with:

    $(this).closest('ul').siblings('input:checkbox')
    

    ...and then the parent's checked property is set to the result of:

    $(this).closest('ul').children().children('input:checkbox').is(':checked')
    

    ...where .is(':checked') will return true if any of the elements in the jQuery object it is called on are checked.

    Then .change() is called on the parent so that the effect cascades upwards. (EDIT: I think you can omit the .first() from the above - at the time I thought I needed it, and it doesn't hurt so I'll leave it since I can't be bothered changing the demo to match.)