Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent modal from closing when click didn't initiate outside of content?

Tags:

javascript

I've created a simple modal that is allowed to be closed when you click outside of the content area. This is by design but it has an unintended side-effect. If I click anywhere in the content area (for example in a text field) and drag the mouse to beyond the content area and then release the click it will close the modal. I often have a habit of doing this and I can see how average users will perceive this as a bug so I'm trying to nip it prior to release.

var modal = document.getElementById("modal-container");
function openModal() { modal.classList.add("active"); }
function closeModal() { modal.classList.remove("active"); }
window.onclick = function (event) {
    if (event.target == modal)
        closeModal();
}
html, body {
  margin: 0;
  height: 100%;
}
.modal-container.active { top: 0; }
.modal-container {
  position: absolute;
  top: -500vh;
  left: 0;
  width: 100%;
  height: 100%;
  display: grid;
  background-color: rgba(0, 0, 0, 0.75);
}

.modal-content {
  height: 50%;
  width: 50%;
  margin: auto;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
<button onclick="openModal();">Open the Modal</button>
<div id="modal-container" class="modal-container">
  <div class="modal-content">
    <input type="text" />
  </div>
</div>

To test it properly:

  1. Click the 'Open the Modal' button.
  2. Click in the text box at the center of the white panel.
  3. Enter some text.
  4. Press the left mouse button down in the text box.
  5. Drag the mouse beyond the bounds of the white panel.
  6. Release the mouse button.

The modal should now be closed.


Is there a way to prevent this without tracking the coordinates of the mouse?

  • Perhaps onmousedown instead of click?
    • That worked! Just need more coffee this morning I suppose. Going to write up a thorough answer later today for future readers.
like image 308
Taco タコス Avatar asked Jun 17 '19 14:06

Taco タコス


People also ask

How do I stop closing the modal when I click outside?

When the Button is clicked, the HTML DIV is referenced using jQuery and its modal function is called along with properties data-backdrop: "static" and data-keyboard: false which disables the closing of the Bootstrap Modal Popup when clicked outside.

How do I make Bootstrap modal not close on click outside?

By default, dialog can be closed by pressing Esc key and clicking the close icon on the right of dialog header. It can also be closed by clicking outside of the dialog using hide method. Set the closeOnEscape property value to false to prevent closing of the dialog when pressing Esc key.

How do you close the modal by clicking outside of the modal box?

Modal Header You have two options to close this modal: Click on the "x" or click anywhere outside of the modal!

How do you close a modal with a button?

Click the button to launch the modal. Then click on the backdrop, close icon or close button to close the modal.


2 Answers

Before you answer yourself with a valid cause (as noted in your Question Edit) - take in consideration:

  • onmousedown might not always be the desired UX. (Sometimes experienced users to undo a mousedown not being registered as a click they on purpose move the mouse over another element for the mouseup event just to retain the current state.)
  • Remove inline JavaScript
  • Assign listeners using Element.addEventListener() to any button having the data-modal attribute
  • Use data-modal="#some_modal_id" even no the container element
  • Finally: use if (evt.target !== this) return;

const el_dataModal = document.querySelectorAll('[data-modal]');

function toggleModal(evt) {
  if (evt.target !== this) return; // Do nothing if the element that propagated the event is not the `this` button which has the event attached.
  const id = evt.currentTarget.getAttribute('data-modal');
  document.querySelector(id).classList.toggle('active');
}

el_dataModal.forEach(el => el.addEventListener('click', toggleModal));
html, body {
  margin: 0;
  height: 100%;
}
.modal-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: grid;
  background-color: rgba(0, 0, 0, 0.75);
  opacity: 0; /* ADDED */
  transition: 0.26s; /* ADDED */
  visibility: hidden; /* ADDED */
}
.modal-container.active {
  opacity: 1; /* ADDED */
  visibility: visible; /* ADDED */
}
.modal-content {
  height: 50%;
  width: 50%;
  margin: auto;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
<button data-modal="#modal-container">Open the Modal</button>

<div id="modal-container" class="modal-container" data-modal="#modal-container">
  <div class="modal-content">
    <input type="text">
    <br><br>
    <button data-modal="#modal-container">CLOSE MODAL TEST</button>
  </div>
</div>
like image 192
Roko C. Buljan Avatar answered Oct 15 '22 23:10

Roko C. Buljan


This is working example. Think, it matches that one you need))

var clickTarget = null;
var modal = document.getElementById("modal-container");

function openModal() {
    modal.classList.add("active");
    document.body.addEventListener('mousedown', onModalMouseDown, false);
    document.body.addEventListener('mouseup', onModalMouseUp, false);
}

function closeModal() {
    modal.classList.remove("active");
    document.body.removeEventListener('mousedown', onModalMouseDown);
    document.body.removeEventListener('mouseup', onModalMouseUp);
}

function onModalMouseDown(event) {
    clickTarget = event.target;
}

function onModalMouseUp() {
    if (clickTarget === modal) {
        closeModal();
    }
}
html, body {
  margin: 0;
  height: 100%;
}
.modal-container.active { top: 0; }
.modal-container {
  position: absolute;
  top: -500vh;
  left: 0;
  width: 100%;
  height: 100%;
  display: grid;
  background-color: rgba(0, 0, 0, 0.75);
}

.modal-content {
  height: 50%;
  width: 50%;
  margin: auto;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-trigger-btn {
  margin: 20px;
  font-size: 16px;
}
<button onmousedown="openModal();" class="modal-trigger-btn">Open the Modal</button>
<div id="modal-container" class="modal-container">
  <div class="modal-content">
    <input type="text" placeholder="Start to drag outside..."/>
  </div>
</div>
like image 40
Evgeny Melnikov Avatar answered Oct 16 '22 00:10

Evgeny Melnikov