繁体   English   中英

当点击没有在内容之外启动时,防止模式关闭?

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

我创建了一个简单的模式,当你在内容区域外单击时,它可以被关闭。 这是设计但它有一个意想不到的副作用。 如果我单击内容区域中的任何位置(例如在文本字段中)并将鼠标拖动到内容区域之外,然后释放单击它将关闭模式。 我经常有这样做的习惯,我可以看到普通用户将这个视为一个错误,所以我试图在发布之前将其扼杀。

 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> 

要正确测试它:

  1. 单击“打开模态”按钮。
  2. 单击白色面板中心的文本框。
  3. 输入一些文字。
  4. 在文本框中按下鼠标左键。
  5. 将鼠标拖动到白色面板的边界之外。
  6. 释放鼠标按钮。

现在应该关闭模态。


有没有办法在不跟踪鼠标坐标的情况下防止这种情况?

  • 也许onmousedown而不是点击?
    • 那很有效! 我想今天早上需要更多的咖啡。 今天晚些时候为未来的读者写下一个彻底的答案。

在您使用有效原因回答自己之前(如问题编辑中所述) - 请考虑:

  • onmousedown可能并不总是理想的用户体验。 (有时有经验的用户撤消mousedown没有被注册为click他们故意将鼠标移动到鼠标事件的另一个元素上以保留当前状态。)
  • 删除内联JavaScript
  • 使用Element.addEventListener()将侦听器分配给具有data-modal属性的任何按钮
  • 使用data-modal="#some_modal_id"甚至没有容器元素
  • 最后:使用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> 

这是一个有效的例子。 想想,它匹配你需要的那个))

 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> 

为了自己回答这个问题,我想到了onclick事件是如何工作的。 单击被定义为按下鼠标按钮,然后释放。 必须出现这两点才能引发onclick事件(尽管在之前或之后的某个时刻你不能真正拥有一个)。

我没有在下面的执行路径上找到任何真实的文档,所以它基于逻辑推理。 如果您有任何相关文档,请将其链接到评论中,以便我可以查看它并调整我的答案以供将来读者阅读。

  1. 用户按下鼠标按钮。

  2. onmousedown事件被提出。

  3. 用户释放鼠标按钮。

  4. onmouseup事件被提出。

  5. onmouseclick事件被引发。

我确实写了一个测试来验证这些结果:

 var ePath = document.getElementById("executionPath"); document.body.onmousedown = function (event) { ePath.innerHTML += "On Mouse Down<br>"; } document.body.onmouseup = function (event) { ePath.innerHTML += "On Mouse Up<br>"; } document.body.onclick = function (event) { ePath.innerHTML += "On Click<br>"; } 
 html, body { height: 100%; } 
 <p id="executionPath">Click the Window<br></p> 

我相信意外行为是由为onclick事件设置target时引起的。 我认为设置时有三种可能性(从大多数到最不可能的下方),我无法确认或拒绝:

  • 释放鼠标按钮时设置target
  • 按下鼠标按钮时设置target ,然后在释放鼠标按钮时再次设置target
  • target是连续设置的。

分析我的想法后,我决定为我的情景onmousedown很可能是最好的解决方案。 这将确保仅当用户在内容区域外发起单击时模式才会关闭。 下面将演示如何将此与onmouseup以确保完全点击的好方法。 虽然在我的情况下,我可以简单地使用onmousedown

 var initialTarget = null; var modal = document.getElementById("modal-container"); function openModal() { modal.classList.add("active"); } function closeModal() { modal.classList.remove("active"); } window.onmousedown = function (event) { initialTarget = event.target; } window.onmouseup = function (event) { if (event.target == initialTarget) closeModal(); } 
 html, body { 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> 

上面的代码段确保在关闭模式之前,点击开始和结束在模态容器上。 如果用户意外启动内容区域外的点击并将鼠标拖入内容区域以完成点击,则可以防止模式关闭。 反过来也是如此,只有在模态容器上启动并完成点击时,模态才会关闭。


我唯一onclick是设置了onclicktarget ,这对于解决这个问题的根本原因可能更为重要,所以请随时告诉我!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM