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;
});
});
精彩评论