Close modal on click outside of the modal JS on iO

2019-08-21 10:31发布

问题:

How do I make this code close a modal when user clicks outside of the modal window both on iOS and non-touch devices?

I know about some other similar topics here regarding window.onclick and touch devices, but I'm relatively new to JS and I don't know how to properly combine this function (for both platforms).

var modal = document.getElementById('myModal');
var btn = document.getElementById("myBtn");
var span = document.getElementsByClassName("close")[0];

btn.onclick = function() {
    modal.style.display = "block";
}
span.onclick = function() {
    modal.style.display = "none";
}
var closeModal = function(event) {
  if (event.target == modal) {
     modal.style.display = "none";
  }
}

window.addEventListener('click', closeModal);
window.addEventListener('touchend', closeModal);
.modal {
    display: none;
    position: fixed;
    overflow: hidden;
    left: 0;
    bottom: 0;
    width: 100%;
    height: auto;
    background-color: black;
    color: white; 
    font-size: 100%;
}
.close {
    color: white;
    float: right;
    font-size: 70%;
}
.close:hover, .close:focus {
    color: #000;
    text-decoration: none;
}
<div id="myModal" class="modal">

<span class="close">&times;</span>

<p>Some content here</p>

</div>

回答1:

Bind touchend and click event to the window element:

var modal = document.getElementById('myModal');
var btn = document.getElementById("myBtn");
var span = document.getElementsByClassName("close")[0];
var state = 'closed';

btn.onclick = function() {
    modal.style.display = "block";
    
    setTimeout(function() {
        state = 'open';
    }, 300);
}

span.onclick = function() {
    modal.style.display = "none";
}

var closeModal = function(event) {
    var closest = event.target.closest('#myModal');
  
    if ((null === closest || 0 < closest.length) && 'open' === state) {
        modal.style.display = "none";
        state = 'closed';
    }
}

window.addEventListener('click', closeModal);
window.addEventListener('touchend', closeModal);
.modal {
    display: none;
    position: fixed;
    overflow: hidden;
    left: 0;
    bottom: 0;
    width: 100%;
    height: auto;
    background-color: black;
    color: white; 
    font-size: 100%;
}
.close {
    color: white;
    float: right;
    font-size: 70%;
}
.close:hover, .close:focus {
    color: #000;
    text-decoration: none;
}
<button id="myBtn">open</button>

<div id="myModal" class="modal">

<span class="close">&times;</span>

<p>Some content here</p>

</div>

Edit: Updated code snippet.

On that solution i added simple a state to run close method only when state is open. With the closest method we search over all parent of the clicked element if there is a element that is equal to modal.

Only when closest is null or has a length of 0 we will close the modal.