修复您的表单:
$('.checkboxlistitem') 和$('.checkboxlistitem:checked') 的选择器选择具有这些类的所有 元素,因此选择两种 形式的复选框。为了解决这个问题,他们需要上下文。
在 jQuery 的事件回调中,this 指的是触发事件的元素。这意味着我们可以使用相对选择器来找到合适的元素:
// find the nearest ancestor that's a form
$form = $(this).closest('form');
// find all the `.checkboxlistitem` elements within the form
$checkboxes = $form.find('.checkboxlistitem');
// find the all checkbox within the form
$all = $form.find('.select-all');
// if there are any unchecked checkboxes the all option should be unchecked
$all.prop('checked', !$checkboxes.not(':checked').length);
// leaving this as it was in the jsfiddle
// Select/Unselect all chexboxes of the form
$(".select-all").change(function () {
$(this).siblings().prop('checked', $(this).prop("checked"));
});
$('.checkboxlistitem').change(function () {
var $form,
$checkboxes,
$all;
// find the nearest ancestor that's a form
$form = $(this).closest('form');
// find all the `.checkboxlistitem` elements within the form
$checkboxes = $form.find('.checkboxlistitem');
// find the all checkbox within the form
$all = $form.find('.select-all');
// if there are any unchecked checkboxes the all option should be unchecked
$all.prop('checked', !$checkboxes.not(':checked').length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="filter1">
<form action='#'>
<input type="checkbox" value="all" class="select-all" checked>(All)
<br>
<input type="checkbox" value="v1" class="checkboxlistitem" checked>F1: Value1
<br>
<input type="checkbox" value="v2" class="checkboxlistitem" checked>F1: Value2
<br>
<input type="checkbox" value="v3" class="checkboxlistitem" checked>F1: Value3
<br>
<input type="checkbox" value="v4" class="checkboxlistitem" checked>F1: Value4
<br>
<input type="submit" value="Apply">
</form>
</div>
<div id="filter2">
<form action='#'>
<input type="checkbox" value="all" class="select-all" checked>(All)
<br>
<input type="checkbox" value="v1" class="checkboxlistitem" checked>F2: Value1
<br>
<input type="checkbox" value="v2" class="checkboxlistitem" checked>F2: Value2
<br>
<input type="checkbox" value="v3" class="checkboxlistitem" checked>F2: Value3
<br>
<input type="checkbox" value="v4" class="checkboxlistitem" checked>F2: Value4
<br>
<input type="submit" value="Apply">
</form>
</div>
这很好,但让我们通过改进表单的可访问性和部分完整复选框列表的行为来提升一个档次。
表单可访问性
标签
您的复选框没有标签。
当然,您在它们之后添加了文本,但屏幕阅读器无法知道每个复选框代表什么。
要解决此问题,请使用 <label> 元素。
<form action="#">
<label>
<input type="checkbox" value="all" class="select-all" checked>
(All)
</label>
<br>
<label>
<input type="checkbox" value="v1" class="checkboxlistitem" checked>
F1: Value1
</label>
<br>
...
</form>
它们可以嵌套复选框,也可以将其[for] 属性指向<input> 元素的[id] 属性,或两者兼而有之。
<form action="#">
<input type="checkbox" id="f1-all" value="all" class="select-all" checked> <label for="f1-all">(All)</label>
<br>
<input type="checkbox" id="f1-v1" value="v1" class="checkboxlistitem" checked> <label for="f1-v1">F1: Value1</label>
<br>
...
</form>
层次结构
“全部”复选框和单个 F#: Value# 复选框之间存在不同的层次关系。
要解决此问题,请使用 <fieldset> 和 <legend> 元素。
<form action="#">
<fieldset>
<legend>
<label>
<input type="checkbox" value="all" checked>
<span>Select All in Filter 1</span>
</label>
</legend>
<label>
<input type="checkbox" value="v1" checked>
<span>F1: Value1</span>
</label>
<br>
...
</fieldset>
</form>
行分隔
您当前正在使用<br> 元素将字段分隔到不同的行。
<p> elements are often used.
<form action="#">
<fieldset>
<legend>...</legend>
<p>
<label>
<input type="checkbox" value="v1" checked>
<span>F1: Value1</span>
</label>
</p>
...
</fieldset>
</form>
名字
您正在使用[value] 属性,这很好,但是<input> 元素都没有[name] 属性,这意味着数据不会发送到服务器,并调用jQuery 的@987654322表单上的 @ 不会为您提供适当的数据。
在具有重要值的复选框上设置[name](不需要“全部”复选框):
<form action="#">
<fieldset>
<legend>...</legend>
<p>
<label>
<input type="checkbox" name="v1" value="1" checked>
<span>F1: Value1</span>
</label>
</p>
...
</fieldset>
</form>
或者,您可以将所有 [name] 属性设置为 filter 并依靠各种值来生成查询字符串,例如 filter=v1&filter=v2,但这是一种高级技术,可能会遇到查询字符串解析的错误,所以请谨慎操作。
部分完整的复选框列表
虽然能够自动取消选中“所有”复选框,但当检查某些复选框并且未选中其他复选框时,未选中的状态并不完全有意义“所有”复选框。它不是“无”,也不是“全部”。
进入不确定状态。
复选框有第三种状态,该状态只能通过 JavaScript 访问,正是为这种情况而设计的。
您可以通过切换其indeterminate 属性将给定复选框设置为不确定状态:
document.querySelector('input[type="checkbox"]').indeterminate = true;
或使用 jQuery:
$('input[type="checkbox"]').first().prop('indeterminate', true);
可以通过以下区分来检查列表是否处于不确定状态:
- 未选中复选框
- 选中所有复选框
- 某些复选框已选中和未选中
实际上,这可能类似于:
checkedCount = $checkboxes.filter(':checked').length;
if (!checkedCount) {
// no checkboxes checked
$all.prop({
checked: false,
indeterminate: false
});
} else if (checkedCount === $checkboxes.length) {
// all checkboxes checked
$all.prop({
checked: true,
indeterminate: false
});
} else {
// some checkboxes checked and unchecked
$all.prop({
indeterminate: true
});
}
现在都在一起
上述所有内容的完整实现如下所示:
$('.filter').on('change', '[value="all"]', function () {
var $form,
$checkboxes,
$all;
$form = $(this).closest('form');
$checkboxes = $form.find('[name="filter"]');
$all = $form.find('[value="all"]');
$checkboxes.prop('checked', $all.prop('checked'));
}).on('change', '[name="filter"]', function () {
var $form,
$checkboxes,
$all,
checkedCount;
$form = $(this).closest('form');
$checkboxes = $form.find('[name="filter"]');
$all = $form.find('[value="all"]');
checkedCount = $checkboxes.filter(':checked').length;
if (!checkedCount) {
// no checkboxes checked
$all.prop({
checked: false,
indeterminate: false
});
} else if (checkedCount === $checkboxes.length) {
// all checkboxes checked
$all.prop({
checked: true,
indeterminate: false
});
} else {
// some checkboxes checked and unchecked
$all.prop({
indeterminate: true
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="filter1" class="filter">
<form action='#'>
<fieldset>
<legend>
<label>
<input type="checkbox" value="all" checked>
<span>Select All in Filter 1</span>
</label>
</legend>
<p>
<label>
<input type="checkbox" name="filter" value="v1" checked>
<span>F1: Value1</span>
</label>
</p>
<p>
<label>
<input type="checkbox" name="filter" value="v2" checked>
<span>F1: Value2</span>
</label>
</p>
<p>
<label>
<input type="checkbox" name="filter" value="v3" checked>
<span>F1: Value3</span>
</label>
</p>
<p>
<label>
<input type="checkbox" name="filter" value="v4" checked>
<span>F1: Value4</span>
</label>
</p>
</fieldset>
<input type="submit" value="Apply">
</form>
</div>
<div id="filter2" class="filter">
<form action='#'>
<fieldset>
<legend>
<label>
<input type="checkbox" value="all" checked>
<span>Select All in Filter 2</span>
</label>
</legend>
<p>
<label>
<input type="checkbox" name="filter" value="v1" checked>
<span>F2: Value1</span>
</label>
</p>
<p>
<label>
<input type="checkbox" name="filter" value="v2" checked>
<span>F2: Value2</span>
</label>
</p>
<p>
<label>
<input type="checkbox" name="filter" value="v3" checked>
<span>F2: Value3</span>
</label>
</p>
<p>
<label>
<input type="checkbox" name="filter" value="v4" checked>
<span>F2: Value4</span>
</label>
</p>
</fieldset>
<input type="submit" value="Apply">
</form>
</div>