开发者

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:

  1. Un-checking the parent unchecks all children of that parent
  2. Un-checking the (one or more) child nodes un-checks the parent
  3. Checking the parent automatically checks all it's children
  4. 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:

jquery tree traversal

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&#243;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&#243;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&#243;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&#243;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&#243;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;
    });

});
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜