JSFiddle - React, Tailwind, and code Playground

by Akram kamal

HTML

<form>
    <input type="checkbox" name="parent" id="parent" data-children="#child1, #child2, #child3" /><label for="parent">Parent</label>
    <ul>
        <li>
            <input type="checkbox" name="child1" id="child1" />
            <label for="child1">Child 1</label>
        </li>
        <li>
            <input type="checkbox" name="child2" id="child2" data-children="#child2sub1, #child2sub2" />
            <label for="child2">Child 2</label><ul>
                        <li><input type="checkbox" name="child2sub1" id="child2sub1" /><label for="child2sub1">Child 2 SubChild 1</label></li>
                        <li><input type="checkbox" name="child2sub2" id="child2sub2" /><label for="child2sub2">Child 2 SubChild2</label></li>
                    </ul>
        </li>
        <li>
            <input type="checkbox" name="child3" id="child3" data-children="#child3sub1, #child3sub2" />
            <label for="child3">Child 3</label>
            <ul>
                <li>
                    <input type="checkbox" name="child3sub1" id="child3sub1" />
                    <label for="child3sub1">Child 3 SubChild 1</label>
                </li>
                <li>
                    <input type="checkbox" name="child3sub2" id="child3sub2" data-children="#child3sub2sub1, #child3sub2sub2" />
                    <label for="child3sub2">Child 3 SubChild 2</label>
                    <ul>
                        <li><input type="checkbox" name="child3sub2sub1" id="child3sub2sub1" /><label for="child3sub2sub1">Child 3 SubChild 2 SubChild 1</label></li>
                        <li><input type="checkbox" name="child3sub2sub2" id="child3sub2sub2" /><label for="child3sub2sub2">Child 3 SubChild 2 SubChild 2</label></li>
                    </ul>
                </li>
            </ul>
            
        </li>
    </ul>
    
    <input type="checkbox" name="parent2" id="parent2" data-children="#p2child1, #p2child2" /><label for="parent2">Parent</label>
    <ul>
        <li>
...

JavaScript

(function($) {
    $('input[type=checkbox][data-children]').unbind("change childchange childchangebubble").each(function() {
        var parent = $(this);

        var linkedChildren = $(parent.data("children"));

        //trigger a "childChange" event on the parent when any child is triggered.
        linkedChildren.bind("change childchangebubble", function() {
            parent.trigger("childchange");
        });

        parent.bind({
            "change": function(event) { // Bind change event to check all children
                linkedChildren.prop("checked", parent.prop("checked")).trigger("change");
            },
            "childchange": function() { // have to bind custom event seperately, there seems to be a jQuery bug.
                // When a child is changed recalculate if parent should be checked
                var noChildrenUnchecked = !linkedChildren.is(":not(:checked)");
                parent.prop("checked", noChildrenUnchecked).trigger("childchangebubble");
            }
        });
    });
})(jQuery);