Issue opening and closing of JavaScript generated modal

The following code is an attempt to create a modal system that allows for multiple images to pop up on click without reloading the page . I have it working, but it is not exactly how I want it.

Problem #1: It takes a double click on the image to open the modal.

Problem #2: The only way to close the modal is to click the ‘X’. I would like to be able to click anywhere outside the modal to close it.

Problem #3: I would really like to fade the background when the modal is open.

The first two problems are really annoying. The third one would be nice.

Thanks for any help you can give.

Here is the code:

<!DOCTYPE html>
<html>
    <meta name="viewport" content="width=device-width, initial-scale=0.86, maximum-scale=3.0, minimum-scale=0.86">
    <style>
        .popImage {
            border-radius: 5px;
            cursor: pointer;
            transition: 0.3s;
        }

        .popImage:hover {opacity: 0.7;}

        /* The Modal (background) */
        .popModal {
            display: none; /* Hidden by default */
            position: fixed; /* Stay in place */
            z-index: 1; /* Sit on top */
            padding-top: 5px; /* Location of the box */
            padding-bottom: 5px; /* Location of the box */
            padding-right: 5px; /* Location of the box */
            padding-left: 5px; /* Location of the box */
            left: 200px;
            top: 100px;
            width: 300px; /* Full width */
            overflow: hidden; /* Enable scroll if needed */
            background-color: rgb(198, 197, 197); /* Fallback color */
            background-color: rgba(198, 197, 197, 0.9); /* Black w/ opacity */
        }

        /* popModal Content (image) */
        .popModal-content {
            margin: auto;
            display: block;
            width: 80%;
            height: 80%; /* Full height */
            max-width: 350px;
        }
        .popcentered {
            position: fixed;
            top: 50%;
            left: 50%;
            /* bring your own prefixes */
            transform: translate(-50%, -50%);
        }
        /* Caption of popModal Image */
        #caption {
            margin: auto;
            display: block;
            width: 80%;
            max-width: 350px;
            text-align: center;
            color: #ccc;
            padding: 10px 0;
            height: 150px;
        }

        /* Add Animation */
        .popModal-content, #caption {
            -webkit-animation-name: zoom;
            -webkit-animation-duration: 0.6s;
            animation-name: zoom;
            animation-duration: 0.6s;
        }

        @-webkit-keyframes zoom {
            from {-webkit-transform:scale(0)}
            to {-webkit-transform:scale(1)}
        }

        @keyframes zoom {
            from {transform:scale(0)}
            to {transform:scale(1)}
        }

        /* The Close Button */
        .close {
            position: absolute;
            top: 2px;
            right: 10px;
            color: #f1f1f1;
            font-size: 40px;
            font-weight: bold;
            transition: 0.3s;
        }

        .close:hover,
        .close:focus {
            color: #aaa;
            text-decoration: none;
            cursor: pointer;
        }

        /* 100% Image Width on Smaller Screens */
        @media only screen and (max-width: 700px){
            .popModal-content {
                width: 100%;
            }
        }
    </style>
</head>
<body>

<div class="popModal popcentered"  id="imgPopModal"  aria-hidden="true">
    <div class="modal-md" role="document" style="color:black;justify-content: center;">
        <div class="modal-content">
            <div class="modal-body"  id="screenSet18b" style="background-color: white; color: black:justify-content: center;padding-top:5px">
                    <span class="close" style="color: black;" data-dismiss="imgPopModal" >&times;</span>
                    <img class="popModal-content" id="img01" style="width: 250px">
                    <div id="caption"></div>
            </div>
        </div>
    </div>
</div>



<h2>Image Modal Test</h2>
<div style="align-content: center">
<img id="128650" class="popImage" src="images/available/128650_90.jpg" alt='<a href="https://ziggysdev.com/index.php">6 in. x 6 in. Black Trifit Steel Corner Pergola Bracket</a>' style="width:100px;max-width:300px" onClick="ShowModalImage(128650)">
<img id="128600" class="popImage" src="images/available/128600.JPG" alt="4 in. x 4 in. Black Unifit Steel Post Base and Wall Mount Pergola Bracket" style="width:100px;max-width:300px" onClick="ShowModalImage(128600)">
<img id="111105" class="popImage" src="images/available/111105_81.jpg" alt="10.1 oz. DYNAFLEX White Silicone Sealant" style="width:100px;max-width:300px" onClick="ShowModalImage(111105)">
<img id="111022" class="popImage" src="images/available/111022_81.jpg" alt="Frost King Poly Foam Caulk Saver 3/8inx20" style="width:100px;max-width:300px" onClick="ShowModalImage(111022)">
</div>

<script>
    function ShowModalImage(imageID) {

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

        // Get the image and insert it inside the modal - use its "alt" text as a caption
        var img = document.getElementById(imageID);
        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("close")[0];

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

</body>
</html>


So I think the double click is coming from the fact that you are registering an img.onclick.

If you change it to this in the js, it should open without double-clicking.

Old

img.onclick = function () {
            modal.style.display = "block";
            modalImg.src = this.src;
            captionText.innerHTML = this.alt;
        }

New

            modal.style.display = "block";
            modalImg.src = this.src;
            captionText.innerHTML = this.alt;

Would you mind if I refactored this code and used it on my YouTube channel as an example of adding features to a code?

Thank you for the reply.
First I have to say that I am not highly proficient in JavaScript.
When I made the change you suggested the single click works but the image and caption are lost. Inspecting the code console gives:

undefined:1 Failed to load resource: the server responded with a status of 404 (Not Found)

I get the modal display with a broken image symbol and “undefined” for the caption.

Thanks again for the help.

Your solution was almost correct. The following change made it work:

           imgPopModal.style.display = "block";
            modalImg.src = img.src;
            captionText.innerHTML = img.alt;

The solution was changing the this.src to img.src and this.alt to image.alt.

Now all I have to do is figure out how to close when clicking anywhere on the screen.

That is usually done by adding a click event listener to the <body>. In there, you first check if the user clicked on the modal or somewhere else.

You’ll likely run into issues when you try something like

if (e.target.id === 'imgPopModal') { /* then don't close modal */ }

because that would only be true if the user clicks on that exact div, not if he clicks maybe on a span inside that div (read about event propagation and event bubbling if you want to learn more).

So what you’ll need is something like e.target.closest('#imgPopModal'). That’ll walk up the DOM tree and search all ancestors of the click target for an id of #imgPopModal.

Thanks for the reply.
I found that when I clicked anywhere inside the modal that the target never equaled ‘imgPopModal’ but rather elements in the modal such as ‘img’ or ‘content’ etc. I also found that when I click outside of the modal the target was blank. So I found that the following code works but I am not sure if this is a good way to do it. Like I said earlier I am not a great JavaScript person so right now it more by trial and error.
If you could take a moment to review the code I would appreciate it.
Thanks.

`
function ShowModalImage(imageID) {

        // Get the popModal
        var popUpModal = document.getElementById("imgPopModal");

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

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

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

    }
</script>
<script>
    window.onclick = function(event) {
         if (event.target.id !== '') {
        }else{
             imgPopModal.style.display = "none";
        }
    }
</script>`

The target wasn’t blank, it just had no id. If you were logging event.target.id, and your click event is attached to the window, you logged an empty string.

But you’re right that your current code isn’t ideal. All your modals have a class of .popImage, so when someone clicks on the body, you only have to check if that class is somewhere in the ancestors of the click target:

    window.onclick = function(event) {
         if (event.target.closest('.popImage')) {
             imgPopModal.style.display = "block";
        } else {
             imgPopModal.style.display = "none";
        }
    }

By the way you have an avalanche of syntax errors in your HTML, which might lead to unexpected behaviour when JS scans your DOM tree. Here’s a good markup online validator, just copy/paste your code in: The W3C Markup Validation Service

Thank you. That did the job and I really appreciate the help. Have a great day.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.