javascriptfor-loopdialog

Simplest way to open/close multiple <dialog> pop-ups on the same page independently of one-another?


HTML

<dialog class="dialog">
<button class="close" autofocus>×</button>
<p>Some Content</p>
</dialog>
<button class="button open">Click Here</button>

<dialog class="dialog">
<button class="close" autofocus>×</button>
<p>Some Other Content</p>
</dialog>
<button class="button open">Click Here</button>

JS

const dialog = document.querySelector("dialog");
const showButton = document.querySelector("dialog + button");
const closeButton = document.querySelector("dialog button");
showButton.addEventListener("click", () => {
dialog.showModal();
});
closeButton.addEventListener("click", () => {
dialog.close();
});

Only the first dialog found on the page opens when clicked, but each respective dialog should open/close independently when interacted with.


Solution

  • Here's a solution using event delegation and where the buttons and modals have a common parent element, allowing them to find each other easily.

    //listen for any clicks in the parent element
    document.getElementById("parent").addEventListener(
      "click",
      e => {
        const theTarget = e.target;
        //is this the "click here" button?
        if (theTarget.closest("button").matches(".button")) {
          //find the closest parent modal-wrapper to the button, then find the modal within it to open
          const relevantModal = theTarget.closest("button").closest(".modal-wrapper").querySelector("dialog.dialog");
          relevantModal.showModal();
        }
        //is this the close button?
        else if (theTarget.closest("button").matches(".close")) {
          //find the closest parent modal-wrapper to the button, then find the modal within it to close
          const relevantModal = theTarget.closest(".modal-wrapper").querySelector("dialog.dialog");
          relevantModal.close();
        }
      }
    );
    <!-- overall parent for event delegation -->
    <div id="parent">
      <!-- modal/button parent container-->
      <div class="modal-wrapper">
        <dialog id="dialog-1" class="dialog">
          <button class="close" autofocus>×</button>
          <p>Thank you!</p>
        </dialog>
        <button class="button open">Click Here - Thanks</button>
      </div>
      <!-- modal/button parent container-->
      <div class="modal-wrapper">
        <dialog id="dialog-2" class="dialog">
          <button class="close" autofocus>×</button>
          <p>Good Bye!</p>
        </dialog>
        <button class="button open">Click Here - Bye</button>
      </div>
    </div>