'Getting the value of parent checkbox for checked and indeterminate status

I have nested checkboxes with a tree hierarchy level. It contains also both indeterminate and checked status for each level. Basically, I need to store each checked / indeterminate value of the checkbox in an array with the correct level. Unfortunately, I'm not able to include indeterminate values with the current solution. Is there any way we can search for two elements (input:checked,input:indeterminate) at the same time?

function toggleCheckboxArea(onlyHide = false) {
  var checkboxes = document.getElementById("SelectOptions");
  var displayValue = checkboxes.style.display;

  if (displayValue != "block") {
    if (onlyHide == false) {
      checkboxes.style.display = "block";
    }
  } else {
    checkboxes.style.display = "none";
  }
}

let data = {
  "Tall Things": {
    "label": "Tall Things",
    "children": {
      "Buildings": {
        "label": "Buildings",
      },
      "Two sandwiches": {
        "label": "Two sandwiches",
      },
      "Giants": {
        "label": "Giants",
        "children": {
          "Andre": {
            "label": "Andre",
          },
          "Paul Bunyan": {
            "label": "Paul Bunyan",
          }
        }
      }
    }
  },
   "Tall' Things 2": {
    "label": "Tall' Things 2",
    "children": {
      "Buildings 2": {
        "label": "Buildings 2",
      },
      "Two sandwiches 2": {
        "label": "Two sandwiches 2",
      },
      "Giants 2": {
        "label": "Giants 2",
        "children": {
          "Andre 2": {
            "label": "Andre 2",
          },
          "Paul Bunyan 2": {
            "label": "Paul Bunyan 2",
          }
        }
      }
    }
  } 
}

let nodeLevel = 1;

function addItem(parentUL, branch, parentName) {
  for (var key in branch) {
    var item = branch[key].children;

    let name = '';

    if (parentName) {
      name = parentName }

    $item = $('<li>', {
      id: key,
    });
    $item.append($('<input>', {
      type: "checkbox",
      id: 'smb',
      name: key,
      value: key,
      "data-parent": name,
    }));
    $item.append($('<label>', {
      for: key,
      text: key
    }));
    parentUL.append($item);
    nodeLevel++;
    if (branch[key].children) {
      var $ul = $('<ul>', {
        class: 'ul-child',
        style: 'display: none'
      }).appendTo($item);

      addItem($ul, item, branch[key].label);
    } else {
      nodeLevel = 1;
    }
  }
}

// On default load
$(document).ready(function(){
  addItem($('#sb'), data);

  $('input[type="checkbox"]').prop("checked", "true");

  $('label').click(function(){
    $(this).closest('li').children('ul').slideToggle();  
  });  

$('input[type="checkbox"]').change(function(e) {

  var checked = $(this).prop("checked"),
      container = $(this).parent(),
      siblings = container.siblings();

  container.find('input[type="checkbox"]').prop({
    indeterminate: false,
    checked: checked
  });

  function checkSiblings(el) {

    var parent = el.parent().parent(),
        all = true;

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

      parent.children('input[type="checkbox"]').prop({
        indeterminate: false,
        checked: checked
      });

      checkSiblings(parent);

    } else if (all && !checked) {

      parent.children('input[type="checkbox"]').prop("checked", checked);
      parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));
      checkSiblings(parent);

    } else {

      el.parents("li").children('input[type="checkbox"]').prop({
        indeterminate: true,
        checked: false
      });

    }

  }

  checkSiblings(container);
});

});


$(".save").click(function() {

    var sbl1 = $('#sb li input:checked').not('#sb li ul li input:checked').not('#sb li ul li ul li input:checked').map(
        function(x){
            return $(this).val().replace(/(["'])/g, "\\$1");
        }).get().join('\',\'');   
    
    console.log(sbl1)
});
        .no-bullets {
          list-style: none;
          padding: 0;
          margin: 0;
        }  
        .ul-child {
          list-style: none;
          margin: 0 0 0 5px;
        }
        .selectBox {
          position: relative;
        }
        .overSelect {
          position: absolute;
          left: 0;
          right: 0;
          top: 0;
          bottom: 0;
        }
        #SelectOptions {
          display: none;
          border: 0.5px #7c7c7c solid;
          background-color: #ffffff;
          max-height: 300px;
          overflow-y: scroll;
          text-align: left;
        }
        #SelectOptions label:hover {
          background-color: #1e90ff;
        }
<head>
  <meta charset="UTF-8">
<link rel="stylesheet" href="./style.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
</head>
<body>
  <div class="form-group col-sm-8">
      <div class="selectBox" onclick="toggleCheckboxArea()">
        <select class="form-select">
          <option></option>
        </select>
        <div class="overSelect"></div>
      </div>
      <div id="SelectOptions">
<ul class="no-bullets">
<li id="All">
<input type="checkbox" name="selectAll" id="selectAll">
<label>All</label>
<ul class="ul-child" style="display:none;" id="sb">
</ul>
</li>
</ul>
</div>
</div>
<button class="save">Save</button>
<p id="demo"></p>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script  src="./script.js"></script>
</body>


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source