Как правильно настроить действие кнопок во вновь сгенерированном divs?

#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. Вау! Я даже не знал, что таким образом мы можем находить братьев и сестер по родительскому элементу. Очень умное решение. Большое вам спасибо!