自动选中/取消选中“全部”复选框

时间:2016-08-18 22:27:32

标签: javascript jquery html checkbox

我是JS的新手,我有一个带有2个过滤器的页面,我被困住了,我正在尝试:

  1. 如果检查过滤器的其他每个复选框,则自动检查(全部)复选框。

  2. 当用户取消选中复选框时,会自动取消选中(全部)复选框。

  3. 我正在尝试以下代码,但它并没有真正起作用......

    HTML:

    <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>
    

    JS:

    $(".checkboxlistitem").change(function() {
    $(".select-all").prop("checked", $(".checkboxlistitem:checked").length ==    $(".checkboxlistitem").length);});
    

    的jsfiddle:

    https://jsfiddle.net/Max06270/5scgbnww/

    如果您需要澄清,请告诉我, 提前致谢, 最大

3 个答案:

答案 0 :(得分:5)

你的jquery选择器过于通用,因此它们影响了两种形式。下面应该是你想要的一个工作例子:

&#13;
&#13;
$(".select-all").change(function () {
    $(this).siblings().prop('checked', $(this).prop("checked"));
});

$(".checkboxlistitem").change(function() {
	  var checkboxes = $(this).parent().find('.checkboxlistitem');
    var checkedboxes = checkboxes.filter(':checked');

    if(checkboxes.length === checkedboxes.length) {
     $(this).parent().find('.select-all').prop('checked', true);
    } else {
    $(this).parent().find('.select-all').prop('checked', false);
    }
});
&#13;
<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>

<br>

<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>
&#13;
&#13;
&#13;

https://jsfiddle.net/0epu6Lnn/

答案 1 :(得分:2)

修复您的表单:

您的$('.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]属性指向[id]元素的<input>属性,或两者兼而有之。

<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的.serialize()将无法获得适当的数据。

在具有重要值的复选框上设置[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);

检查列表是否处于不确定状态可以通过区分:

来完成
  1. 未选中复选框
  2. 选中所有复选框
  3. 选中并取消选中某些复选框
  4. 在实践中,这可能类似于:

    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
      });
    }
    

    All Together Now

    完全充实的以上所有内容的实现如下:

    $('.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>

答案 2 :(得分:0)

对于那些想要使用 vanilla js 的人:

const checkboxes = document.getElementsByClassName("checkboxlistitem");
const selectAllBtn = document.getElementById("select-all");
for (let i = 0; i < checkboxes.length; i++) {
  checkboxes[i].addEventListener("change", () => {
    for (let i = 0; i < checkboxes.length; i++) {
      if (checkboxes[i].checked === false) {
        selectAllBtn.checked = false;
        break;
      } else {
        selectAllBtn.checked = true;
      }
    }
  });
}
// select all button

selectAllBtn.addEventListener("change", (event) => {
  for (let i = 0, n = checkboxes.length; i < n; i++) {
    checkboxes[i].checked = event.target.checked;
    
  }
});
<div id="filter1">
  <form action='#'>
    <input type="checkbox" value="all" id="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>