复选框不确定状态逻辑



我嵌套了一个无序列表,其中一个列表项作为它的标题,看起来像这样。

<ul>
    <li><input type="checkbox" /> Header 1</li>
    <ul>
        <li><input type="checkbox" value="1" />Item 1</li>
    </ul>
    <li><input type="checkbox" /> Header 2</li>
    <ul>
        <li><input type="checkbox" value="1" />Item 1</li>
        <li><input type="checkbox" value="2" />Item 2</li>
        <li><input type="checkbox" value="3" />Item 3</li>
        <li><input type="checkbox" value="4" />Item 4</li>
    </ul>
    <li><input type="checkbox" /> Header 3</li>
    <ul>
        <li><input type="checkbox" value="5" />Item 5</li>
        <li><input type="checkbox" value="6" />Item 6</li>
        <li><input type="checkbox" value="7" />Item 7</li>
        <li><input type="checkbox" value="8" />Item 8</li>
        <li><input type="checkbox" value="9" />Item 9</li>
        <li><input type="checkbox" value="10" />Item 10</li>
        <li><input type="checkbox" value="11" />Item 11</li>
        <li><input type="checkbox" value="12" />Item 12</li>
        <li><input type="checkbox" value="13" />Item 13</li>
        <li><input type="checkbox" value="14" />Item 14</li>
        <li><input type="checkbox" value="15" />Item 15</li>
        <li><input type="checkbox" value="16" />Item 16</li>
    </ul>
</ul>

注意item1存在于Header 1的列表中,也存在于Header 2的列表中

有几件事我正在努力完成。

  1. 当我点击一个标题项目,它会自动选择或取消选择所有列表项目li在它的ul列表紧随其后。
  2. 当我点击一个列表项目li内嵌套的ul我要检查,看看是否其他项目都被选中(在这种情况下,在标题列表项目上放置一个复选标记),或未选中(在这种情况下,删除标题列表项目上的复选标记),如果它是选中和未选中的混合,然后设置标题列表项目为不确定状态。
  3. 当我检查一个列表项,如列表项1,显示在头1的列表和头2的列表,我希望它取消选中两个项目,或检查两个列表中的两个项目,并导致检查要求二发生在受影响的列表。

我很难做到这一点,因为我不是很擅长JavaScript,到目前为止我读过的所有代码都没有真正接近我需要的。

任何帮助都会很感激。我使用的是jQuery 1.9.1,但是如果你想用JavaScript来完成它,我也很好(因为当你在Google Dev Tools中设置一个断点来查看正在发生什么时,它更容易遵循)。

我已经将topList类添加到外部UL中,并将header类添加到LI header元素中以简化选择器,因此您可能想要调整它,但我认为这应该做您想要的。关于jsfiddle

的完整示例
//selects all items under a header. This might also select checkboxes from other headers if they share a value. Assumes, "this" points to the header LI
function selectAll() {
    var $this = $(this);
    var isChecked = $this.find(":checkbox").prop("checked");
    $this.find("+ul :checkbox").each(function() {
        selectCheckbox($(this), isChecked);
    });
    $(".header + ul").each(updateHeaderState);
}
//selects or deselects a checkbox. Also, selects other checkboxes if they share a value
function selectCheckbox($checkbox, isChecked) {
    var value = $checkbox.val();
    $checkbox.prop("checked", isChecked);
    $(".topList :checkbox[value="+value+"]").prop("checked", isChecked);
}
//updates the state of the header checkbox. Assumes "this" points to the UL element following a header
function updateHeaderState() {
    var $this = $(this);
    var someChecked = $this.find(":checkbox:checked").length > 0;
    var someUnchecked = $this.find(":checkbox:not(:checked)").length > 0;
    var $header = $this.prev().find(":checkbox");
    $header.prop("indeterminate", someChecked && someUnchecked);
    $header.prop("checked", someChecked || !someUnchecked);
}
$(".header").click(selectAll);
$(".header + ul li").click(function() {
    var $this = $(this);
    var isChecked = $this.find(":checkbox").prop("checked");
    selectCheckbox($this.find(":checkbox"), isChecked);    
    $(".header + ul").each(updateHeaderState);
});

最新更新