Checkbox & indeterminate
Я разбирался с одним примером, где зашло в тупик.
Вот мой рабочий код, где вылезла такая ошибка. Тыкал в разной последовательности и по разным чекбоксам. Если по трем шагам сделать нажатиям чекбокса:
1 -> 1.1.2 -> 1
Видно, что не снята галочка indeterminate
// переменная, где массив с чекбоксами
let treeInterest = Array.from(document.querySelectorAll(".interest__check"));
// функция поиска чекбокса
function searchCheckbox() {
// цикл, где перебираем все чекбоксы
for (let i = 0; i < treeInterest.length; i++) {
// вешаем событие на клик изменения чекбокса
treeInterest[i].addEventListener("change", function() {
// переменная на дочерние чекбоксы, где ищет ближайший родительский элемент
let childCheckbox = treeInterest[i]
.closest(".interest")
.querySelectorAll(".interests_active .interest__check");
// условие, если поставить все галочки выведет все иначе снимутся все
treeInterest[i].checked ?
childCheckbox.forEach((elem) => (elem.checked = true)) :
childCheckbox.forEach((elem) => (elem.checked = false));
// поиск ближайшего элемента родителя
let parentActive = treeInterest[i].closest(".interests_active");
// проверка если есть родитель то изменяем чекбоксы через функцию
if (parentActive) {
changeTreeInterest(parentActive);
// поиск родителя
let parentActiveFarther = parentActive
.closest(".interest")
.querySelector(".interest__check")
.closest(".interests_active");
// если родитель есть то изменяем чекбоксы через функцию
if (parentActiveFarther) {
changeTreeInterest(parentActiveFarther);
}
}
});
}
}
// функция изменения чекбоксов родителя
function changeTreeInterest(parentActive) {
// переменные родителей чекбокса
let parentInterest = parentActive.closest(".interest");
let parent = parentInterest.querySelector(".interest__check");
// переменная где массив соседних чекбоксов
let neighborCheckbox = Array.from(
parentActive.querySelectorAll(".interest__check")
);
// массив для значений чекбокса
let childBooleanArray = [];
// перебираем все соседние чекбоксы и пушим в новый массив
neighborCheckbox.forEach((el) => childBooleanArray.push(el.checked));
// переменная истина, если все элементы в массиве истины
let childrenTrue = childBooleanArray.includes(true);
// переменная ложь, если все элементы в массиве ложны
let childrenFalse = childBooleanArray.includes(false);
// если все галочки ложь, то убираем тире у родителя и галочку у родителя
// если все галочки истина, то убираем тире у родителя и ставим галочку у родителя
// если галочки и истина и ложь, то ставим тире родителю и ставим галочку родителю
if (!childrenTrue && childrenFalse) {
parent.indeterminate = false;
parent.checked = false;
} else if (childrenTrue && !childrenFalse) {
parent.indeterminate = false;
parent.checked = true;
} else {
parent.indeterminate = true;
parent.checked = true;
}
}
// вызов функции
searchCheckbox();
<div class="card">
<div class="interests interests_main">
<ul>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1 </label>
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.1 </label>
<!-- Задание повышенной сложности. Раскомментируйте код -->
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.1.1 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.1.2 </label>
</li>
</ul>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.2 </label>
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.2.1 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.2.2 </label>
</li>
</ul>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3 </label>
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3.1 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3.2 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3.3 </label>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
Ответы (1 шт):
Автор решения: ksa
→ Ссылка
вылезла такая ошибка
Мне твой вариант кода не особо понравился... Предложу свой вариант алгоритма.
const oc = document.querySelector('.interests.interests_main')
oc.addEventListener('click', e => {
const o = e.target
if (o.type != 'checkbox') return
const v = o.checked
o.closest('.interest').querySelectorAll('ul .interest__check').forEach(o => {
o.checked = v
})
const oa = [...oc.querySelectorAll('.interest__check')]
oa.reverse().forEach(o => {
const op = o.closest('.interest').querySelector('ul')
if (!op) return
const n = op.querySelectorAll('.interest__check').length
const m = op.querySelectorAll(':checked').length
if (n === m) {
o.checked = true
o.indeterminate = false
return
}
if (!m) {
o.checked = false
o.indeterminate = false
return
}
o.indeterminate = true
})
})
<div class="card">
<div class="interests interests_main">
<ul>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1 </label>
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.1 </label>
<!-- Задание повышенной сложности. Раскомментируйте код -->
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.1.1 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.1.2 </label>
</li>
</ul>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.2 </label>
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.2.1 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.2.2 </label>
</li>
</ul>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3 </label>
<ul class="interests interests_active">
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3.1 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3.2 </label>
</li>
<li class="interest">
<label> <input type="checkbox" class="interest__check" />1.3.3 </label>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>