0
votes

The Issue
I'm looking to implement a flexible javascript solution to opening and closing multiple modal windows on the same page.

I have found way to open multiple modal windows in such a manner, but I can't for the life of me figure out how to close them by the click of a button or by clicking outside of the modal window itself.

Here is my javascript code:

var openModal = document.getElementsByClassName("open-modal");

for (var i = 0; i < openModal.length; i++) {
    var thisOpenModal = openModal[i];

    thisOpenModal.addEventListener("click", function() {
        var modal = document.getElementById(this.dataset.modal);
        modal.style.display = "block";

    }, false);
}

(I didn't write this code myself, it's an edited copy of "pgk's" answer over on this page: Opening multiple modal boxes on one page)

I trigger the modal windows by adding the 'open-modal' class to my "buttons" and I use 'data-modal' in relation to the id's of the modal windows:

<div class="featurette-wrap featurette--anchor open-modal" data-modal="modal-microsoft-account">
   Opprett konto
</div>


The button above triggers the modal window with the id of modal-microsoft-account:

<div class="modal" id="modal-microsoft-account">
    Microsoft-konto
</div>


So my question is:
How can I implement a way to close a modal window once it's opened?


I've tried doing this, but I can't get it to work (from W3schools):

// When the user clicks on <span> (x), close the modal
    closeModal.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";
        }
    }
2

2 Answers

1
votes

It's better to use event listeners to track actions on elements as I've done below;

also, making use of the setAttribute function when setting styles with Javascript ensures that every other style assigned to that element is overridden and the style you are setting always applies (except in cases where another style is set to be important)

var openModal = document.getElementsByClassName("open-modal");

for (var i = 0; i < openModal.length; i++) {
  var thisOpenModal = openModal[i];
  var targetModal = thisOpenModal.getAttribute('data-modal')
  //get the id of the modal to open based on thisOpenModal
  var thisTargetModal = document.getElementById(targetModal)
  //get element

  thisOpenModal.addEventListener("click", function(event) {
    thisTargetModal.setAttribute('style', "display:block;")
    //code to open modal on click of div with id=""
  }, false);


  // When the user clicks on <span> (x), close the modal
  var closeModal = document.querySelector('#' + thisTargetModal.id, "span");

  //code to listen to click event and change block style attribute to none on click
  closeModal.addEventListener("click", function() {
    thisTargetModal.setAttribute('style', "display:none;")
  }, false)


  // When the user clicks anywhere on the modal div, close it
  window.addEventListener("click", function(event) {
    //code to listen to click event on window and change block style attribute to none
    if (event.target == targetModal) {
      thisTargetModal.setAttribute('style', "display:none;")
    }
  })

}
<div class="featurette-wrap featurette--anchor open-modal" data-modal="modal-microsoft-account">
  Opprett konto
</div>

<div class="modal" id="modal-microsoft-account" style="display:none;">
  <p>Microsoft-konto </p>
  <p>
    <span id="close-modal">
    x
</span>
  </p>
</div>
1
votes

So I actually ended up finding a solution that did exactly what I was looking for over at W3Schools forum: http://w3schools.invisionzone.com/topic/55976-multiple-modal-boxes-on-webpage/

This did the trick 🙌:

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

// Get the button that opens the modal
var openModal = document.getElementsByClassName("open-modal");

// Get the <span> element that closes the modal
var closeModal = document.getElementsByClassName("modal__close");

// When the user clicks the button, open the modal
function setDataIndex() {
    for (i = 0; i < openModal.length; i++) {
        openModal[i].setAttribute('data-index', i);
        modal[i].setAttribute('data-index', i);
        closeModal[i].setAttribute('data-index', i);
    }
}

for (i = 0; i < openModal.length; i++) {
    openModal[i].onclick = function() {
        var ElementIndex = this.getAttribute('data-index');
        modal[ElementIndex].style.display = "block";
    };

    // When the user clicks on <span> (x), close the modal
    closeModal[i].onclick = function() {
        var ElementIndex = this.getAttribute('data-index');
        modal[ElementIndex].style.display = "none";
    };

}

window.onload = function() {
    setDataIndex();
};

window.onclick = function(event) {
    if (event.target === modal[event.target.getAttribute('data-index')]) {
        modal[event.target.getAttribute('data-index')].style.display = "none";
    }
};