简体   繁体   中英

Close popup if clicking outside it

I have this code showing a button who displays a popup, i want the user to be able to close the popup by clicking outside of it when it's open.

So i want to asign the methode "Close()" to the event listner who detect outside click of the class '.popup', for now it's only an alert.

The problem is that when i click on the button, it's start already with the alert even if the popup didn't open yet, i want the event listner to start working once the popup in open, not before.

Any suggestion to take off repetitive code is also appreciated.

Thank you.

  /* Clean up the URL from '#popup1' in the end */ history.replaceState(null, null, ' '); /* Take off the popup from DOM before clicking in case user refresh*/ let id_popup = document.querySelector('#popup1'); let popup = id_popup.parentNode popup.removeChild(id_popup); /*Opening the popup*/ function Open() { popup.appendChild(id_popup); let class_popup = document.querySelector('.popup'); window.addEventListener('click', function (e) { if (!class_popup.contains(e.target)) { alert('You\\'re clicking outside the popup !') } }); } /*Closing the popup*/ function Close() { popup.removeChild(id_popup); history.replaceState(null, null, ' '); } 
  .button { font-size: 1em; padding: 10px; color: #000; border: 2px solid #06D85F; border-radius: 20px/50px; text-decoration: none; cursor: pointer; transition: all 0.3s ease-out; } .button:hover { background: #06D85F; } .overlay { position: fixed; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.7); transition: opacity 500ms; visibility: hidden; opacity: 0; } .overlay:target { visibility: visible; opacity: 1; } .popup { margin: 70px auto; padding: 20px; background: #fff; border-radius: 5px; width: 60%; position: relative; transition: all 5s ease-in-out; } .popup h2 { margin-top: 0; color: #333; font-family: Tahoma, Arial, sans-serif; } .popup .close { position: absolute; top: 20px; right: 30px; transition: all 200ms; font-size: 30px; font-weight: bold; text-decoration: none; color: #333; } .popup .close:hover { color: #06D85F; } .popup .content { max-height: 30%; overflow: auto; } @media screen and (max-width: 700px) { .box { width: 70%; } .popup { width: 70%; } } 
 <a class="button" href="#popup1" onclick="Open()">Let me Pop up</a> </div> <title>hi</title> <div id="popup1" class="overlay"> <div class="popup"> <h2>Title</h2> <a class="close" onclick="Close()" href="javascript://">&times;</a> <div class="content"> Text </div> </div> 

Try the following:

let allElems = document.querySelectorAll("body > div:not(#popup1)"); // Special query selector to get everything except .popup and its children

Array.from(allElems).forEach(elem => // Convert to iterable (with Array.from) and loop through all elements selected
  elem.addEventListener('click', function (e) { // Give them all the click event listener.
    alert('You\'re clicking outside the popup !') 
  });
}

The issue was mostly with your if statement, since the .contains was kind of messing things up. The alternative would be to convert both the elements to strings and compare them that way, but this method is better and also faster (slightly), since we don't need to check on every single click whether it's in the box or not.

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