s88s
(s88s)
01.Октябрь.2020 13:37:42
#1
Здравствуйте.
Помогите решить одну задачу
Есть несколько групп с checkbox
<div id="div_1">
<label><input type="checkbox" name="checkbox1_1">1 Общий</label>
<label><input type="checkbox" name="checkbox1_2">1.1</label>
<label><input type="checkbox" name="checkbox1_3">1.2</label>
<label><input type="checkbox" name="checkbox1_4">1.3</label>
</div>
<div id="div_2">
<label><input type="checkbox" name="checkbox2_1">2 Общий</label>
<label><input type="checkbox" name="checkbox2_2">2.1</label>
<label><input type="checkbox" name="checkbox2_3">2.2</label>
<label><input type="checkbox" name="checkbox2_4">2.3</label>
</div>
Вопрос вот в чем при выборе в группе общего чекбокса вся группа к которой относится общий чекбокс выделялась, а если из группы к примеру выделить один чекбокс то выделялось всего два чекбокса тот который я выбрал и общий чекбокс и не более. как можно такое реализовать?
AlexP
(Alex P.)
01.Октябрь.2020 14:15:23
#2
Наверно надо просто подписаться на событие изменения значения (.addEventListener('change', ...)
) общего чекбокса, и в зависимости от его состояния включать/выключать группу (.checked = true/false
).
И это аналогично, только может быть потребуется завести какой-то флаг устанавливаемый на время программного изменения чекбоксов, чтобы не запускать то, что выше, и наоборот.
Еще есть indeterminate
состояние, может лучше его ставить общему в этом случае. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox
s88s
(s88s)
01.Октябрь.2020 20:53:09
#3
По ссылке выше взял пример и не много переделал под себя
Сам пример тут
Насколько правильно я всё сделал?
HTML
<legend>Complete the recipe</legend>
<div>
<input type="checkbox" id="EnchTbl" name="EnchTbl">
<label for="EnchTbl">Enchantment table</label>
<span>
<input type="checkbox" id="book" name="ingredient" value="book">
<label for="book">Book</label>
<input type="checkbox" id="diamonds" name="ingredient" value="diamonds">
<label for="diamonds">Diamonds (x2)</label>
<input type="checkbox" id="obsidian" name="ingredient" value="obsidian">
<label for="obsidian">Obsidian (x4)</label>
</span>
</div>
JS
var overalll = document.querySelectorAll('input[id="EnchTbl"]');
var ingredients = document.querySelectorAll('span input');
for(var i = 0; i < ingredients.length; i++) {
ingredients[i].addEventListener('click', updateDisplay);
}
function updateDisplay() {
var checkedCount = 0;
for(var i = 0; i < ingredients.length; i++) {
if(ingredients[i].checked) {
checkedCount++;
}
}
if(checkedCount === 0) {
overalll[0].checked = false;
overalll[0].checked = false;
} else {
overalll[0].checked = false;
overalll[0].checked = true;
}
}
for(var i = 0; i < overalll.length; i++) {
overalll[i].addEventListener('click', updateDisplay1);
}
function updateDisplay1() {
var checkedCount1 = 0;
for(var i = 0; i < overalll.length; i++) {
if(overalll[i].checked) {
checkedCount1++;
}
}
if(checkedCount1 === 0) {
var checkedCount1 = 0;
for(var i = 0; i < ingredients.length; i++) {
ingredients[i].checked = false;
ingredients[i].checked = false;
}
} else {
var checkedCount1 = 0;
for(var i = 0; i < ingredients.length; i++) {
ingredients[i].checked = false;
ingredients[i].checked = true;
}
}
}
Мой пример тут
Sergebl
(Сергей)
02.Октябрь.2020 07:39:25
#4
долго тупил, пока не понял, что “Enchantment table” - это общий чекбокс для нижних
ну, работает так, как Вы и хотели, уж не знаю, правильно это или нет.
два вопроса.
а почему не используете indeterminate
состояние ?
пишете на “чистом” JS принципиально? Или просто обучение JS?
просто есть разные библиотеки, упрощающие, улучшающие написание кода на JS, например, широко используется jQuery
AlexP
(Alex P.)
02.Октябрь.2020 08:32:48
#5
Sergebl:
просто есть разные библиотеки, упрощающие, улучшающие написание кода на JS, например, широко используется jQuery
Так а тут что упрощать? querySelectorAll
и так есть уже )
Разве что цикл с addEventListener
. Но и там можно хотя бы взять forEach
. И filter
вместо второго цикла.
id
и так должен быть уникальным на странице. Можно #EnchTbl
И чтобы получить один элемент есть querySelector
.
s88s:
overalll
Лишняя l
+ странноватое имя, может лучше что-то типа parentCheckbox
и childrenCheckboxes
. И если нужно больше одной такой группы, то можно искать контейнеры (добавить какой-нибудь класс div
, …) и на нем вызывать querySelectorAll
.
Зачем по 2 раза?)
checkedCount1 = 0
лишний скопипастился два раза )
s88s:
updateDisplay1
Можно сразу анонимную функцию передавать в addEventListener
.
Он же один, зачем тут считать в цикле?
s88s
(s88s)
02.Октябрь.2020 10:05:47
#6
Из-за того что мне нужен чисто checked без каких либо промежуточных состояний и в одном стиле
А что плохого в JS?
Sergebl:
Или просто обучение JS?
Ну каждый учится чему то всегда и постоянно =)
Sergebl:
просто есть разные библиотеки, упрощающие, улучшающие написание кода на JS, например, широко используется jQuery
Ну зачем громоздить если можно и проще сделать?
Что касается id буду переделывать под себя с использованием this.id
overall добавил букву l пока переделывал так сказать под себя … в оконечном варианте буду все равно переменные менять как мне надо
JS привел к такому варианту
var overall = document.querySelectorAll('input[id="EnchTbl"]');
var ingredients = document.querySelectorAll('span input');
for(var i = 0; i < ingredients.length; i++) {
ingredients[i].addEventListener('click', updateDisplay);
}
function updateDisplay() {
var checkedCount = 0;
for(var i = 0; i < ingredients.length; i++) {
if(ingredients[i].checked) {
checkedCount++;
}
}
if(checkedCount === 0) {
overall[0].checked = false;
} else {
overall[0].checked = true;
}
}
overall[0].addEventListener('click', updateDisplay1);
function updateDisplay1() {
if(overall[0].checked){
for(var i = 0; i < ingredients.length; i++) {
ingredients[i].checked = true;
}
} else {
for(var i = 0; i < ingredients.length; i++) {
ingredients[i].checked = false;
}
}
}
AlexP
(Alex P.)
02.Октябрь.2020 10:39:06
#7
<legend>Complete the recipe</legend>
<div class="checkbox-group">
<input type="checkbox" data-role="parent" name="EnchTbl" id="EnchTbl">
<label for="EnchTbl">Enchantment table</label>
<br>
<span>
<input type="checkbox" id="book" name="ingredient" value="book">
<label for="book">Book</label>
<br>
<input type="checkbox" id="diamonds" name="ingredient" value="diamonds">
<label for="diamonds">Diamonds (x2)</label>
<br>
<input type="checkbox" id="obsidian" name="ingredient" value="obsidian">
<label for="obsidian">Obsidian (x4)</label>
</span>
</div>
function makeCheckboxGroup(container) {
const parentCheckbox = container.querySelector('input[type="checkbox"][data-role="parent"]');
const childrenCheckboxes = container.querySelectorAll('input[type="checkbox"]:not([data-role="parent"])');
childrenCheckboxes.forEach(chk => chk.addEventListener('click', () => {
const checkedCheckboxes = Array.from(childrenCheckboxes).filter(chk => chk.checked);
parentCheckbox.checked = checkedCheckboxes.length > 0;
}));
parentCheckbox.addEventListener('click', () => {
childrenCheckboxes.forEach(chk => {
chk.checked = parentCheckbox.checked;
});
});
}
document.querySelectorAll('.checkbox-group').forEach(makeCheckboxGroup);
https://jsfiddle.net/AlexP11223/o7bxL1v6/1/
2 лайка