From 303ffebd0312fdda3e16442f29e1270d775a1392 Mon Sep 17 00:00:00 2001 From: Sentox6 <71313530+Sentox6@users.noreply.github.com> Date: Sun, 19 Jun 2022 20:14:51 +1200 Subject: [PATCH] Prevent clicks originating inside modal from dismissing Current behaviour means any click events on the modal backdrop will dismiss the dialog, regardless of whether the initial mousedown event originated inside the dialog. When the modal contains elements such as text inputs, it's quite easy to accidentally close it by (for example) clicking and dragging to select text; if the mouse is released over the backdrop, the modal will close. This change uses an event handler for mousedown and mouseup, and tracks whether a mousedown began outside the dialog or not. --- js/src/modal.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/js/src/modal.js b/js/src/modal.js index d3f0540bb8b9..598c33443d8a 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -30,7 +30,8 @@ const EVENT_HIDDEN = `hidden${EVENT_KEY}` const EVENT_SHOW = `show${EVENT_KEY}` const EVENT_SHOWN = `shown${EVENT_KEY}` const EVENT_RESIZE = `resize${EVENT_KEY}` -const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}` +const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}` +const EVENT_MOUSEUP_DISMISS = `mouseup.dismiss${EVENT_KEY}` const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}` const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` @@ -69,6 +70,7 @@ class Modal extends BaseComponent { this._focustrap = this._initializeFocusTrap() this._isShown = false this._isTransitioning = false + this._dismissOutside = false this._scrollBar = new ScrollBarHelper() this._addEventListeners() @@ -221,8 +223,12 @@ class Modal extends BaseComponent { } }) - EventHandler.on(this._element, EVENT_CLICK_DISMISS, event => { - if (event.target !== event.currentTarget) { // click is inside modal-dialog + EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => { + this._dismissOutside = (event.target === event.currentTarget) + }) + + EventHandler.on(this._element, EVENT_MOUSEUP_DISMISS, event => { + if (event.target !== event.currentTarget || !this._dismissOutside) { // click is inside (or originated inside) modal-dialog return }