classList.toggle() работает только один раз

#javascript #html #css

Вопрос:

Я пытаюсь реализовать другое всплывающее окно, когда я нажимаю на разные разделы. Вот пример:

 <div class="column" onclick="togglePopup('popup', 2)">Residential cleaning</div> <!--Function used here. -->
                        <div id="overlay">
                            <div class="popup">
                                <div class="popup_content">
                                    <div class="close_btn" onclick="closePopup('popup',2)">amp;times;</div>
                                    <h1>Some heading</h1>
                                    <p>SOME TEXT</p>
                                    <img src="assets/some_image.jpg" alt="image" width="249">
                                </div>
                            </div> <!--END of the popup window -->
                        </div>
 

Когда я нажимаю на столбец div класса, я должен видеть всплывающий div, однако он работает только с самым первым. Вот JavaScript:

 function togglePopup(popup_class, div_num){
    overlay.style.display="flex";
    let all_divs = document.getElementsByClassName(popup_class);
    let my_div = all_divs[div_num-1];
    my_div.classList.toggle("active");
    console.log(my_div)
    
}

function closePopup(popup_class, div_num){
    overlay.style.display="none";
    let all_divs = document.getElementsByClassName(popup_class);
    let my_div = all_divs[div_num-1];
    my_div.classList.toggle("active");
    console.log(my_div)
}
 

Функция сохраняет все всплывающие окна классов во всплывающем окне let all_divs, затем использует параметр div_num для выбора определенного div и, наконец, переключает класс «активный» (CSS будет показан ниже). Но, как я уже сказал, это работает только один раз. Кстати, наложение идентификатора изначально скрыто.
CSS:

 .popup.active .popup_content {
    transition:all 300ms ease-in-out;
    transform:translate(-50%,-50%) scale(1);
}

#overlay  {
    position:fixed;
    top:0px;
    left:0px;
    width:100%;
    height:100%;
    background-color:rgba(0,0,0,0.7);
    z-index:1;
    display:none;
}
 

Я действительно не знаю, почему это происходит, это работает как задумано только с первым элементом списка «all_divs». Есть ли способ обойти это? Я уже перепробовал много вещей и понял, что это работает только с первым элементом списка. Я не включил первый div в код (тот, который работает), потому что это то же самое, за исключением того, что вместо 1 в onclick=»togglePopup(«всплывающее окно», 1)» у него есть 2.

Комментарии:

1. Попробуйте измениться my_div.classList.toggle("active"); my_div.classList.remove('active'); внутрь closePopup .

2. Похоже, что он может запускаться дважды на одном и том же элементе с помощью togglePopup и closePopup.

Ответ №1:

Вы пытаетесь получить доступ к коллекции HTMLC по индексу, которого не существует. например

 let all_divs = document.getElementsByClassName('popup');
let my_div = all_divs[2]; // undefined
 

Вместо этого вы должны добавить данные в кнопку «Открыть», чтобы явно описать, какое всплывающее окно оно должно открыть по своему уникальному идентификатору.

Кроме того, вы должны:

  • используйте querySelectorAll addEventListener для каждой из соответствующих кнопок
  • используйте html-кнопки вместо divs
 const openBtns = document.querySelectorAll('.open_btn')
const closeBtns = document.querySelectorAll('.close_btn')


openBtns.forEach(openBtn => openBtn.addEventListener('click', (e) => {
  const popupIdToOpen = e.currentTarget.dataset.popup;
  const popupToOpen = document.querySelector(`#${popupIdToOpen}`)
  if (popupToOpen) {
    popupToOpen.classList.add('active')
  }
}))

closeBtns.forEach(closeBtn => closeBtn.addEventListener('click', (e) => {
  const popupToClose = e.currentTarget.closest(".overlay")
  if (popupToClose) {
    popupToClose.classList.remove('active')
  }
})) 
 .overlay {
  color: white;
  position: fixed;
  top: 0;
  background-color: #000;
  display: none;
}

.active {
  display: block;
} 
 <button class="open_btn" data-popup="popup1">Popup 1</button>
<div class="overlay" id="popup1">
  <button class="close_btn">amp;times;</button >
  <h1>Popup 1 heading</h1>
  <p>Popup 1 Content</p>
</div>

<button class="open_btn" data-popup="popup2">Popup 2</button>
<div class="overlay" id="popup2">
  <button class="close_btn">amp;times;</button >
  <h1>Popup 2 heading</h1>
  <p>Popup 2 Content</p>
</div>

<button class="open_btn" data-popup="popup3">Popup 3</button>
<div class="overlay" id="popup3">
  <button class="close_btn">amp;times;</button >
  <h1>Popup 3 heading</h1>
  <p>Popup 3 Content</p>
</div>