在树形结构中动态地勾选/取消勾选复选框

4
我有一个类似于JQuery中如果所有子节点都未选中则取消父节点选中的问题(使用此解决方案),并尝试修改它,使得当取消选择父节点时,所有子节点也都取消勾选(而上面/下面的代码未能实现这一点)。
上述问题的JSFiddle链接为 (http://jsfiddle.net/fRxVs/)
jQuery.each(jQuery('#treeList ul li').find(':checkbox'),  function(){
    jQuery(this).change(function (){
        if (jQuery(this).is(':checked')) {
                      jQuery(this).parentsUntil('#treeList').siblings().filter('input:checkbox').attr('checked', true).trigger('change');
        }else{

            jQuery(this).parents('ul:first').siblings('input:checkbox').prop('checked', $(this).parent().siblings().children('input:checked').length).trigger('change');
        }        
    });    
});

尽管我不知道原因,但为了让JSFiddle在本地正确工作,我必须将最后一行的prop更改为attr
基本上,我的设置有三个级别:
Grand-Parent
- Parent
-- Child
  • 如果选中/取消选中祖父母,那么它的子代和孙辈应该全部被选中/取消选中。
  • 如果选中/取消选中父母,那么它的子代应该被选中/取消选中,同时它的父级也应该被选中/取消选中。
  • 如果选中子代,那么它的父级和祖父母也应该被选中(如果没有子代被选中,则不应选中父级)。

我正在尝试将此更改为大洲、国家、地区 - 如果我只是这样说,我认为您会理解...

谢谢


请看一下Code Review上的这个问题:http://codereview.stackexchange.com/questions/4939/nested-select-all-checkboxes/5038#5038 - John Hartsock
刚刚看了一下,并尝试了相应的 JSFiddle 示例 - 但那只会让子元素的父元素检查它们是否都已被选中(我想最终是所有子元素都要被选中)- 我希望只需一个子元素即可向上反馈。 - MrJ
我正在看它。我刚刚优化了代码,接下来要修复它 ;) - Rob W
感谢@RobW!期待看到你的解决方案,希望通过它能增加我对jQuery的理解 :) - MrJ
2个回答

6
这是解决方案:Fiddle: http://jsfiddle.net/fRxVs/55/
$('#treeList :checkbox').change(function (){
    $(this).siblings('ul').find(':checkbox').prop('checked', this.checked);
    if (this.checked) {
        $(this).parentsUntil('#treeList', 'ul').siblings(':checkbox').prop('checked', true);
    } else {
        $(this).parentsUntil('#treeList', 'ul').each(function(){
            var $this = $(this);
            var childSelected = $this.find(':checkbox:checked').length;
            if (!childSelected) {
                $this.prev(':checkbox').prop('checked', false);
            }
        });
    }
});

修改和解释

  • $jQuery 是完全相同的。在使用时要保持一致: 只有在不确定 $ === jQuery(是否覆盖了 $)时才使用 jQuery
  • :checkbox 是选择器,匹配所有 input[type="checkbox"]。指定 input:checbkox 已经过时,因为复选框元素始终是输入元素。
  • .find(..) 查找与匹配的选择器的任何子元素(不一定是直接子元素)。"#treeList :checkbox" 更快,并且具有与 $('#treeList').find(':checkbox') 相同的结果。
  • 当向 jQuery 对象添加属性/方法/事件时,所有与选择器匹配的元素都将被修改。因此,您无需逐个遍历每个元素: jQuery.each(jQuery('#treeList :checkbox'), function(){ jQuery(this).change(...)}) 可以简化为 jQuery('#treeList :checkbox').change(...)
  • 更改复选框的选中状态后,不必触发 change,因为该函数已经处理了整个树形结构。

不错!尽管我刚注意到,如果您选中2个“父级”,然后取消选中一个,“祖父母”就会取消选中,能否修改使得只有在没有选中任何父级时才取消选中祖父母? - MrJ
使得当我取消选中每个子项时,而不是取消选中父项。 - MrJ
顺便说一下,解释得非常好! - MrJ

0

虽然这是一个老问题,但你可以像这样做:

$('input[type=checkbox]').change(function(){
    $(this).next().find('input[type=checkbox]').prop('checked', this.checked);
    $(this).parents('ul').prev('input[type=checkbox]').prop('checked', function(){
        return $(this).next().find(':checked').length;
    });
});

代码演示: http://jsfiddle.net/ojc1qg1f/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接