Joss
Joss

Reputation: 197

Modal not closing upon button and/or window click events

I've got a close button next to a modal that does not work and I'm struggling to figure it out (despite all the resources available in other tickets). The modal also does not close when I click anywhere outside of the modal.

// Get the modal
var modal = document.getElementById("myModal");

// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("myImg");
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
img.onclick = function() {
  modal.style.display = "block";
  modalImg.src = this.src;
  captionText.innerHTML = this.alt;
}

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("closebtn")[0];

// When the user clicks on <span> (x), close the modal
span.onclick = function() {
  modal.style.display = "none";
}

// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
}
<div class="card-header">
  <!-- Trigger the Modal -->
  <img id="myImg" src="pathtomyimage" alt="mycaptiontext" style="width:100%;max-width:600px">

  <!-- The Modal -->
  <div id="myModal" class="modal">

    <!-- The Close Button -->
    <span class="closebtn">&times;</span>

    <!-- Modal Content (The Image) -->
    <img class="modal-content" id="img01">

    <!-- Modal Caption (Image Text) -->
    <div id="caption"></div>
  </div>
</div>

Upvotes: 1

Views: 85

Answers (1)

traktor
traktor

Reputation: 19301

Two changes to get the posted code working:

  1. Stop event propagation in the click handler that opens the modal.

    • If not stopped, the click that opens the modal reaches the window click handler and closes the modal immediately after opening it.
  2. Address the problem that a typo in the window click handler is checking (event.target == modal) instead of (event.target != modal), yet simply testing (event.target != modal) returns a false positive if the user clicks an element within the modal element itself .

    The code snippet solves the combined problem using element.closest to detect if event.target has modal class or has an ancestral element of modal class.

"use strict";
// Get the modal
var modal = document.getElementById("myModal");

// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("myImg");
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
img.onclick = function( event){
    modal.style.display = "block";
    modalImg.src = this.src;
    captionText.innerHTML = this.alt;
    event.stopPropagation();  // prevent event reaching window.onclick
    }

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("closebtn")[0];

// When the user clicks on <span> (x), close the modal
span.onclick = function(){
    modal.style.display = "none";
}

/*** updated window.onclick hander ***/
// When the user clicks anywhere outside of the modal, close it 
window.onclick = function(event){
    let modalContainer = event.target.closest(".modal");
    if( modalContainer === null && modal.style.display == "block") {
       modal.style.display = "none";
    }
}
img {
    min-height: 4rem;
    min-width: 4rem;
    border: medium solid blue;
}
.closebtn { 
    font-size:200%;
    color:white;
    background-color: red;
}
.modal {
    background-color: yellow;
    display: none;
}
<div class="card-header">
    <!-- Trigger the Modal -->
    <img id="myImg" src="pathtomyimage" alt="mycaptiontext" style="width:100%;max-width:600px">
    
    <!-- The Modal -->
    <div id="myModal" class="modal">
    
        <!-- The Close Button -->
        <span class="closebtn">&times;</span>
    
        <!-- Modal Content (The Image) -->
        <img class="modal-content" id="img01">
    
        <!-- Modal Caption (Image Text) -->
        <div id="caption"></div>
    </div>
</div>

Upvotes: 1

Related Questions