From 9434aaa22c75d04a285e24867a45c70e65b4ec44 Mon Sep 17 00:00:00 2001 From: Higor Anjos <higor.anjos@conductor.com.br> Date: Fri, 11 Oct 2019 22:46:51 -0300 Subject: [PATCH 1/7] Added animation when modal backdrop is static --- js/src/modal.js | 35 ++++++++++++++++++++++++++++++++--- js/tests/units/modal.spec.js | 28 ++++++++++++++++++++++++++++ scss/_modal.scss | 5 +++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/js/src/modal.js b/js/src/modal.js index bee5e23f88..5e7b0a921b 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', + SCALE: 'scale' } const Selector = { @@ -307,8 +309,22 @@ 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() + if (this._config.backdrop === 'static') { + const hideEvent = EventHandler.trigger(this._element, Event.HIDE_PREVENTED) + if (hideEvent.defaultPrevented) { + return + } + + this._element.classList.add(ClassName.SCALE) + const modalTransitionDuration = getTransitionDurationFromElement(this._element) + EventHandler.one(this._element, TRANSITION_END, () => { + this._element.classList.remove(ClassName.SCALE) + }) + emulateTransitionEnd(this._element, modalTransitionDuration) + this._element.focus() + } else { + this.hide() + } } }) } else { @@ -368,6 +384,19 @@ class Modal { } if (this._config.backdrop === 'static') { + const hideEvent = EventHandler.trigger(this._element, Event.HIDE_PREVENTED) + + if (hideEvent.defaultPrevented) { + return + } + + this._element.classList.add(ClassName.SCALE) + const modalTransitionDuration = getTransitionDurationFromElement(this._element) + EventHandler.one(this._element, TRANSITION_END, () => { + this._element.classList.remove(ClassName.SCALE) + }) + emulateTransitionEnd(this._element, modalTransitionDuration) + this._element.focus() } else { this.hide() diff --git a/js/tests/units/modal.spec.js b/js/tests/units/modal.spec.js index 604934785a..5054de430f 100644 --- a/js/tests/units/modal.spec.js +++ b/js/tests/units/modal.spec.js @@ -540,6 +540,34 @@ describe('Modal', () => { modal.show() }) + it('should not close modal when clicking outside of modal-content if backdrop = static', done => { + fixtureEl.innerHTML = + '<div class="modal" data-backdrop="static" ><div class="modal-dialog" /></div>' + + const modalEl = fixtureEl.querySelector('.modal') + const modal = new Modal(modalEl, { + backdrop: 'static' + }) + + const shownCallback = () => { + setTimeout(() => { + expect(modal._isShown).toEqual(true) + done() + }, 10) + } + + modalEl.addEventListener('shown.bs.modal', () => { + modalEl.click() + shownCallback() + }) + + modalEl.addEventListener('hidden.bs.modal', () => { + throw new Error('Should not hide a modal') + }) + + modal.show() + }) + it('should not adjust the inline body padding when it does not overflow', done => { fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog" /></div>' diff --git a/scss/_modal.scss b/scss/_modal.scss index 6001d040dd..187dc7019b 100644 --- a/scss/_modal.scss +++ b/scss/_modal.scss @@ -48,6 +48,11 @@ .modal.show & { transform: $modal-show-transform; } + + // When trying to close, animate focus to scale + .modal.scale & { + transform: scale(1.02); + } } .modal-dialog-scrollable { -- GitLab From 9a28600a1ceff30a2cb9646e25848530642714e9 Mon Sep 17 00:00:00 2001 From: XhmikosR <xhmikosr@gmail.com> Date: Sat, 12 Oct 2019 16:21:43 +0300 Subject: [PATCH 2/7] Update modal.spec.js --- js/tests/unit/modal.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/tests/unit/modal.spec.js b/js/tests/unit/modal.spec.js index 5054de430f..2edef22b2c 100644 --- a/js/tests/unit/modal.spec.js +++ b/js/tests/unit/modal.spec.js @@ -541,8 +541,7 @@ describe('Modal', () => { }) it('should not close modal when clicking outside of modal-content if backdrop = static', done => { - fixtureEl.innerHTML = - '<div class="modal" data-backdrop="static" ><div class="modal-dialog" /></div>' + fixtureEl.innerHTML = '<div class="modal" data-backdrop="static" ><div class="modal-dialog" /></div>' const modalEl = fixtureEl.querySelector('.modal') const modal = new Modal(modalEl, { -- GitLab From 85e1c041caa6b5cbd0973683be6832044e7b03c8 Mon Sep 17 00:00:00 2001 From: Higor Anjos <higor.anjos@conductor.com.br> Date: Mon, 14 Oct 2019 15:35:15 -0300 Subject: [PATCH 3/7] Refactored modal js code and changed classname --- js/src/modal.js | 61 +++++++++++++++++++++--------------------------- scss/_modal.scss | 2 +- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/js/src/modal.js b/js/src/modal.js index 5e7b0a921b..7865c76e7a 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -70,7 +70,7 @@ const ClassName = { OPEN: 'modal-open', FADE: 'fade', SHOW: 'show', - SCALE: 'scale' + STATIC: 'modal-static' } const Selector = { @@ -309,22 +309,8 @@ class Modal { if (this._isShown && this._config.keyboard) { EventHandler.on(this._element, Event.KEYDOWN_DISMISS, event => { if (event.which === ESCAPE_KEYCODE) { - if (this._config.backdrop === 'static') { - const hideEvent = EventHandler.trigger(this._element, Event.HIDE_PREVENTED) - if (hideEvent.defaultPrevented) { - return - } - - this._element.classList.add(ClassName.SCALE) - const modalTransitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, () => { - this._element.classList.remove(ClassName.SCALE) - }) - emulateTransitionEnd(this._element, modalTransitionDuration) - this._element.focus() - } else { - this.hide() - } + // This will trigger a scale transition if the backdrop is static + this._triggerBackdropTransition() } }) } else { @@ -383,24 +369,8 @@ class Modal { return } - if (this._config.backdrop === 'static') { - const hideEvent = EventHandler.trigger(this._element, Event.HIDE_PREVENTED) - - if (hideEvent.defaultPrevented) { - return - } - - this._element.classList.add(ClassName.SCALE) - const modalTransitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, () => { - this._element.classList.remove(ClassName.SCALE) - }) - emulateTransitionEnd(this._element, modalTransitionDuration) - - this._element.focus() - } else { - this.hide() - } + // This will trigger a scale transition if the backdrop is static + this._triggerBackdropTransition() }) if (animate) { @@ -438,6 +408,27 @@ class Modal { } } + // This function will trigger a HIDE_PREVENTED event and do a scale animation if + // the backdrop is static + _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/scss/_modal.scss b/scss/_modal.scss index 187dc7019b..78a6b55ee9 100644 --- a/scss/_modal.scss +++ b/scss/_modal.scss @@ -50,7 +50,7 @@ } // When trying to close, animate focus to scale - .modal.scale & { + .modal.modal-static & { transform: scale(1.02); } } -- GitLab From bc97ef0b771ba63c9be3ac8594f4ec08e6d16694 Mon Sep 17 00:00:00 2001 From: Higor Anjos <higor.anjos@conductor.com.br> Date: Mon, 14 Oct 2019 15:36:34 -0300 Subject: [PATCH 4/7] Added static backdrop info on docs --- site/content/docs/4.3/components/modal.md | 65 ++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/site/content/docs/4.3/components/modal.md b/site/content/docs/4.3/components/modal.md index f82ee774e5..bb06ed5f3e 100644 --- a/site/content/docs/4.3/components/modal.md +++ b/site/content/docs/4.3/components/modal.md @@ -140,6 +140,65 @@ Toggle a working modal demo by clicking the button below. It will slide down and </div> {{< /highlight >}} +### Static backdrop + +When backdrop is set to static, the modal will not close when clicking outside it. Click the button below to try it. + +<div id="staticBackdropLive" class="modal fade" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="staticBackdropLiveLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="staticBackdropLiveLabel">Modal title</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <p>I'll not close if you click outside me. Don't even try to press escape key.</p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Understood</button> + </div> + </div> + </div> +</div> + +<div class="bd-example"> + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#staticBackdropLive"> + Launch static backdrop modal + </button> +</div> + +{{< highlight html >}} +<!-- Button trigger modal --> +<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#staticBackdrop"> + Launch static backdrop modal +</button> + +<!-- Modal --> +<div class="modal fade" id="staticBackdrop" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="staticBackdropLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="staticBackdropLabel">Modal title</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + ... + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Understood</button> + </div> + </div> + </div> +</div> +{{< /highlight >}} + + ### Scrolling long content When modals become too long for the user's viewport or device, they scroll independent of the page itself. Try the demo below to see what we mean. @@ -753,7 +812,7 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap <td>backdrop</td> <td>boolean or the string <code>'static'</code></td> <td>true</td> - <td>Includes a modal-backdrop element. Alternatively, specify <code>static</code> for a backdrop which doesn't close the modal on click.</td> + <td>Includes a modal-backdrop element. Alternatively, specify <code>static</code> for a backdrop which doesn't close the modal on click or on escape key press.</td> </tr> <tr> <td>keyboard</td> @@ -859,6 +918,10 @@ Bootstrap's modal class exposes a few events for hooking into modal functionalit <td>hidden.bs.modal</td> <td>This event is fired when the modal has finished being hidden from the user (will wait for CSS transitions to complete).</td> </tr> + <tr> + <td>hidePrevented.bs.modal</td> + <td>This event is fired when the modal is shown, its backdrop is <code>static</code> and a click outside the modal or a scape key press is performed.</td> + </tr> </tbody> </table> -- GitLab From efcc341ec6b0cf25dbd395aaa6cd6d8edbbef486 Mon Sep 17 00:00:00 2001 From: Higor Anjos <higor.anjos@conductor.com.br> Date: Wed, 16 Oct 2019 10:23:18 -0300 Subject: [PATCH 5/7] Removed comments on JS code --- js/src/modal.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/src/modal.js b/js/src/modal.js index 7865c76e7a..e2b711e5be 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -309,7 +309,6 @@ class Modal { if (this._isShown && this._config.keyboard) { EventHandler.on(this._element, Event.KEYDOWN_DISMISS, event => { if (event.which === ESCAPE_KEYCODE) { - // This will trigger a scale transition if the backdrop is static this._triggerBackdropTransition() } }) @@ -369,7 +368,6 @@ class Modal { return } - // This will trigger a scale transition if the backdrop is static this._triggerBackdropTransition() }) @@ -408,8 +406,6 @@ class Modal { } } - // This function will trigger a HIDE_PREVENTED event and do a scale animation if - // the backdrop is static _triggerBackdropTransition() { if (this._config.backdrop === 'static') { const hideEvent = EventHandler.trigger(this._element, Event.HIDE_PREVENTED) -- GitLab From 10e443bf59e02606e98d0a9748f6173ff199197c Mon Sep 17 00:00:00 2001 From: XhmikosR <xhmikosr@gmail.com> Date: Thu, 17 Oct 2019 09:52:35 +0300 Subject: [PATCH 6/7] Update modal.md --- site/content/docs/4.3/components/modal.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/4.3/components/modal.md b/site/content/docs/4.3/components/modal.md index bb06ed5f3e..fd1a04a621 100644 --- a/site/content/docs/4.3/components/modal.md +++ b/site/content/docs/4.3/components/modal.md @@ -154,7 +154,7 @@ When backdrop is set to static, the modal will not close when clicking outside i </button> </div> <div class="modal-body"> - <p>I'll not close if you click outside me. Don't even try to press escape key.</p> + <p>I will not close if you click outside me. Don't even try to press escape key.</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> -- GitLab From 20108a135b222150a1556f25504da21dafb0b33c Mon Sep 17 00:00:00 2001 From: Higor Anjos <higor.anjos@conductor.com.br> Date: Fri, 25 Oct 2019 14:09:13 -0300 Subject: [PATCH 7/7] Made scale transform a variable --- scss/_modal.scss | 2 +- scss/_variables.scss | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/scss/_modal.scss b/scss/_modal.scss index 78a6b55ee9..381b0685e5 100644 --- a/scss/_modal.scss +++ b/scss/_modal.scss @@ -51,7 +51,7 @@ // When trying to close, animate focus to scale .modal.modal-static & { - transform: scale(1.02); + transform: $modal-scale-transform; } } diff --git a/scss/_variables.scss b/scss/_variables.scss index b4dff2cf59..1adc5f5a08 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -1073,6 +1073,7 @@ $modal-sm: 300px !default; $modal-fade-transform: translate(0, -50px) !default; $modal-show-transform: none !default; $modal-transition: transform .3s ease-out !default; +$modal-scale-transform: scale(1.02) !default; // Alerts -- GitLab