I have some hierarchical data I am manipulating with JQuery, and I am trying to add some type of visual indication about which elements in my tree are selected. Here is a sample of the html I am generating (which we are manipulating):
<li>
<input class="selectedcheck" checked disabled type="checkbox" name="ign-130">
<input class="millermultiselect" type="checkbox" name="chk-130">
<a href="#" data-parent="6" data-nodename="Egypt" data-self="130">Egypt</a>
<ul>
<li>
<input class="selectedcheck" checked disabled type="checkbox" name="ign-131">
<input class="millermultiselect" type="checkbox" name="chk-131">
<a href="#" data-parent="130" data-nodename="Cairo" data-self="131">Cairo</a>
</li>
</ul>
</li>
All of this resides within a div#miller. The first check box (.selectedcheck), is used only to show that a region is selected (it starts out hidden, and is shown when the parent region is selected, so if you clicked the .millermultiselect in Egypt, the .selectedcheck in Cairo would become visible replacing Cairo’s .millermultiselect). What I would like to do is also add a class to any li which contains (as a direct child) a checked check box. I am attempting to accomplish this with the following JQuery code:
$("#miller li:has(input:checkbox:checked:visible)").addClass('chosen');
The problem that I am having is that since all of the regions are composed of nested ul’s, checking a check box in any region also adds .chosen to any li higher in the tree… so clicking the check box for Cairo adds the .chosen class to Egypt and Africa.
Anyone have an idea how I would go about only capturing li’s that have a visible, checked check box as a direct child?
Here is my whole js file just in case it provides insight:
$(document).ready(function() {
$(".selectedcheck").hide();
showSelected = function(){
$("#miller li").removeClass("chosen");
$("#miller li:has(input:checkbox:checked:visible)").addClass('chosen');
};
$("#miller a").click(function(event) {
event.preventDefault();
$("#miller li").removeClass("selected");
$(this).parent().addClass("selected");
data = $(this).data();
$("#addChild").attr("href", "addChild.php?parentid=" + data.self).html("Add item under " + data.nodename);
$("#addSibling").attr("href", "addChild.php?parentid=" + data.parent).html("Add item next to " + data.nodename);
$("#editRegion").attr("href", "editRegion.php?id=" + data.self).html("Edit " + data.nodename);
$("#deleteRegion").attr("href", "deleteRegion.php?id=" + data.self).html("Delete " + data.nodename);
$("#addResort").attr("href", "addResort.php?regionid=" + data.self).html("Add resort to " + data.nodename);
$("#miller ul ul").hide();
$(this).parents("#miller ul").show();
$(this).siblings("#miller ul").show();
showSelected();
});
$("#miller .millermultiselect").click(function(event) {
$("#miller li").removeClass("selected");
$(this).parent().addClass("selected");
$("#miller ul ul").hide();
$(this).parents("#miller ul").show();
if($(this).is(':checked')) {
$(this).parent().find(".millermultiselect").not(this).hide();
$(this).parent().find(".millermultiselect").not(this).removeAttr("checked");
$(this).parent().find(".selectedcheck").show();
} else {
$(this).parent().find(".millermultiselect").not(this).show();
$(this).parent().find(".selectedcheck").hide();
}
$(this).siblings(".selectedcheck").hide();
$(this).siblings("#miller ul").show();
showSelected();
});
});
You can use the direct descendant selector and then get it’s parent: