0

I'm trying to implement a cascade check on a nested list with checkboxes.

I'm using this answer from ᾠῗᵲᄐᶌ as a guide.

I'm having trouble dealing with the check/uncheck of the parents of a given node. I can check all parents but uncheck only fist one and I can't figure out what I'm doing wrong.

HTML

<ul>
    <li>
        <a href="#">
            <input type="checkbox"><span>NODE A</span>
        </a>
        <ul>
            <li>
                <a href="#">
                    <input type="checkbox"><span>NODE A1</span>
                </a>
                <ul></ul>
            </li>
            <li>
                <a href="#">
                    <input type="checkbox"><span>NODE A2</span>
                </a>
                <ul></ul>
            </li>
            <li>
                <a href="#">
                    <input type="checkbox"><span>NODE A3</span>
                </a>
                <ul>
                    <li>
                        <a href="#">
                            <input type="checkbox"><span>NODE A3a</span>
                        </a>
                        <ul></ul>
                    </li>
                    <li>
                        <a href="#">
                            <input type="checkbox"><span>NODE A3b</span>
                        </a>
                        <ul>
                            <li>
                                <a href="#">
                                    <input type="checkbox"><span>NODE A3b1</span>
                                </a>
                                <ul></ul>
                            </li>
                            <li>
                                <a href="#">
                                    <input type="checkbox"><span>NODE A3b2</span>
                                </a>
                                <ul></ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
    <li>
        <a href="#">
            <input type="checkbox"><span>NODE B</span>
        </a>
        <ul></ul>
    </li>
    <li>
        <a href="#">
            <input type="checkbox"><span>NODE C</span>
        </a>
        <ul>
            <li>
                <a href="#">
                    <input type="checkbox"><span>NODE C1</span>
                </a>
                <ul></ul>
            </li>
            <li>
                <a href="#">
                    <input type="checkbox"><span>NODE C2</span>
                </a>
                <ul>
                    <li>
                        <a href="#">
                            <input type="checkbox"><span>NODE C2a</span>
                        </a>
                        <ul></ul>
                    </li>
                    <li>
                        <a href="#">
                            <input type="checkbox"><span>NODE C2b</span>
                        </a>
                        <ul></ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

JS

$("input:checkbox").click(function()
{
    var isChecked = $(this).is(":checked");

    //down
    $(this).parent().next().find("input:checkbox").prop("checked", isChecked);

    //up
    $(this).parents("ul").prev("a").find("input:checkbox").prop("checked", function()
    {
        return $(this).parent("a").next("ul").find(":checked").length;
    });
});

FIDDLE: https://jsfiddle.net/h8hzj01q/

Community
  • 1
  • 1
Matías Cánepa
  • 5,770
  • 4
  • 57
  • 97

1 Answers1

1

The problem was that the statement $(this).parents("ul").prev("a").find("input:checkbox") traverses the dom from top to bottom, i.e. from topmost ul to the lowest. You need this in reverse, to make all the parent checkboxes unchecked.
Reversing the jquery object obtained from $(this).parents("ul").prev("a").find("input:checkbox") and using each loop, the desired result is obtained.

The example that you included worked as it uses prev which traverses bottom to top, while you're using find that traverses from top to bottom

Changed your code to work like this:

jQuery.fn.reverse = [].reverse;
$("input:checkbox").click(function()
{
 var isChecked = $(this).is(":checked");
 
 //down
 $(this).parent().next().find("input:checkbox").prop("checked", isChecked);

 //up
  $(this).parents("ul").prev("a").find("input:checkbox").reverse().each(function(a, b) {
   $(b).prop("checked", function()
    {
      return $(b).parent("a").next("ul").find(":checked").length;
    });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
                <li>
                    <a href="#">
                        <input type="checkbox"><span>NODE A</span>
                    </a>
                    <ul>
                        <li>
                            <a href="#">
                                <input type="checkbox"><span>NODE A1</span>
                            </a>
                            <ul></ul>
                        </li>
                        <li>
                            <a href="#">
                                <input type="checkbox"><span>NODE A2</span>
                            </a>
                            <ul></ul>
                        </li>
                        <li>
                            <a href="#">
                                <input type="checkbox"><span>NODE A3</span>
                            </a>
                            <ul>
                                <li>
                                    <a href="#">
                                        <input type="checkbox"><span>NODE A3a</span>
                                    </a>
                                    <ul></ul>
                                </li>
                                <li>
                                    <a href="#">
                                        <input type="checkbox"><span>NODE A3b</span>
                                    </a>
                                    <ul>
                                        <li>
                                            <a href="#">
                                                <input type="checkbox"><span>NODE A3b1</span>
                                            </a>
                                            <ul></ul>
                                        </li>
                                        <li>
                                            <a href="#">
                                                <input type="checkbox"><span>NODE A3b2</span>
                                            </a>
                                            <ul></ul>
                                        </li>
                                    </ul>
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li>
                    <a href="#">
                        <input type="checkbox"><span>NODE B</span>
                    </a>
                    <ul></ul>
                </li>
                <li>
                    <a href="#">
                        <input type="checkbox"><span>NODE C</span>
                    </a>
                    <ul>
                        <li>
                            <a href="#">
                                <input type="checkbox"><span>NODE C1</span>
                            </a>
                            <ul></ul>
                        </li>
                        <li>
                            <a href="#">
                                <input type="checkbox"><span>NODE C2</span>
                            </a>
                            <ul>
                                <li>
                                    <a href="#">
                                        <input type="checkbox"><span>NODE C2a</span>
                                    </a>
                                    <ul></ul>
                                </li>
                                <li>
                                    <a href="#">
                                        <input type="checkbox"><span>NODE C2b</span>
                                    </a>
                                    <ul></ul>
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
            </ul>
gaganshera
  • 2,629
  • 1
  • 14
  • 21
  • Thanks man! One question: how did the answer I linked worked if it doesn't do the reverse trick? – Matías Cánepa May 16 '17 at 19:43
  • The difference is that you use `find`, which traverses from top to bottom. The example uses `prev` which traverses bottom to top. Hey if the answer worked for you, please mark it as correct. – gaganshera May 16 '17 at 19:54