Home > Net >  How do I activate more than one modalbox with js?
How do I activate more than one modalbox with js?

Time:09-26

I have a modal box that opens at the click of a button. Everything works fine. However I need another modal box on my page so I duplicated the first modal box but this doesn't open on click button.

What I would like to do is trigger the second modal with the same classes and the same js function in such a way that no more code is added. Is such a thing possible?

Alternatively, how could I activate the second modal by adding the least amount of code?

/* Modal Box Js */
const modal = document.querySelector(".modal");
const trigger = document.querySelector(".trigger");
const closeButton = document.querySelector(".close-button");

function toggleModal() {
    modal.classList.toggle("show-modal");
}

function windowOnClick(event) {
    if (event.target === modal) {
        toggleModal();
    }
}

trigger.addEventListener("click", toggleModal);
closeButton.addEventListener("click", toggleModal);
window.addEventListener("click", windowOnClick);
/**********
Modal Box Style
**********/
.trigger {cursor: pointer;}

.modal {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  opacity: 0;
  visibility: hidden;
  transform: scale(1.1);
  transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;
}

.modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: white;
  padding: 20px;
  width: 40rem;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
}

.msg-title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 12px;
}

.msg-text {
  font-size: 14px;
  margin-bottom: 6px;
  color: #5B616D;
}

.close-button {
  float: right;
  width: 1.5rem;
  line-height: 1.5rem;
  text-align: center;
  cursor: pointer;
  border-radius: 0.25rem;
  background-color: lightgray;
  align-self: end;
}

.close-button:hover {
  background-color: darkgray;
}

.show-modal {
  opacity: 1;
  visibility: visible;
  transform: scale(1.0);
  transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;
}
<!-- Modal Box 1 -->
<div >Modal Box 1</div>
<div >
  <div >
    <span >×</span>
    <span >Title 1</span>
    <span >
      “If you are distressed by anything external, the pain is not due to the thing itself, but to your estimate of it;       and this you have the power to revoke at any moment.”
      ― Marcus Aurelius.
    </span>
  </div>
</div>


<!-- Modal Box 2 -->
<div >Modal Box 2</div>
<div >
  <div >
    <span >×</span>
    <span >Title 2</span>
    <span >
      “If you are distressed by anything external, the pain is not due to the thing itself, but to your estimate of it;       and this you have the power to revoke at any moment.”
      ― Marcus Aurelius.
    </span>
  </div>
</div>

CodePudding user response:

Your main problem was because of not using NodeList.forEach to both assign clicks to the desired elements and for not looping the modals to toggle the "open" class.

Here's a variant on your code that uses the aforementioned and the better tool for the job, and that's by using data-* attribute to reference the desired modal to toggle, namely data-modal, which can be assigned to any button or element, and accepts the ID selector of the modal to target. So you're not limited to have a specific HTML structure or having to use only one button element-per-modal.

Another issue that's fixed is: never use negative transform in CSS to center your modal content. Use instead margin: auto inside a flex parent. Also, add some scrollbars! (See my comments in CSS)

// DOM helpers:

const el = (sel, par) => (par || document).querySelector(sel);
const els = (sel, par) => (par || document).querySelectorAll(sel);

// Task: Modal Box

const elsModals = els(".modal");
const elsModalBtns = els("[data-modal]");

const modalToggle = (id) => {
  el(id).classList.toggle("show-modal");
};

const modalsClose = (evt) => {
  // Do nothing, click was inside a modal or modal button:
  if (evt.target.closest(".modal-content") || evt.target.closest("[data-modal]")) return;
  // Else, close all modals:
  elsModals.forEach(elMod => elMod.classList.remove("show-modal"));
}

elsModalBtns.forEach(elBtn => {
  elBtn.addEventListener("click", () => modalToggle(elBtn.dataset.modal));
});

addEventListener("click", modalsClose);
/*
 * Modal Box
 */

.trigger {
  cursor: pointer;
}

.modal {
  position: fixed;
  display: flex;
  /* use flex!!! */
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  opacity: 0;
  visibility: hidden;
  transform: scale(1.1);
  transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;
}

.modal-content {
  margin: auto; /* center inside flex parent */
  overflow: auto; /* scroll inner content if needed */
  max-height: 70vh; /* make it scroll if exceeds this height */
  background-color: white;
  padding: 20px;
  width: 40rem;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
}

.msg-title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 12px;
}

.msg-text {
  font-size: 14px;
  margin-bottom: 6px;
  color: #5B616D;
}

.close-button {
  text-align: center;
  cursor: pointer;
  border-radius: 0.25rem;
  background-color: lightgray;
  align-self: end;
  border: 0;
  font-size: 1.2rem;
}

.close-button:hover {
  background-color: darkgray;
}

.show-modal {
  opacity: 1;
  visibility: visible;
  transform: scale(1.0);
  transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;
}
<div  data-modal="#modal-lorem">Modal Box 1</div>
<div  data-modal="#modal-aurelius">Modal Box 2</div>

<div id="modal-lorem" >
  <div >
    <button type="button"  data-modal="#modal-lorem">×</button>
    <span >Title 1</span>
    <span >
      “Dolor sit amet, consectetur adipisicing elit. Numquam earum debitis architecto, temporibus quod maxime velit, rem ex nam eum ea illum, assumenda nesciunt consectetur quaerat. Accusamus reprehenderit, distinctio et!
”
      ― Lorem ipsum.
    </span>
  </div>
</div>


<div id="modal-aurelius" >
  <div >
    <button type="button"  data-modal="#modal-aurelius">×</button>
    <span >Title 2</span>
    <span >
      “he pain is not due to the thing itself, but to your estimate of it;       and this you have the power to revoke at any moment.”
      ― Marcus Aurelius.
    </span>
  </div>
</div>

  • Related