1

The code should open a modal window after a click on the button but the first time you want to open it, it requires two clicks on the button to open it. I encoutered this problem after copying some code from W3Schools and modifying it so it fits inside my JS file.

HTML

<h2>Modal Example</h2>

<!-- Trigger/Open The Modal -->
<button id="myBtn" onclick="modalFunction()">Open Modal</button>

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

  <!-- Modal content -->
  <div class="modal-content">
    <span class="close">×</span>
    <p>Some text in the Modal..</p>
  </div>

</div>

Javasript

function modalFunction() {
// Get the modal
var modal = document.getElementById('myModal');

// Get the button that opens the modal
var btn = document.getElementById("myBtn");

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

// When the user clicks the button, open the modal 
btn.onclick = function() {
    modal.style.display = "block";
}

// 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";
    }
}
}

1 Answers1

3

If you move your event load handlers outside the function it will work as expected.

Here I simply removed the function and the inline script handler.

I also change the onlick to the newer addEventListener, and here's a good answer explaining their differences: addEventListener vs onclick

Note that the script needs to be runned at page load, not before

// Make sure DOM is loaded before access any of its elements
window.addEventListener('load', function() {

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

  // Get the button that opens the modal
  var btn = document.getElementById("myBtn");

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

  // When the user clicks the button, open the modal 
  btn.addEventListener('click', function(ev) {
    mdl.style.display = "block";
    // Prevent event bubbling (so in this case the window listener
    // won't catch the event and simply close it immediately)
    ev.stopPropagation();
  });

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

  // When the user clicks anywhere outside of the modal, close it
  window.addEventListener('click', function(ev) {
    if (!mdl.contains(ev.target)) {
      mdl.style.display = "none";
    }
  });
});
.modal {
  position: relative;
  display: none;
  border: 1px solid black;
}
.close {
  position: absolute;
  display: block;
  color: white;
  background: red;
  padding: 3px 5px;
  right: 0;
  top: 0;
}
<h2>Modal Example</h2>

<!-- Trigger/Open The Modal -->
<button id="myBtn">Open Modal</button>

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

  <!-- Modal content -->
  <div class="modal-content">
    <span class="close"> X </span>
    <p>Some text in the Modal..</p>
  </div>

</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • If I remove the function it doesn't appear at all, and if i try the code in a jsfiddle it works but in my sublime it doesn't – Martijn Hermsen Nov 30 '16 at 19:35
  • @MartijnHermsen As the above code works here at SO, you must have missed something. Do note that your script needs to run _after_ page loaded, either added last in your page or using the body onload handler – Asons Nov 30 '16 at 19:55
  • @MartijnHermsen Updated my answer with an event listener for page load – Asons Nov 30 '16 at 19:58
  • thanks now it works. I just started with javascript so I don't know a lot yet – Martijn Hermsen Nov 30 '16 at 20:05
  • @MartijnHermsen We all started with not knowing a lot :) – Asons Nov 30 '16 at 20:07