简体   繁体   中英

Need to stop propagation in order to prevent menu from closing when clicked inside dropdown content

I need to hold the the dropdown when a click is made inside the items of dropdown, for which I added two commented lines beneath TO-DO comment in my JS file below, and it is not the right way to go, but it does hold the dropdown when dropdown items are clicked but it breaks one of my functionality ie when i make a click outside area of dropdown the dropdown is minimized. The error produced at the console says "Uncaught TypeError" addEventListener is not a function. Please correct me by making use of pure javascript only.

 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()
}
}

Add an event listener to all your links. I added this to the bottom of your 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>

document.getElementsByClassName('dropdown-content')

This method returns a collection of HTML Elements, and addEventListener can only be applied to one element.

To add a listener to every element in the collection you have to loop through them and apply it to each one.

To add the listener to just one element you can just add an index:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM