如何检查是否所有兄弟姐妹(包括选定的)都用jQuery检查?
How to check if all siblings (including selected) are checked with jQuery?
我试图只获取所选元素的兄弟元素,但找不到合适的方法或实现方法。我总是用 find() 方法得到整棵树,用 children() 我无法让它工作。
此点击应该像复选框树一样工作:
如果单击 parent,则应单击所有 children,如果取消选中 parent,则必须取消选中所有 children。
但是不起作用的是,如果您选中了一个复选框并且没有单击所有兄弟姐妹,那么 parent 必须不确定!
而且上面的parent一定是不确定的。
所以我真正需要的是获取选中复选框的 parent 然后收集 children 并检查它们是否都被选中。如果是,则将 parent 设置为已选中,如果不是,则 parent 必须不确定。但问题是 jquery 深入....我只需要第一个 children,而不是下面的所有内容。
$(document).on('change', 'input.parent_cat_0', function() {
var mainPermission = $(this);
var mainPermissionChildren = mainPermission.parent().find('input:checkbox');
if (mainPermission.is(':checked')) {
mainPermissionChildren.each(function() {
this.indeterminate = false;
this.checked = true;
});
} else {
mainPermissionChildren.each(function() {
this.indeterminate = false;
this.checked = false;
$(this).removeClass("displayNone").next("img.tick").remove();
});
}
});
$(document).on('change', 'input.docPermission:not(.parent_cat_0)', function() {
var selected = $(this);
var liParents = selected.parents('li');
var allCheckboxes = liParents.find('input:checkbox');
var childrenOfSelected = selected.parent().find('input:checkbox');
var upperParents = $(allCheckboxes).not(childrenOfSelected).get();
if (selected.is(':checked')) {
childrenOfSelected.prop('indeterminate', false);
childrenOfSelected.prop('checked', true);
//console.log('Total upper parents:', upperParents.length);
$(upperParents).each(function (i,e) {
// HOW TO GET ONLY FIRST SIBLINGS
// For example if you click on Form 1
// you should get only (Form 1a, Form 1b, Form 1c)
// but NOT 'Form 1aa'
//console.log($(e));
});
} else {
childrenOfSelected.prop('indeterminate', false);
childrenOfSelected.prop('checked', false);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<li class="main">
<input type="checkbox" id="cat_52" class="docPermission parent_cat_0" name="localPerm[]">
<label class="strong" for="cat_52">Forms</label>
<ul>
<li>
<input type="checkbox" id="cat_53" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_53">Form 1</label>
<ul>
<li>
<input type="checkbox" id="cat_55" class="docPermission parent_cat_53" name="localPerm[]">
<label class="strong" for="cat_55">Form 1a</label>
<ul>
<li>
<input type="checkbox" id="cat_56" class="docPermission parent_cat_55" name="localPerm[]">
<label class="strong" for="cat_56">Form 1aa</label>
</li>
</ul>
</li>
<li class="main">
<input type="checkbox" id="doc_80" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_80">Form 1b</label>
</li>
<li class="main">
<input type="checkbox" id="doc_82" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_82">Form 1c</label>
</li>
</ul>
</li>
<li>
<input type="checkbox" id="cat_54" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_54">Form 2</label>
</li>
</ul>
</li>
您可以尝试 siblings()
和 andSelf()
$(document).on('change', 'input:checkbox', function(e) {
const $this = $(this);
if (!e.isTrigger) {
$this
.siblings('ul')
.find('input:checkbox')
.prop('checked', this.checked);
}
const $children = $this.parent('li').siblings().addBack();
const $ckb = $children.find('> input:checkbox');
const total = $ckb.length;
const checked = $ckb.filter(':checked').length;
const indeter = $ckb.filter(function() {
return this.indeterminate;
}).length;
$this
.parents('ul:first')
.siblings('input:checkbox')
.prop({
checked: checked === total,
indeterminate: indeter > 0 || (checked > 0 && checked < total)
})
.trigger('change')
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
<li class="main">
<input type="checkbox" id="cat_52" class="docPermission parent_cat_0" name="localPerm[]">
<label class="strong" for="cat_52">Forms</label>
<ul>
<li>
<input type="checkbox" id="cat_53" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_53">Form 1</label>
<ul>
<li>
<input type="checkbox" id="cat_55" class="docPermission parent_cat_53" name="localPerm[]">
<label class="strong" for="cat_55">Form 1a</label>
<ul>
<li>
<input type="checkbox" id="cat_56" class="docPermission parent_cat_55" name="localPerm[]">
<label class="strong" for="cat_56">Form 1aa</label>
</li>
</ul>
</li>
<li class="main">
<input type="checkbox" id="doc_80" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_80">Form 1b</label>
</li>
<li class="main">
<input type="checkbox" id="doc_82" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_82">Form 1c</label>
</li>
</ul>
</li>
<li>
<input type="checkbox" id="cat_54" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_54">Form 2</label>
</li>
</ul>
</li>
</ul>
而不是依赖SomeParentCheckbox.trigger('change')
我们可以递归遍历父组
- 在复选框更改时,处理后代复选框(任何深度),将
checked
状态设置为与触发的复选框相同。
- 复选框更改,递归遍历父级以设置
checked
或indeterminate
属性状态
function handleDocPermParent(ckb) {
// Get group element: (Ideally we would have a 'group' class, but sadly we don't, so let's go tricky for known common selectors)
const $group = $(ckb).closest('ul');
const $par = $group.closest('li');
if (!$par.length) return; // No parent? Recursion job done!
const $par_ckb = $par.find(docPermClass).first(); // Find parent's main checkbox
const $group_ckb = $group.children('li').children(docPermClass); // Collect all group's checkboxes
const tot = $group_ckb.length; // How many checkboxes?
const tot_checked = $group_ckb.filter(':checked').length; // How many siblings are checked?
const tot_indeter = $group_ckb.filter((i, e) => e.indeterminate).length; // How many siblings are indeterminate?
$par_ckb.prop({ // Finally set parent's main checkbox state:
checked: tot_checked === tot,
indeterminate: tot_indeter || tot_checked && tot_checked < tot
});
handleDocPermParent($par_ckb[0]); // Recursively iterate to outer parent
}
const docPermClass = '.docPermission';
const $docPerm = $(docPermClass);
$docPerm.on('change', function (evt) {
const $ch = $(this).parent().find(docPermClass).not(this);
$ch.prop({checked: this.checked}); // Handle inner checkboxes (in all childrens, any depth) explicitly:
handleDocPermParent(this); // Handle parents recursively (from inner to outer) implicitly:
});
<ul>
<li class="main">
<input type="checkbox" id="cat_52" class="docPermission parent_cat_0" name="localPerm[]">
<label class="strong" for="cat_52">Forms</label>
<ul>
<li>
<input type="checkbox" id="cat_53" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_53">Form 1</label>
<ul>
<li>
<input type="checkbox" id="cat_55" class="docPermission parent_cat_53" name="localPerm[]">
<label class="strong" for="cat_55">Form 1a</label>
<ul>
<li>
<input type="checkbox" id="cat_56" class="docPermission parent_cat_55" name="localPerm[]">
<label class="strong" for="cat_56">Form 1aa</label>
</li>
</ul>
</li>
<li class="main">
<input type="checkbox" id="doc_80" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_80">Form 1b</label>
</li>
<li class="main">
<input type="checkbox" id="doc_82" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_82">Form 1c</label>
</li>
</ul>
</li>
<li>
<input type="checkbox" id="cat_54" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_54">Form 2</label>
</li>
</ul>
</li>
</ul>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
我试图只获取所选元素的兄弟元素,但找不到合适的方法或实现方法。我总是用 find() 方法得到整棵树,用 children() 我无法让它工作。
此点击应该像复选框树一样工作:
如果单击 parent,则应单击所有 children,如果取消选中 parent,则必须取消选中所有 children。
但是不起作用的是,如果您选中了一个复选框并且没有单击所有兄弟姐妹,那么 parent 必须不确定!
而且上面的parent一定是不确定的。
所以我真正需要的是获取选中复选框的 parent 然后收集 children 并检查它们是否都被选中。如果是,则将 parent 设置为已选中,如果不是,则 parent 必须不确定。但问题是 jquery 深入....我只需要第一个 children,而不是下面的所有内容。
$(document).on('change', 'input.parent_cat_0', function() {
var mainPermission = $(this);
var mainPermissionChildren = mainPermission.parent().find('input:checkbox');
if (mainPermission.is(':checked')) {
mainPermissionChildren.each(function() {
this.indeterminate = false;
this.checked = true;
});
} else {
mainPermissionChildren.each(function() {
this.indeterminate = false;
this.checked = false;
$(this).removeClass("displayNone").next("img.tick").remove();
});
}
});
$(document).on('change', 'input.docPermission:not(.parent_cat_0)', function() {
var selected = $(this);
var liParents = selected.parents('li');
var allCheckboxes = liParents.find('input:checkbox');
var childrenOfSelected = selected.parent().find('input:checkbox');
var upperParents = $(allCheckboxes).not(childrenOfSelected).get();
if (selected.is(':checked')) {
childrenOfSelected.prop('indeterminate', false);
childrenOfSelected.prop('checked', true);
//console.log('Total upper parents:', upperParents.length);
$(upperParents).each(function (i,e) {
// HOW TO GET ONLY FIRST SIBLINGS
// For example if you click on Form 1
// you should get only (Form 1a, Form 1b, Form 1c)
// but NOT 'Form 1aa'
//console.log($(e));
});
} else {
childrenOfSelected.prop('indeterminate', false);
childrenOfSelected.prop('checked', false);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<li class="main">
<input type="checkbox" id="cat_52" class="docPermission parent_cat_0" name="localPerm[]">
<label class="strong" for="cat_52">Forms</label>
<ul>
<li>
<input type="checkbox" id="cat_53" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_53">Form 1</label>
<ul>
<li>
<input type="checkbox" id="cat_55" class="docPermission parent_cat_53" name="localPerm[]">
<label class="strong" for="cat_55">Form 1a</label>
<ul>
<li>
<input type="checkbox" id="cat_56" class="docPermission parent_cat_55" name="localPerm[]">
<label class="strong" for="cat_56">Form 1aa</label>
</li>
</ul>
</li>
<li class="main">
<input type="checkbox" id="doc_80" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_80">Form 1b</label>
</li>
<li class="main">
<input type="checkbox" id="doc_82" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_82">Form 1c</label>
</li>
</ul>
</li>
<li>
<input type="checkbox" id="cat_54" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_54">Form 2</label>
</li>
</ul>
</li>
您可以尝试 siblings()
和 andSelf()
$(document).on('change', 'input:checkbox', function(e) {
const $this = $(this);
if (!e.isTrigger) {
$this
.siblings('ul')
.find('input:checkbox')
.prop('checked', this.checked);
}
const $children = $this.parent('li').siblings().addBack();
const $ckb = $children.find('> input:checkbox');
const total = $ckb.length;
const checked = $ckb.filter(':checked').length;
const indeter = $ckb.filter(function() {
return this.indeterminate;
}).length;
$this
.parents('ul:first')
.siblings('input:checkbox')
.prop({
checked: checked === total,
indeterminate: indeter > 0 || (checked > 0 && checked < total)
})
.trigger('change')
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
<li class="main">
<input type="checkbox" id="cat_52" class="docPermission parent_cat_0" name="localPerm[]">
<label class="strong" for="cat_52">Forms</label>
<ul>
<li>
<input type="checkbox" id="cat_53" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_53">Form 1</label>
<ul>
<li>
<input type="checkbox" id="cat_55" class="docPermission parent_cat_53" name="localPerm[]">
<label class="strong" for="cat_55">Form 1a</label>
<ul>
<li>
<input type="checkbox" id="cat_56" class="docPermission parent_cat_55" name="localPerm[]">
<label class="strong" for="cat_56">Form 1aa</label>
</li>
</ul>
</li>
<li class="main">
<input type="checkbox" id="doc_80" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_80">Form 1b</label>
</li>
<li class="main">
<input type="checkbox" id="doc_82" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_82">Form 1c</label>
</li>
</ul>
</li>
<li>
<input type="checkbox" id="cat_54" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_54">Form 2</label>
</li>
</ul>
</li>
</ul>
而不是依赖SomeParentCheckbox.trigger('change')
我们可以递归遍历父组
- 在复选框更改时,处理后代复选框(任何深度),将
checked
状态设置为与触发的复选框相同。 - 复选框更改,递归遍历父级以设置
checked
或indeterminate
属性状态
function handleDocPermParent(ckb) {
// Get group element: (Ideally we would have a 'group' class, but sadly we don't, so let's go tricky for known common selectors)
const $group = $(ckb).closest('ul');
const $par = $group.closest('li');
if (!$par.length) return; // No parent? Recursion job done!
const $par_ckb = $par.find(docPermClass).first(); // Find parent's main checkbox
const $group_ckb = $group.children('li').children(docPermClass); // Collect all group's checkboxes
const tot = $group_ckb.length; // How many checkboxes?
const tot_checked = $group_ckb.filter(':checked').length; // How many siblings are checked?
const tot_indeter = $group_ckb.filter((i, e) => e.indeterminate).length; // How many siblings are indeterminate?
$par_ckb.prop({ // Finally set parent's main checkbox state:
checked: tot_checked === tot,
indeterminate: tot_indeter || tot_checked && tot_checked < tot
});
handleDocPermParent($par_ckb[0]); // Recursively iterate to outer parent
}
const docPermClass = '.docPermission';
const $docPerm = $(docPermClass);
$docPerm.on('change', function (evt) {
const $ch = $(this).parent().find(docPermClass).not(this);
$ch.prop({checked: this.checked}); // Handle inner checkboxes (in all childrens, any depth) explicitly:
handleDocPermParent(this); // Handle parents recursively (from inner to outer) implicitly:
});
<ul>
<li class="main">
<input type="checkbox" id="cat_52" class="docPermission parent_cat_0" name="localPerm[]">
<label class="strong" for="cat_52">Forms</label>
<ul>
<li>
<input type="checkbox" id="cat_53" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_53">Form 1</label>
<ul>
<li>
<input type="checkbox" id="cat_55" class="docPermission parent_cat_53" name="localPerm[]">
<label class="strong" for="cat_55">Form 1a</label>
<ul>
<li>
<input type="checkbox" id="cat_56" class="docPermission parent_cat_55" name="localPerm[]">
<label class="strong" for="cat_56">Form 1aa</label>
</li>
</ul>
</li>
<li class="main">
<input type="checkbox" id="doc_80" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_80">Form 1b</label>
</li>
<li class="main">
<input type="checkbox" id="doc_82" class="docPermission parent_cat_53" name="localPerm[]">
<label for="doc_82">Form 1c</label>
</li>
</ul>
</li>
<li>
<input type="checkbox" id="cat_54" class="docPermission parent_cat_52" name="localPerm[]">
<label class="strong" for="cat_54">Form 2</label>
</li>
</ul>
</li>
</ul>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>