Nested Check-Boxes

by xixonia

HTML

<div class="subtree">
    <input type="checkbox">Tree
    <ul>
        <li><input type="checkbox">Option 1</li>
        <li><input type="checkbox">Option 2</li>
        <li>
            <input type="checkbox">Sub Tree
            <ul>
                <li><input type="checkbox">Option 1</li>
                <li><input type="checkbox">Option 2</li>
            </ul>
        </li>
        <li>
            <input type="checkbox">Sub Tree
            <ul>
                <li><input type="checkbox">Option 1</li>
                <li><input type="checkbox">Option 2</li>
                <li>
                    <input type="checkbox">Sub Tree
                    <ul>
                        <li><input type="checkbox">Option 1</li>
                        <li><input type="checkbox">Option 2</li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>

CSS

input[type=checkbox]
{
    margin: 0px 5px 0px 0px;
}

li
{
    margin: 0px 0px 0px 10px;
}

span
{
    font-weight:bold;
    font-size:1.2em;
    padding: 3px 0px 0px 5px;
    display:block;
    background:lightblue;
}

ul
{
    margin: 5px;
    padding: 0px;
    border-left: 1px solid black;
}

JavaScript

$(function() {
    
    $(':checkbox').change(function() {
        
        // Find all the "sibling" check boxes
        var $siblings = $(this).closest('ul').children().children(':checkbox:not(:checked)');
        
        // Find the "parent" check box.
        var $parent = $(this)
            .closest('ul')
            .prev(':checkbox');
        
        // If the parent check box differs from the state we want it, change it and trigger a change
        if($parent[0].checked != ($siblings.length == 0))
        {
            $parent[0].checked = ($siblings.length == 0);
            $parent.change();
        }
    });
    
    $(':checkbox').click(function() {
        
        // When clicked, the checkbox should trickle it's value to the lower check boxes.
        var checked = this.checked;
        $(this).next('ul').find(':checkbox').each(function(){ this.checked = checked; });
        
    });
    
});