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');
}
}
});