#javascript #dom
#javascript #dom
Вопрос:
Я пытаюсь правильно настроить действие в моем проекте списка посещаемости. Я имею в виду две кнопки с кнопкой проверки класса и кнопкой времени (кнопка со значком X).
Это должно работать таким образом, когда я нажимаю, например, на check-button, тогда для этой кнопки будет установлен класс ‘selected’. На следующем шаге, если я нажму на times-button, то check-button должен быть отменен сам выбор, а класс ‘selected’ должен быть установлен на times-button и другим способом то же самое.
Чтобы продемонстрировать свою концепцию, я создал две простые кнопки со всем механизмом.
let checkBtn = null;
let timesBtn = null;
checkBtn = document.querySelector('.check-btn');
timesBtn = document.querySelector('.times-btn');
checkBtn.addEventListener('click', function(){
if(this.classList.contains('selected')===true){
this.classList.remove('selected');
if(timesBtn.classList.contains('selected')===false){
timesBtn.classList.add('selected');
}
}
else if(this.classList.contains('selected')===false){
this.classList.add('selected');
if(timesBtn.classList.contains('selected')===true){
timesBtn.classList.remove('selected');
}
}
});
timesBtn.addEventListener('click', function(){
if(this.classList.contains('selected')===true){
this.classList.remove('selected');
if(checkBtn.classList.contains('selected')===false){
checkBtn.classList.add('selected');
}
}
else if(this.classList.contains('selected')===false){
this.classList.add('selected');
if(checkBtn.classList.contains('selected')===true){
checkBtn.classList.remove('selected');
}
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.check-btn.selected{
background-color: red;
}
.times-btn.selected{
background-color: red;
}
</style>
</head>
<body>
<div class="container">
<div class="container-buttos">
<button class="check-btn">click 1</button>
<button class="times-btn">click 2</button>
</div>
</div>
</body>
<script src="main.js"></script>
</html>
В списке посещаемости я написал почти аналогичный алгоритм, но с элементами DOM
containerPerson.addEventListener('click', function(e){
//check button
if(e.target.closest('.check-button') !== null){
if(e.target.closest('.check-button').classList.contains('selected')===true){ //start
e.target.closest('.check-button').classList.remove('selected');
e.target.closest('.check-button').childNodes[0].classList.remove('selected');
if(e.target.closest('.times-button') !== null){
if((e.target.closest('.times-button').classList.contains('selected')===false)){
e.target.closest('.times-button').classList.add('selected');
e.target.closest('.times-button ').childNodes[0].classList.add('selected');
}
}
}
}
if(e.target.closest('.check-button') !== null){
if(e.target.closest('.check-button').classList.contains('selected')===false){ //start
e.target.closest('.check-button').classList.add('selected');
e.target.closest('.check-button').childNodes[0].classList.add('selected');
if(e.target.closest('.times-button') !== null){
if((e.target.closest('.times-button').classList.contains('selected')===true)){
e.target.closest('.times-button').classList.remove('selected');
e.target.closest('.times-button ').childNodes[0].classList.remove('selected');
}
}
}
}
//X button
if(e.target.closest('.times-button') !== null){
if(e.target.closest('.times-button').classList.contains('selected')===true){ //start
e.target.closest('.times-button').classList.remove('selected');
e.target.closest('.times-button').childNodes[0].classList.remove('selected');
if(e.target.closest('.check-button') !== null){
if((e.target.closest('.check-button').classList.contains('selected')===false)){
e.target.closest('.check-button').classList.add('selected');
e.target.closest('.check-button').childNodes[0].classList.add('selected');
}
}
}
}
if(e.target.closest('.times-button') !== null){ //if you haven't "e.target.closest('.times-button') !== null" then will show error: "cannot read property classList of null"
if(e.target.closest('.times-button').classList.contains('selected')===false){ //start
e.target.closest('.times-button').classList.add('selected');
e.target.closest('.times-button').childNodes[0].classList.add('selected');
if(e.target.closest('.check-button') !== null){
if((e.target.closest('.check-button').classList.contains('selected')===true)){
e.target.closest('.check-button').classList.remove('selected');
e.target.closest('.check-button').childNodes[0].classList.remove('selected');
}
}
}
}
});
и на этой фотографии результаты
Я не знаю, как решить эту проблему. Возможно, эта проблема вызвана множеством вложенных элементов, динамически генерируемых в документе? Может быть, кто-то знает лучший способ решить это?
Ответ №1:
Я объединил ваши отдельные блоки if в блоки if / else. Я думаю, что это исправило некоторые незначительные проблемы, которые были отделены от вашего вопроса.
Эта проблема, которую я вижу, является вашей внутренней проверкой на if(e.target.closest('/* OTHER BUTTON'S CLASS */') !== null)
На самом деле это никогда не будет правдой. В вашем упрощенном демонстрационном примере ваш код работает, потому что вы находите все кнопки соответствующего класса и удаляете из них классы. Это, очевидно, не будет работать в вашем проекте, поскольку каждая строка должна влиять только на кнопки в этой строке (я предполагаю). Вы пытаетесь найти аналог кнопки, на которую вы нажали. Таким образом, мы можем использовать некоторые вызовы querySelector для родительского элемента нажатой кнопки, чтобы найти братьев и удалить класс.
containerPerson.addEventListener('click', function(e){
//check button
if(e.target.closest('.check-button') !== null) {
e.target.closest('.check-button').classList.toggle('selected');
e.target.closest('.check-button').childNodes[0].classList.toggle('selected');
let sibs = e.target.closest('.check-button').parentNode.querySelector('.times-button');
if(sibs !== null){
if(sibs.classList.contains('selected')){
sibs.classList.remove('selected');
sibs.childNodes[0].classList.remove('selected');
} else {
//sibs.classList.add('selected');
//sibs.childNodes[0].classList.add('selected');
}
}
} else if (e.target.closest('.times-button') !== null) {
e.target.closest('.times-button').classList.toggle('selected');
e.target.closest('.times-button').childNodes[0].classList.toggle('selected');
let sibs = e.target.closest('.times-button').parentNode.querySelector('.check-button');
if(sibs !== null){
if(sibs.classList.contains('selected')){
sibs.classList.remove('selected');
sibs.childNodes[0].classList.remove('selected');
} else {
//sibs.classList.add('selected');
//sibs.childNodes[0].classList.add('selected');
}
}
}
});
Комментарии:
1. Вау! Я даже не знал, что таким образом мы можем находить братьев и сестер по родительскому элементу. Очень умное решение. Большое вам спасибо!