Необходимо остановить распространение, чтобы предотвратить закрытие меню при нажатии внутри выпадающего содержимого

#javascript

#javascript

Вопрос:

Мне нужно удерживать выпадающий список при щелчке внутри элементов выпадающего списка, для чего я добавил две строки с комментариями под комментарием к задаче в моем JS-файле ниже, и это неправильный путь, но он удерживает выпадающий список при нажатии на элементы выпадающего списка, но он прерывается одна из моих функций, то есть когда я делаю щелчок вне области выпадающего списка, выпадающий список сворачивается. Ошибка, возникающая на консоли, гласит «Uncaught TypeError» addEventListener не является функцией. Пожалуйста, поправьте меня, используя только чистый javascript.

  HTML - 
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/98.css">
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<title>Test</title>

</head>
 <body>

   <div class="window" style="width: 100%">
    <div class="title-bar">
     <div class="title-bar-text">Test Page</div>
      <div class="title-bar-controls">
        <button aria-label="Minimize"></button>
        <button aria-label="Maximize"></button>
        <button aria-label="Close"></button>
    </div>
   </div>

  <!-- Main menu -->
  <div class="window-body">
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_file')">File</button>
    <div class="dropdown-content" id="dd_file">
      <a href="#">Open</a>
      <a href="#">Close</a>
      <a href="#">Settings</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_edit')">Edit</button>
    <div class="dropdown-content" id="dd_edit">
      <a href="#">Cut</a>
      <a href="#">Copy</a>
      <a href="#">Paste</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_view')">View</button>
    <div class="dropdown-content" id="dd_view">
      <a href="#">Toggle CSS</a>
      <a href="#">Toggle Javascript</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_tools')">Tools</button>
    <div class="dropdown-content" id="dd_tools">
      <a href="#">Not Decided</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_favorite')">Favourties</button>
    <div class="dropdown-content" id="dd_favorite">
      <a href="#">Add New Favorite</a>
      <a href="#">Add this Page to Favorites</a>
      <a href="#">Show Favorites</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_help')">Help</button>
    <div class="dropdown-content" id="dd_help">
      <a
        href="#">Final</a>
    </div>
  </div>
  </div>
 </div>

</body>
</html>

  CSS - 
 .dropdown {
  position: relative;
  display: inline-block;
  }

 .dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
 }

.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}

JS- 
 function open_dropdown(element_id) {
 console.log('Opening Dropdown:', element_id)
 close_all_dropdowns()
 document.getElementById(element_id).style.display = 'block';
}

 // Close the dropdown if the user clicks outside of it
 function close_dropdown(element) {
 console.log('I am closing dropdown:', element)
 element.style.display = 'none'
 }

 // Close all dropdowns.
 function close_all_dropdowns() {
 var dropdowns = document.getElementsByClassName('dropdown-content')
 for (var i = 0; i < dropdowns.length; i  ) {
 close_dropdown(dropdowns[i]);
 }
}

// Close all dropdowns.
function close_all_dropdowns() {
var dropdowns = document.getElementsByClassName('dropdown-content')
for (var i = 0; i < dropdowns.length; i  ) {
close_dropdown(dropdowns[i]);
}
}

// Close all dropdowns when clicking outside.
window.onclick = function (e) {
 //TO-DO
//document.getElementsByClassName(' ').addEventListener('click', 
//function (e) {e.stopPropagation(); });
if (!e.target.matches('.dropbtn')) {
close_all_dropdowns()
}
}
 

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

1. По ошибке я оставил getElementsByClassName(‘ ‘) пустым, что находится чуть ниже TO-DO в js. Это был //document.getElementsByClassName(‘выпадающее содержимое’).addEventListener(‘click’, //function (e) {e.stopPropagation(); });

2. getElementsByClassName возвращает коллекцию, вам нужно выделить ее, чтобы добавить прослушиватель событий. Попробуйте getElementsByClassName(‘dropdown-content’)[0].addEventListener, чтобы избавиться от ошибки типа

3. @Sydney Y, большое вам спасибо, это сработало!

4. В этом была вся проблема? Думаю, я напишу ответ…

Ответ №1:

Добавьте прослушиватель событий ко всем вашим ссылкам. Я добавил это в нижнюю часть вашего JS.

 window.onload = (event) => {
  alert('page is fully loaded')
  var elements = document.querySelectorAll('.dropdown a')
  for (var i = 0, len = elements.length; i < len; i  ) {
    elements[i].onclick = function (e) {
      alert('clicked a link')
      e.stopPropagation()
    }
  }
}
 
  function open_dropdown(element_id) {
 close_all_dropdowns()
 document.getElementById(element_id).style.display = 'block';
}

 // Close the dropdown if the user clicks outside of it
 function close_dropdown(element) {
 element.style.display = 'none'
 }

 // Close all dropdowns.
 function close_all_dropdowns() {
 var dropdowns = document.getElementsByClassName('dropdown-content')
 for (var i = 0; i < dropdowns.length; i  ) {
 close_dropdown(dropdowns[i]);
 }
}


// Close all dropdowns when clicking outside.
window.onclick = function (e) {
 //TO-DO
//document.getElementsByClassName(' ').addEventListener('click', 
//function (e) {e.stopPropagation(); });

if (!e.target.matches('.dropbtn')) {
close_all_dropdowns()
}
}

window.onload = (event) => {

var elements = document.querySelectorAll('.dropdown a');
for(var i = 0, len = elements.length; i < len; i  ) {
    elements[i].onclick = function (e) {
        e.stopPropagation()
    }
}


}; 
  .dropdown {
  position: relative;
  display: inline-block;
  }

 .dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
 }

.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
} 
  <body>



  <!-- Main menu -->
  <div class="window-body">
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_file')">File</button>
    <div class="dropdown-content" id="dd_file">
      <a href="#">Open</a>
      <a href="#">Close</a>
      <a href="#">Settings</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_edit')">Edit</button>
    <div class="dropdown-content" id="dd_edit">
      <a href="#">Cut</a>
      <a href="#">Copy</a>
      <a href="#">Paste</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_view')">View</button>
    <div class="dropdown-content" id="dd_view">
      <a href="#">Toggle CSS</a>
      <a href="#">Toggle Javascript</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_tools')">Tools</button>
    <div class="dropdown-content" id="dd_tools">
      <a href="#">Not Decided</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_favorite')">Favourties</button>
    <div class="dropdown-content" id="dd_favorite">
      <a href="#">Add New Favorite</a>
      <a href="#">Add this Page to Favorites</a>
      <a href="#">Show Favorites</a>
    </div>
  </div>
  <div class="dropdown">
    <button class="dropbtn" onclick="open_dropdown('dd_help')">Help</button>
    <div class="dropdown-content" id="dd_help">
      <a
        href="#">Final</a>
    </div>
  </div>
  </div>
 </div>

</body> 

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

1. Просто будьте осторожны, если у вас есть другие ссылки на вашей странице, которые вы хотите вести себя нормально!

2. Я изменил его на «документ. querySelectorAll(‘.dropdown a’)». Так что это относится только к ссылкам в выпадающем списке.

3. @Aaron Tomlinson , я точно так же сделал. Также я попробовал — var elements = document.getElementsByClassName(‘выпадающее содержимое’); // Это тоже работает нормально

Ответ №2:

 document.getElementsByClassName('dropdown-content')
 

Этот метод возвращает коллекцию элементов HTML и addEventListener может быть применен только к одному элементу.

Чтобы добавить слушателя к каждому элементу в коллекции, вы должны перебирать их и применять к каждому из них.

Чтобы добавить слушателя только к одному элементу, вы можете просто добавить индекс:

 document.getElementsByClassName('dropdown-content')[0].addEventListener('click', function (e) {
  e.stopPropagation();
});