diff --git a/js/src/modal.js b/js/src/modal.js index bee5e23f88..e2b711e5be 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -50,6 +50,7 @@ const DefaultType = { const Event = { HIDE: `hide${EVENT_KEY}`, + HIDE_PREVENTED: `hidePrevented${EVENT_KEY}`, HIDDEN: `hidden${EVENT_KEY}`, SHOW: `show${EVENT_KEY}`, SHOWN: `shown${EVENT_KEY}`, @@ -68,7 +69,8 @@ const ClassName = { BACKDROP: 'modal-backdrop', OPEN: 'modal-open', FADE: 'fade', - SHOW: 'show' + SHOW: 'show', + STATIC: 'modal-static' } const Selector = { @@ -307,8 +309,7 @@ class Modal { if (this._isShown && this._config.keyboard) { EventHandler.on(this._element, Event.KEYDOWN_DISMISS, event => { if (event.which === ESCAPE_KEYCODE) { - event.preventDefault() - this.hide() + this._triggerBackdropTransition() } }) } else { @@ -367,11 +368,7 @@ class Modal { return } - if (this._config.backdrop === 'static') { - this._element.focus() - } else { - this.hide() - } + this._triggerBackdropTransition() }) if (animate) { @@ -409,6 +406,25 @@ class Modal { } } + _triggerBackdropTransition() { + if (this._config.backdrop === 'static') { + const hideEvent = EventHandler.trigger(this._element, Event.HIDE_PREVENTED) + if (hideEvent.defaultPrevented) { + return + } + + this._element.classList.add(ClassName.STATIC) + const modalTransitionDuration = getTransitionDurationFromElement(this._element) + EventHandler.one(this._element, TRANSITION_END, () => { + this._element.classList.remove(ClassName.STATIC) + }) + emulateTransitionEnd(this._element, modalTransitionDuration) + this._element.focus() + } else { + this.hide() + } + } + // ---------------------------------------------------------------------- // the following methods are used to handle overflowing modals // ---------------------------------------------------------------------- diff --git a/js/tests/unit/modal.spec.js b/js/tests/unit/modal.spec.js index 604934785a..2edef22b2c 100644 --- a/js/tests/unit/modal.spec.js +++ b/js/tests/unit/modal.spec.js @@ -540,6 +540,33 @@ describe('Modal', () => { modal.show() }) + it('should not close modal when clicking outside of modal-content if backdrop = static', done => { + fixtureEl.innerHTML = '