multiselect with callback
HTML
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css">
<div class="multiselect">
<ul id="ms-foobar" class="level-0 ui-selectable">
<li><div class="ui-selectee">All Foobars</div>
<ul class="level-1" data-ref="/data/b-search/sizes.json">
<li><div class="ui-selectee">Foobar 1</div></li>
<li><div class="ui-selectee">Foobar 2</div></li>
<li><div class="ui-selectee">Foobar 3</div></li>
<li><div class="ui-selectee">Foobar 4</div></li>
<li><div class="ui-selectee">Foobar 5</div></li>
</ul>
</li>
</ul>
</div>
<p id="selectedItems"></p>
CSS
.multiselect {font-size:.85em;background:#FFF;max-width:25em}
.multiselect .ms-hd {padding:0 .5em;min-height:3em;border:1px solid #EEE;margin-bottom:1px}
.multiselect .ms-hd label {display:inline-block;font-weight:bold;color:#333}
.multiselect .ms-bd {max-height:350px;overflow-y:auto;border:1px solid #EEE;padding:.25em .5em}
.multiselect ul{padding:0;margin:0}
.multiselect li{display:block;margin:0;padding:0;font-size:.96em;line-height:1.4em;background-color:#FFF;border-bottom:1px solid #EEE}
.multiselect li:last-child {border:none}
.multiselect li div {margin-bottom:1px;padding:0 16px;padding:0 1rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;border-radius:3px}
.multiselect .level-0 {margin-left:0;margin-bottom:1px}
.multiselect .ui-selected {background:#70961a;color:#FFF}
.multiselect .ui-selecting {background:#FEFF9F}
.multiselect li>div:hover {cursor:pointer;background-color:#EEE}
.multiselect li li>div:hover {cursor:pointer;background-color:#EEE}
.multiselect li>div.ui-selected:hover {cursor:pointer;background:#7bb2cc;color:#FFF}
.multiselect .level-1{margin-left:8px;margin-left:.5rem;margin-bottom:1px;border-top:1px solid #EEE}
.multiselect .level-2{margin-left:16px;margin-left:1rem;border-top:1px solid #EEE}
JavaScript
multiselect('#ms-foobar', doSomething);
var doSomething = function(stuff){
$('#selectedItems').empty().text(stuff);
//console.log(data);
};
function multiselect(ul, onSelect){
$(ul).selectable({
filter: 'li div',
selecting: function(event, ui){
if( $(ui.selecting).parent().parent().hasClass('level-0')){
//this is a level-0 item, so select all of it's children
var ch = $(ui.selecting).parent().parent().find('.level-1 .ui-selectee');
$(ch).not(".ui-selected").addClass("ui-selecting");
} else if( $(ui.selecting).parent().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");
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-0 parent as well
$(ui.selecting).parent().parent().parent().find('>:first-child').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') ){
...