skip to Main Content

My goal with this example is for the blue bloxes .box to close whenever you click outside of them, even if you click on the scrollbars.

My problem, and my question, is that this example works, but not in my full project, once in my full project I have to call/include the <script src=""> inside the <head> before the entire <html> page is loaded. What other alternatives do I have, perhaps using addeventlistener for the scroll of each <div>, without being forced to call the <script> at the end of each page?

note: Keep in mind that in my full project, I use the classes of each <div> instead of using IDs.

function closeBoxes() {

  if(event.target.closest(".box") === null){
    let boxes = document.querySelectorAll(".box");
    boxes.forEach(e =>{ e.style.display = "none"; });
  }

}

let alldiv = document.querySelectorAll("div");
alldiv.forEach(e =>{ e.onscroll = (event) => { closeBoxes(); }; });

window.addEventListener("click", function(){ closeBoxes(); });
.main { 
  background-color: #e6e6e6; 
  border: 1px solid black;
  width: 350px; 
  height: 170px; 
  padding: 10px;
  text-align: center;
  box-sizing: border-box;
  overflow: auto;
}

.container { 
  background-color: #ffccff; 
  border: 1px solid magenta;
  width: 200px; 
  height: 220px; 
  padding: 10px;
  margin-top: 10px;
  overflow: auto;
}

.child { 
  background-color: #ffffcc; 
  border: 1px solid yellow;
  width: 150px; 
  height: 270px; 
  padding: 10px;
}

.box { 
  background-color: #ccd8ff; 
  border: 1px solid blue;
  width: 100px; 
  height: 20px;
  padding: 10px;
  margin-bottom: 10px;
  display: block;
  overflow: auto;
}
<div class="main">
  click outside the blue boxes to close them
    <div class="container">
      <div class="child">
        <div class="box">BOX-A1<br>BOX-A2<br>BOX-A3<br>BOX-A4<br>BOX-A5</div>
        <div class="box">BOX-B1<br>BOX-B2<br>BOX-B3<br>BOX-B4<br>BOX-B5</div>
      </div>
  </div>
</div>

2

Answers


  1. Chosen as BEST ANSWER

    The solution is add an window.addEventListener("scroll",function(){},true); with useCapture parameter = true;

    function closeBoxes() {
    
      if(event.target.closest){ console.log("entrou"); }
    
      // EDITED - `event.target.closest` can't be false, prevents >> TypeError: evt.target.closest is not a function
      if(event.target.closest && event.target.closest(".box") === null){
        let boxes = document.querySelectorAll(".box");
        boxes.forEach(e =>{ e.style.display = "none"; });
      }
    
    }
    
    window.addEventListener("click", function(){ closeBoxes(); });
    
    window.addEventListener("scroll", function(){ closeBoxes(); }, true); // NEW - with `useCapture` parameter = true;
    

    "With the addEventListener() method you can specify the propagation type by using the "useCapture" parameter: addEventListener(event, function, useCapture);
    The default value is false, which will use the bubbling propagation, when the value is set to true, the event uses the capturing propagation."

    font: https://www.w3schools.com/js/js_htmldom_eventlistener.asp


  2. The script tag had an attribute called defer. This will allow us to place the script on the head without having an issue. For your reference.
    https://www.w3schools.com/tags/att_script_defer.asp

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search