jquery tree traversal
I have a task where I need to traverse a tree (checking/un-checking individual items). I've written the code and it works correctly but slow at times. Please help me improve it.
Here is how it is suppose to work:
- Un-checking the parent unchecks all children of that parent
- Un-checking the (one or more) child nodes un-checks the parent
- Checking the parent automatically checks all it's children
- When all children are checked the
parent gets checked as well
automatically
- this should also work with any depth tree..so if there are 3 level deep nodes unchecking the most inner child will uncheck the First parent of each node.
Few other considerations: Css classes:
- "checked" - black color font, when removed font is gray
- "marked" - gray background
So:
- When the parent has NO children selected, it's css class "checked" is removed (it becomes gray)
- When an item is un-checked it's css classes "checked" and "marked" are removed (black font becomes gray and without gray background)
- When ALL children are un-checked the parent's "marked" class is removed (gray background is removed).
I hope this illustration will help:

And part of HTML source code:
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:30px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Aparatura elektryczna, elektroenergetyka </span></div>
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:60px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Silniki, napędy, automatyka napędów </span></div>
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:90px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Silniki i napędy przemysłowe </span></div>
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Prądu stałego </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Prądu przemiennego </span></div>
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:150px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>synchroniczne </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:150px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>asynchroniczne </span></div>
</li></ul></li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Silniki krokowe </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Siłowniki elektryczne </span></div>
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:150px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Liniowe </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:150px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Obrotowe </span></div>
</li></ul></li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Serwosilniki, serwonapędy </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Inne </span></div>
</li></ul></li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:90px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Układy zabezpieczeń silników </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:90px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Elektroniczne układy sterowania napędów </span></div>
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Przemienniki prądu stałego </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Przemienniki częstotliwości (falowniki) </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Układy łagodnego rozruchu (softstarty) </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Sterowniki silników DC </span></div>
</li><li class='open'> 开发者_Go百科 <div class="tlWrap clearfix marked checked" style="padding-left:120px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Sterowniki silników krokowych </span></div>
<ul class='treeList2b'><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:150px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Jednoosiowe </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:150px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Wieloosiowe </span></div>
</li><li class='open'> <div class="tlWrap clearfix marked checked" style="padding-left:150px;"><input type="checkbox" checked="checked" class="checkbox" name="SelectedBranch" id="SelectedBranch"><span>Wieloosiowe z interpolacją </span></div>
</li></ul></li>
...
And my script:
<script type="text/javascript">
/*<![CDATA[*/
$(function(){
$('ul.treeList2b .checkbox').click(function(e){
e.stopPropagation();
var obj = $(this).closest('li').find(':checkbox');
obj.attr('checked', this.checked);
var childCnt=obj.size(); // get childrent count - when parent was clicked
var checkedCnt=obj.filter(':checked').length; // out of those get those that are checked
if (childCnt==checkedCnt){
obj.parents('li').each(function (index, element) {
var objSub = $(element).find('li');
childCnt = objSub.size();
checkedCnt = objSub.find(':checkbox:checked').length;
if (childCnt==checkedCnt) {
$(element).find(':checkbox:first').attr("checked", true);
$(element).children('div.tlWrap').addClass('checked');
}
$(element).children('div.tlWrap').addClass('marked');
});
}else{
var objParent = obj.parents('li').find(':checkbox:first');
objParent.attr("checked", false);
objParent.parent('div.tlWrap').removeClass('checked');
}
refleshCheckbox(this);
});
});
function refleshCheckbox(obj){
if(!$(obj).attr('checked')){
$(obj).closest('li').find('div.tlWrap').removeClass('marked');
}
if ($(obj).closest('ul').find(':checkbox:checked').length==0){
$(obj).closest('ul').parent().find('div.tlWrap').removeClass('marked');
}
}
/*]]>*/
</script>
I won't be adding all the functionality to this answer since you'll learn more by implementing them yourself. But I made a test case on jsFiddle that works as illustrated:
$(".option-tree > li > label > input:checkbox").each(function(){
var $this = $(this),
options = $this.closest("li").find("> ul > li > label > input:checkbox");
$this.change(function(){
options.prop("checked", $this[0].checked);
});
options.change(function(){
var all = options.length,
checked = options.filter(":checked").length;
$this[0].checked = all === checked;
});
});
Note that the above example is using jQuery 1.6 where you have to use .prop instead of .attr and .removeAttr.
For earlier versions of jQuery (pre 1.6) it would look like this:
$(".option-tree > li > label > input:checkbox").each(function(){
var $this = $(this),
options = $this.closest("li").find("> ul > li > label > input:checkbox");
$this.change(function(){
if ($this[0].checked) {
options.attr("checked", "checked");
} else {
options.removeAttr("checked");
}
});
options.change(function(){
var all = options.length,
checked = options.filter(":checked").length;
$this[0].checked = all === checked;
});
});
加载中,请稍侯......
精彩评论