Indeterminate state of the checkbox

Checkbox that holds another checkboxes and it is in indeterminate

by Konstantin Rouda

HTML

<section class="c-checkboxes-group">
  <dl id="checkboxesList">
    <dt>
      <input class="o-checkbox o-checkbox--main" id="main-checkbox" name="names" type="checkbox" />
      <label for="main-checkbox">Family</label>
    </dt>
    <dd>
      <input class="o-checkbox o-checkbox--secondary" id="checkbox-chris" name="name" type="checkbox" value="chris" />
      <label for="checkbox-chris">Chris</label>
    </dd>
    <dd>
      <input class="o-checkbox o-checkbox--secondary" id="checkbox-stewie" name="name" type="checkbox" value="stewie" />
      <label for="checkbox-stewie">Stewie</label>
    </dd>
    <dd>
      <input class="o-checkbox o-checkbox--secondary" id="checkbox-meg" name="name" type="checkbox" value="meg" />
      <label for="checkbox-meg">Meg</label>
    </dd>
  </dl>
</section>

JavaScript

;(function () {
  "use strict";
  
  const checkboxesList = document.getElementById("checkboxesList");
  const checkboxes = checkboxesList.querySelectorAll(".o-checkbox--secondary");
  const mainCheckbox = checkboxesList.querySelector(".o-checkbox--main");
  
  
  checkboxesList.addEventListener("change", onCheckboxChange);
  
  
  
  function onCheckboxChange (e) {
    const targetCheckbox = e.target;
    const isSecondaryCheckbox = targetCheckbox.matches(".o-checkbox--secondary");
    const isChecked = targetCheckbox.checked;
    let checkedCounter = 0;
    
    if(isSecondaryCheckbox) {
      checkboxes.forEach(function (checkbox) { if(checkbox.checked) { checkedCounter++; } });

      if(checkedCounter === checkboxes.length) {
        mainCheckbox.checked = true;
        mainCheckbox.indeterminate = false;
      } else if (checkedCounter === 0) {
        mainCheckbox.checked = false;
        mainCheckbox.indeterminate = false;
      } else {
        mainCheckbox.indeterminate = true;
      }
      
    } else {
      checkboxes.forEach(function (checkbox) { checkbox.checked = isChecked; })
    }
    
  };
  
  
  
})();