Leon
Leon

Reputation: 1508

How to close an open HTML dialog box with JavaScript

I have multiple HTML dialog elements in a table. The JavaScript openDialog and closeDialog functions are working, but I'm unable to get the closeDialogFromOutside function working.

let openDialog = (event) => {
  if (event.target.className === "open-dialog-button") {
    const el_dialog = event.target.closest("td").querySelector("dialog");
    el_dialog.showModal();
  }
};

let closeDialog = (event) => {
  if (event.target.className === "close-dialog-button") {
    const el_dialog = event.target.closest("dialog");
    el_dialog.close();
  }
};

let closeDialogFromOutside = (event) => {
  const db_nodes = document.getElementsByClassName("dialog-box");
  let el_open_dialog;

  for (let i = 0; i < db_nodes.length; i++) {
    if (db_nodes[i].open) {
      el_open_dialog = db_nodes[i];
    }
  }

  if (typeof el_open_dialog !== "undefined") {
    let rect = el_open_dialog.getBoundingClientRect();
    if (
      event.clientY < rect.top ||
      event.clientY > rect.bottom ||
      event.clientX < rect.left ||
      event.clientX > rect.right
    ) {
      console.log("help!");
      el_open_dialog.close();
    }
  }
};

document.addEventListener("click", function() {
  openDialog(event);
  closeDialog(event);
  closeDialogFromOutside(event);
});
<table>
  <tr>
    <td>
      <dialog class="dialog-box">
        <button class="close-dialog-button">close #1</button> Table cell dialog #1
      </dialog>
      <button class="open-dialog-button">Open dialog box #1</button>
    </td>
  </tr>
  <tr>
    <td>
      <dialog class="dialog-box">
        <button class="close-dialog-button">close #2</button> Table cell dialog #2
      </dialog>
      <button class="open-dialog-button">Open dialog box #2</button>
    </td>
  </tr>
  <tr>
    <td>
      <dialog class="dialog-box">
        <button class="close-dialog-button">close #3</button> Table cell dialog #3
      </dialog>
      <button class="open-dialog-button">Open dialog box #3</button>
    </td>
  </tr>
</table>

Upvotes: 0

Views: 85

Answers (1)

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48600

You can return a boolean value of true or false to short-circuit the click function.

document.addEventListener('click', function(event) {
  if (openDialog(event)) return;  // exit early
  if (closeDialog(event)) return; // exit early
  closeDialogFromOutside(event);
});

If you open or close a modal via a button, do not attempt to close an open modal from the outside.

const openDialog = (event) => {
  if (event.target.classList.contains('open-dialog-button')) {
    const showButton = event.target;
    const tableCell = showButton.closest('td');
    const dialog = tableCell.querySelector('.dialog-box');
    dialog.showModal();
    return true;
  }
  return false;
};

let closeDialog = (event) => {
  if (event.target.classList.contains('close-dialog-button')) {
    const closeButton = event.target;
    const dialog = closeButton.closest('.dialog-box');
    dialog.close();
    return true;
  }
  return false;
};

let closeDialogFromOutside = (event) => {
  const dialogs = [...document.querySelectorAll('.dialog-box')];
  const openDialog = dialogs.find(dialog => dialog.open);

  if (openDialog !== undefined) {
    const bounds = openDialog.getBoundingClientRect();
    if (
      event.clientY < bounds.top ||
      event.clientY > bounds.bottom ||
      event.clientX < bounds.left ||
      event.clientX > bounds.right
    ) {
      openDialog.close();
    }
  }
};

document.addEventListener('click', function(event) {
  if (openDialog(event)) return;
  if (closeDialog(event)) return;
  closeDialogFromOutside(event);
});
<table>
  <tr>
    <td>
      <dialog class="dialog-box">
        <button class="close-dialog-button">close #1</button> Table cell dialog #1
      </dialog>
      <button class="open-dialog-button">Open dialog box #1</button>
    </td>
  </tr>
  <tr>
    <td>
      <dialog class="dialog-box">
        <button class="close-dialog-button">close #2</button> Table cell dialog #2
      </dialog>
      <button class="open-dialog-button">Open dialog box #2</button>
    </td>
  </tr>
  <tr>
    <td>
      <dialog class="dialog-box">
        <button class="close-dialog-button">close #3</button> Table cell dialog #3
      </dialog>
      <button class="open-dialog-button">Open dialog box #3</button>
    </td>
  </tr>
</table>

Upvotes: 1

Related Questions