JSFiddle - React, Tailwind, and code Playground

by rolfsf

HTML

<ul id="theParentList">
    <li class="level-1">
        <div>Parent 1</div>
        <ul class="level-2">
            <li>
                <div>Child 1.1</div>
            </li>
            <li>
                <div>Child 1.2</div>
            </li>
        </ul>
    </li>
    <li class="level-1">
        <div>Parent 2</div>
        <ul class="level-2">
            <li>
                <div>Child 2.1</div>
            </li>
            <li>
                <div>Child 2.2</div>
            </li>
        </ul>
    </li>
</ul>

CSS

.level-1 {
    margin-left: .25em;
    margin-bottom: 1px;
}
.level-2 {
    margin-left: 1em;
}
.ui-selected {
    background: #0088cc;
    color: #FFF;
}
.ui-selecting {
    background: #FEFF9F;
}
ul {
    width: 25em;
}
li {
    display: block;
    font-size: .96em;
    line-height: 1.4em;
}
li div {
    margin-bottom: 1px;
    padding: 0 1em;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    -ms-border-radius: 3px;
    border-radius: 3px;
}
li.level-1 div:hover {
    cursor: pointer;
    background-color: #EEE;
}
li li:hover {
    cursor: pointer;
    background-color: #EEE;
}
li div.ui-selected:hover {
    cursor: pointer;
    background: #0088FF;
    color: #FFF;
}

JavaScript

$('#theParentList').selectable({
		    filter: 'li div',
		    selecting: function (event, ui) {
		        if ($(ui.selecting).parent().hasClass('level-1')) {
		            //this is a level-1 item, so select all of it's children
		            var ch = $(ui.selecting).parent().find('.level-2 .ui-selectee');
		            $(ch).not(".ui-selected").addClass("ui-selecting");
		        } else {
		            //this is a level-2 item, so check to see if all of it's siblings are also selected
		            var sibs = $(ui.selecting).parent().siblings().find('.ui-selectee');
		            var notSelected = 0;
		            for (var i = 0; i < sibs.length; i++) {
		                if ($(sibs[i]).hasClass('ui-selected') || $(sibs[i]).hasClass('ui-selecting')) {
		                    notSelected = notSelected
		                } else {
		                    notSelected = notSelected + 1;
		                }
		            }
		            if (notSelected === 0) { //all siblings are selected, so select their level-1 parent as well
		                $(ui.selecting).parent().parent().parent().find('>:first-child').not(".ui-selected").addClass("ui-selecting");
		            }
		            //otherwise, just select as usual
		        }
		    },
		    unselected: function (event, ui) {
		        if ($(ui.unselected).parent().hasClass('level-1')) {
		            //unselect all of it's children
		            $(ui.unselected).parent().children().each(function () {
		                $(this).find('.ui-selectee').removeClass('ui-selected').addClass('ui-unselected');
		            });
		        } else {
		            //this is a level-2 item, so we need to deselect its level-1 parent
		            $(ui.unselected).parents('li.level-1').find(">:first-child").removeClass('ui-selected');
		        }
		    }
		});