Checkboxes nested

controle nested checkboxes

by slawe

HTML

<div id="page-wrap">
	
	   <h2>Treeview with Custom Checkboxes and Indeterminate State</h2>
		
  	 <ul class="treeview">
        <li>
            <input type="checkbox" name="tall" id="tall">
            <label for="tall" class="custom-unchecked">Tall Things</label>
            
            <ul>
                 <li>
                     <input type="checkbox" name="tall-1" id="tall-1">
                     <label for="tall-1" class="custom-unchecked">Buildings</label>
                 </li>
                 <li>
                     <input type="checkbox" name="tall-2" id="tall-2">
                     <label for="tall-2">Giants</label>
                     <ul>
                         <li>
                             <input type="checkbox" name="tall-2-1" id="tall-2-1">
                             <label for="tall-2-1" class="custom-unchecked">Andre</label>
                         </li>
                         <li>
                             <input type="checkbox" name="tall-2-2" id="tall-2-2">
                             <label for="tall-2-2" class="custom-unchecked">Paul Bunyan</label>
                         </li>
                     </ul>
                 </li>
                 <li>
                     <input type="checkbox" name="tall-3" id="tall-3">
                     <label for="tall-3" class="custom-unchecked">Two sandwiches</label>
                 </li>
            </ul>
        </li>
        <li class="last">
            <input type="checkbox" name="short" id="short">
            <label for="short" class="custom-unchecked">Short Things</label>
            
            <ul>
                 <li>
                     <input type="checkbox" name="short-1" id="short-1">
                     <label for="short-1" class="custom-unchecked">Smurfs</label>
                 </li>
                 <li>
                     <input type="checkbox" name="short-2" id="short-2">
                     <label for="short-2"...

CSS

ul { 
  list-style: none;
}

JavaScript

$(function() {

  $('#page-wrap input[type="checkbox"]').change(checkboxChanged);

  function checkboxChanged() {
    let $this = $(this),
        checked = $this.prop("checked"),
        container = $this.parent(),
        siblings = container.siblings();

    container.find('input[type="checkbox"]')
    .prop({ checked: checked })
    .siblings('label')
    .removeClass('custom-checked custom-unchecked')
    .addClass(checked ? 'custom-checked' : 'custom-unchecked');

    checkSiblings(container, checked);
  }

  function checkSiblings($el, checked) {
    let parent = $el.parent().parent(),
        all = true;

    $el.siblings().each(function() {
      return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);
    });

    if (all && checked) {
      parent.children('input[type="checkbox"]')
      .prop({ checked: checked })
      .siblings('label')
      .removeClass('custom-checked custom-unchecked')
      .addClass(checked ? 'custom-checked' : 'custom-unchecked');

      checkSiblings(parent, checked);
    } 
    else if (all && !checked) {

      parent.children('input[type="checkbox"]')
      .prop("checked", checked)
      .siblings('label')
      .removeClass('custom-checked custom-unchecked')
      .addClass(checked ? 'custom-checked' : 'custom-unchecked');

      checkSiblings(parent, checked);
    } 
    else {
      $el.parents("li").children('input[type="checkbox"]')
      .prop({ checked: true })
      .siblings('label')
      .removeClass('custom-checked custom-unchecked')
      .addClass('custom-checked');
    }
  }
});