Skip to content

Instantly share code, notes, and snippets.

@angusjf
Last active August 30, 2023 19:17
Show Gist options
  • Save angusjf/3cc08177cf1a1ece21e142b600bf1f57 to your computer and use it in GitHub Desktop.
Save angusjf/3cc08177cf1a1ece21e142b600bf1f57 to your computer and use it in GitHub Desktop.
nested checkboxes w/ indeterminate state
<ul>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li><label><input type="checkbox">TVs</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
</ul>
</li>
</ul>
</li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Microphones</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Microphones</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Microphones</label></li>
</ul>
</li>
</ul>
</li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Microphones</label></li>
</ul>
</li>
<li><label><input type="checkbox">Microphones</label></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><label><input type="checkbox">Microphones</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
</ul>
</li>
</ul>
</li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
<li>
<label><input type="checkbox">Electronics</label>
<ul>
<li><label><input type="checkbox">Laptops</label></li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
</ul>
</li>
</ul>
</li>
<li><label><input type="checkbox">TVs</label></li>
<li><label><input type="checkbox">Microphones</label></li>
</ul>
</li>
</ul>
</li>
</ul>
<script>
const parent = (n) => n.closest("ul")?.closest("li")?.querySelector("label > input")
const children = (n) => n.closest("li")?.querySelectorAll("ul label > input")
const siblings = (n) => n.closest("ul")?.querySelectorAll("label > input")
document.querySelectorAll('input[type=checkbox]').forEach((checkbox) =>
checkbox.onclick = () => {
children(checkbox).forEach(child => {
child.checked = checkbox.checked
child.indeterminate = false
})
let p = checkbox
while (p = parent(p)) {
const sibs = [...siblings(checkbox)]
p.checked = sibs.every(x => x.checked)
p.indeterminate = !p.checked && sibs.some(x => x.checked)
}
}
)
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment