From dc5e3328c12058de7fb6404edbe5dcee61f3400f Mon Sep 17 00:00:00 2001 From: Rohit Sharma Date: Mon, 22 Feb 2021 12:31:04 +0530 Subject: Allow constructors to accept a CSS selector (#32245) Co-authored-by: XhmikosR Co-authored-by: Mark Otto --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 79a2f143a..4f42e733e 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -83,7 +83,7 @@ class Modal extends BaseComponent { super(element) this._config = this._getConfig(config) - this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, element) + this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element) this._backdrop = null this._isShown = false this._isBodyOverflowing = false -- cgit v1.2.3 From 056216a3bd2fd1f28ba9ec6f2797aa2aaec5c6f0 Mon Sep 17 00:00:00 2001 From: Muhammadamin Date: Tue, 23 Feb 2021 07:52:09 -0500 Subject: modal: don't add margin & padding when sticky is not full width (#30621) * modal: don't add margin & padding when sticky is not full width * Check if element is shorter than window Co-authored-by: XhmikosR Co-authored-by: Rohit Sharma --- js/src/modal.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 4f42e733e..5afb9791b 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -466,6 +466,10 @@ class Modal extends BaseComponent { _setElementAttributes(selector, styleProp, callback) { SelectorEngine.find(selector) .forEach(element => { + if (element !== document.body && window.innerWidth > element.clientWidth + this._scrollbarWidth) { + return + } + const actualValue = element.style[styleProp] const calculatedValue = window.getComputedStyle(element)[styleProp] Manipulator.setDataAttribute(element, styleProp, actualValue) -- cgit v1.2.3 From 48a95f7280735d6f8962fe8b17975b03e351710c Mon Sep 17 00:00:00 2001 From: alpadev <2838324+alpadev@users.noreply.github.com> Date: Tue, 2 Mar 2021 15:55:44 +0100 Subject: refactor: use a Map instead of an Object in dom/data (#32180) Co-authored-by: XhmikosR Co-authored-by: Rohit Sharma --- js/src/modal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 5afb9791b..332d636d0 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -508,7 +508,7 @@ class Modal extends BaseComponent { static jQueryInterface(config, relatedTarget) { return this.each(function () { - let data = Data.getData(this, DATA_KEY) + let data = Data.get(this, DATA_KEY) const _config = { ...Default, ...Manipulator.getDataAttributes(this), @@ -556,7 +556,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( }) }) - let data = Data.getData(target, DATA_KEY) + let data = Data.get(target, DATA_KEY) if (!data) { const config = { ...Manipulator.getDataAttributes(target), -- cgit v1.2.3 From e163d988457c77f83296b0f950659cd9d2b7bb94 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Mon, 8 Mar 2021 18:35:59 +0200 Subject: modal: move common code to a new `isAnimated` method (#33056) --- js/src/modal.js | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 332d636d0..40fd226bf 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -113,7 +113,7 @@ class Modal extends BaseComponent { return } - if (this._element.classList.contains(CLASS_NAME_FADE)) { + if (this._isAnimated()) { this._isTransitioning = true } @@ -164,9 +164,9 @@ class Modal extends BaseComponent { } this._isShown = false - const transition = this._element.classList.contains(CLASS_NAME_FADE) + const isAnimated = this._isAnimated() - if (transition) { + if (isAnimated) { this._isTransitioning = true } @@ -180,7 +180,7 @@ class Modal extends BaseComponent { EventHandler.off(this._element, EVENT_CLICK_DISMISS) EventHandler.off(this._dialog, EVENT_MOUSEDOWN_DISMISS) - if (transition) { + if (isAnimated) { const transitionDuration = getTransitionDurationFromElement(this._element) EventHandler.one(this._element, 'transitionend', event => this._hideModal(event)) @@ -229,7 +229,7 @@ class Modal extends BaseComponent { } _showElement(relatedTarget) { - const transition = this._element.classList.contains(CLASS_NAME_FADE) + const isAnimated = this._isAnimated() const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog) if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { @@ -247,7 +247,7 @@ class Modal extends BaseComponent { modalBody.scrollTop = 0 } - if (transition) { + if (isAnimated) { reflow(this._element) } @@ -268,7 +268,7 @@ class Modal extends BaseComponent { }) } - if (transition) { + if (isAnimated) { const transitionDuration = getTransitionDurationFromElement(this._dialog) EventHandler.one(this._dialog, 'transitionend', transitionComplete) @@ -332,16 +332,13 @@ class Modal extends BaseComponent { } _showBackdrop(callback) { - const animate = this._element.classList.contains(CLASS_NAME_FADE) ? - CLASS_NAME_FADE : - '' - + const isAnimated = this._isAnimated() if (this._isShown && this._config.backdrop) { this._backdrop = document.createElement('div') this._backdrop.className = CLASS_NAME_BACKDROP - if (animate) { - this._backdrop.classList.add(animate) + if (isAnimated) { + this._backdrop.classList.add(CLASS_NAME_FADE) } document.body.appendChild(this._backdrop) @@ -363,13 +360,13 @@ class Modal extends BaseComponent { } }) - if (animate) { + if (isAnimated) { reflow(this._backdrop) } this._backdrop.classList.add(CLASS_NAME_SHOW) - if (!animate) { + if (!isAnimated) { callback() return } @@ -386,7 +383,7 @@ class Modal extends BaseComponent { callback() } - if (this._element.classList.contains(CLASS_NAME_FADE)) { + if (isAnimated) { const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop) EventHandler.one(this._backdrop, 'transitionend', callbackRemove) emulateTransitionEnd(this._backdrop, backdropTransitionDuration) @@ -398,6 +395,10 @@ class Modal extends BaseComponent { } } + _isAnimated() { + return this._element.classList.contains(CLASS_NAME_FADE) + } + _triggerBackdropTransition() { const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED) if (hideEvent.defaultPrevented) { -- cgit v1.2.3 From 220139a89ffc3864bbb6e1b35471667318eadc1f Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Tue, 23 Mar 2021 18:26:54 +0200 Subject: Release v5.0.0-beta3 (#33439) --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 40fd226bf..2966f03fb 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.0-beta2): modal.js + * Bootstrap (v5.0.0-beta3): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ -- cgit v1.2.3 From 5cc53a0ef0718b43e376462f156d39bf5542fbf9 Mon Sep 17 00:00:00 2001 From: Rohit Sharma Date: Tue, 30 Mar 2021 11:27:05 +0530 Subject: Use template literals instead of concatenation (#33497) --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 2966f03fb..4ce910dc6 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -474,7 +474,7 @@ class Modal extends BaseComponent { const actualValue = element.style[styleProp] const calculatedValue = window.getComputedStyle(element)[styleProp] Manipulator.setDataAttribute(element, styleProp, actualValue) - element.style[styleProp] = callback(Number.parseFloat(calculatedValue)) + 'px' + element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px` }) } -- cgit v1.2.3 From 752b001b0a65a595d1844b01226f1402562a8a7f Mon Sep 17 00:00:00 2001 From: GeoSot Date: Wed, 3 Mar 2021 02:17:48 +0200 Subject: Simplify Modal config --- js/src/modal.js | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 4ce910dc6..aa6a8ffb2 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -10,12 +10,11 @@ import { emulateTransitionEnd, getElementFromSelector, getTransitionDurationFromElement, - isVisible, isRTL, + isVisible, reflow, typeCheckConfig } from './util/index' -import Data from './dom/data' import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' import SelectorEngine from './dom/selector-engine' @@ -222,6 +221,7 @@ class Modal extends BaseComponent { _getConfig(config) { config = { ...Default, + ...Manipulator.getDataAttributes(this._element), ...config } typeCheckConfig(NAME, config, DefaultType) @@ -509,24 +509,17 @@ class Modal extends BaseComponent { static jQueryInterface(config, relatedTarget) { return this.each(function () { - let data = Data.get(this, DATA_KEY) - const _config = { - ...Default, - ...Manipulator.getDataAttributes(this), - ...(typeof config === 'object' && config ? config : {}) - } + const data = Modal.getInstance(this) || new Modal(this, typeof config === 'object' ? config : {}) - if (!data) { - data = new Modal(this, _config) + if (typeof config !== 'string') { + return } - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - - data[config](relatedTarget) + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } + + data[config](relatedTarget) }) } } @@ -540,7 +533,7 @@ class Modal extends BaseComponent { EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { const target = getElementFromSelector(this) - if (this.tagName === 'A' || this.tagName === 'AREA') { + if (['A', 'AREA'].includes(this.tagName)) { event.preventDefault() } @@ -557,15 +550,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( }) }) - let data = Data.get(target, DATA_KEY) - if (!data) { - const config = { - ...Manipulator.getDataAttributes(target), - ...Manipulator.getDataAttributes(this) - } - - data = new Modal(target, config) - } + const data = Modal.getInstance(target) || new Modal(target, Manipulator.getDataAttributes(this)) data.toggle(this) }) -- cgit v1.2.3 From 317c2cd08e91d118132c36648ba0bbed7812357a Mon Sep 17 00:00:00 2001 From: GeoSot Date: Fri, 5 Mar 2021 22:06:18 +0200 Subject: Omit getting data-attributes from toggle element --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index aa6a8ffb2..b2a2e80eb 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -550,7 +550,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( }) }) - const data = Modal.getInstance(target) || new Modal(target, Manipulator.getDataAttributes(this)) + const data = Modal.getInstance(target) || new Modal(target) data.toggle(this) }) -- cgit v1.2.3 From 7b7f4a5ced176ae3d7d9d16583795245cb9c7df3 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Sun, 11 Apr 2021 09:37:59 +0300 Subject: Decouple Modal's scrollbar functionality (#33245) --- js/src/modal.js | 82 ++++++++------------------------------------------------- 1 file changed, 11 insertions(+), 71 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index b2a2e80eb..dea90ec0a 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -18,6 +18,7 @@ import { import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' import SelectorEngine from './dom/selector-engine' +import { getWidth as getScrollBarWidth, hide as scrollBarHide, reset as scrollBarReset } from './util/scrollbar' import BaseComponent from './base-component' /** @@ -57,7 +58,6 @@ const EVENT_MOUSEUP_DISMISS = `mouseup.dismiss${EVENT_KEY}` const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}` const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` -const CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure' const CLASS_NAME_BACKDROP = 'modal-backdrop' const CLASS_NAME_OPEN = 'modal-open' const CLASS_NAME_FADE = 'fade' @@ -68,8 +68,6 @@ const SELECTOR_DIALOG = '.modal-dialog' const SELECTOR_MODAL_BODY = '.modal-body' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]' const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]' -const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top' -const SELECTOR_STICKY_CONTENT = '.sticky-top' /** * ------------------------------------------------------------------------ @@ -85,10 +83,8 @@ class Modal extends BaseComponent { this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element) this._backdrop = null this._isShown = false - this._isBodyOverflowing = false this._ignoreBackdropClick = false this._isTransitioning = false - this._scrollbarWidth = 0 } // Getters @@ -126,8 +122,9 @@ class Modal extends BaseComponent { this._isShown = true - this._checkScrollbar() - this._setScrollbar() + scrollBarHide() + + document.body.classList.add(CLASS_NAME_OPEN) this._adjustDialog() @@ -206,10 +203,8 @@ class Modal extends BaseComponent { this._dialog = null this._backdrop = null this._isShown = null - this._isBodyOverflowing = null this._ignoreBackdropClick = null this._isTransitioning = null - this._scrollbarWidth = null } handleUpdate() { @@ -321,7 +316,7 @@ class Modal extends BaseComponent { this._showBackdrop(() => { document.body.classList.remove(CLASS_NAME_OPEN) this._resetAdjustments() - this._resetScrollbar() + scrollBarReset() EventHandler.trigger(this._element, EVENT_HIDDEN) }) } @@ -433,13 +428,15 @@ class Modal extends BaseComponent { _adjustDialog() { const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight + const scrollbarWidth = getScrollBarWidth() + const isBodyOverflowing = scrollbarWidth > 0 - if ((!this._isBodyOverflowing && isModalOverflowing && !isRTL()) || (this._isBodyOverflowing && !isModalOverflowing && isRTL())) { - this._element.style.paddingLeft = `${this._scrollbarWidth}px` + if ((!isBodyOverflowing && isModalOverflowing && !isRTL()) || (isBodyOverflowing && !isModalOverflowing && isRTL())) { + this._element.style.paddingLeft = `${scrollbarWidth}px` } - if ((this._isBodyOverflowing && !isModalOverflowing && !isRTL()) || (!this._isBodyOverflowing && isModalOverflowing && isRTL())) { - this._element.style.paddingRight = `${this._scrollbarWidth}px` + if ((isBodyOverflowing && !isModalOverflowing && !isRTL()) || (!isBodyOverflowing && isModalOverflowing && isRTL())) { + this._element.style.paddingRight = `${scrollbarWidth}px` } } @@ -448,63 +445,6 @@ class Modal extends BaseComponent { this._element.style.paddingRight = '' } - _checkScrollbar() { - const rect = document.body.getBoundingClientRect() - this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth - this._scrollbarWidth = this._getScrollbarWidth() - } - - _setScrollbar() { - if (this._isBodyOverflowing) { - this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + this._scrollbarWidth) - this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - this._scrollbarWidth) - this._setElementAttributes('body', 'paddingRight', calculatedValue => calculatedValue + this._scrollbarWidth) - } - - document.body.classList.add(CLASS_NAME_OPEN) - } - - _setElementAttributes(selector, styleProp, callback) { - SelectorEngine.find(selector) - .forEach(element => { - if (element !== document.body && window.innerWidth > element.clientWidth + this._scrollbarWidth) { - return - } - - const actualValue = element.style[styleProp] - const calculatedValue = window.getComputedStyle(element)[styleProp] - Manipulator.setDataAttribute(element, styleProp, actualValue) - element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px` - }) - } - - _resetScrollbar() { - this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight') - this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight') - this._resetElementAttributes('body', 'paddingRight') - } - - _resetElementAttributes(selector, styleProp) { - SelectorEngine.find(selector).forEach(element => { - const value = Manipulator.getDataAttribute(element, styleProp) - if (typeof value === 'undefined' && element === document.body) { - element.style[styleProp] = '' - } else { - Manipulator.removeDataAttribute(element, styleProp) - element.style[styleProp] = value - } - }) - } - - _getScrollbarWidth() { // thx d.walsh - const scrollDiv = document.createElement('div') - scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER - document.body.appendChild(scrollDiv) - const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth - document.body.removeChild(scrollDiv) - return scrollbarWidth - } - // Static static jQueryInterface(config, relatedTarget) { -- cgit v1.2.3 From 566451230f5c87c3d7515af02995895df610b8ac Mon Sep 17 00:00:00 2001 From: GeoSot Date: Sun, 11 Apr 2021 09:54:48 +0300 Subject: Remove element event listeners through base component (#33429) After some research, I found out that EventHandler saves all the custom events per element using namespace, and is capable of removing handlers using only the element and its namespace (`DATA_KEY`). So, probably is better to utilize the base-component to do the same job. --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index dea90ec0a..c6d67ac95 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -187,7 +187,7 @@ class Modal extends BaseComponent { } dispose() { - [window, this._element, this._dialog] + [window, this._dialog] .forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY)) super.dispose() -- cgit v1.2.3 From 80085a12f6936bef11aa72631392e3e9b2646f17 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Wed, 14 Apr 2021 23:28:50 +0300 Subject: Decouple BackDrop from modal (#32439) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create backdrop.js util * revert breaking changes remove PromiseTimout usage revert class name * one more test | change bundlewatch.config * add config obj to backdrop helper | tests for rootElement | use transitionend helper * Minor tweaks — Renaming Co-authored-by: Rohit Sharma --- js/src/modal.js | 84 +++++++++++++++------------------------------------------ 1 file changed, 22 insertions(+), 62 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index c6d67ac95..fabb151cb 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -20,6 +20,7 @@ import Manipulator from './dom/manipulator' import SelectorEngine from './dom/selector-engine' import { getWidth as getScrollBarWidth, hide as scrollBarHide, reset as scrollBarReset } from './util/scrollbar' import BaseComponent from './base-component' +import Backdrop from './util/backdrop' /** * ------------------------------------------------------------------------ @@ -58,7 +59,6 @@ const EVENT_MOUSEUP_DISMISS = `mouseup.dismiss${EVENT_KEY}` const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}` const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` -const CLASS_NAME_BACKDROP = 'modal-backdrop' const CLASS_NAME_OPEN = 'modal-open' const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' @@ -81,7 +81,7 @@ class Modal extends BaseComponent { this._config = this._getConfig(config) this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element) - this._backdrop = null + this._backdrop = this._initializeBackDrop() this._isShown = false this._ignoreBackdropClick = false this._isTransitioning = false @@ -201,6 +201,7 @@ class Modal extends BaseComponent { this._config = null this._dialog = null + this._backdrop.dispose() this._backdrop = null this._isShown = null this._ignoreBackdropClick = null @@ -213,6 +214,13 @@ class Modal extends BaseComponent { // Private + _initializeBackDrop() { + return new Backdrop({ + isVisible: Boolean(this._config.backdrop), // 'static' option will be translated to true, and booleans will keep their value + isAnimated: this._isAnimated() + }) + } + _getConfig(config) { config = { ...Default, @@ -313,7 +321,7 @@ class Modal extends BaseComponent { this._element.removeAttribute('aria-modal') this._element.removeAttribute('role') this._isTransitioning = false - this._showBackdrop(() => { + this._backdrop.hide(() => { document.body.classList.remove(CLASS_NAME_OPEN) this._resetAdjustments() scrollBarReset() @@ -321,73 +329,25 @@ class Modal extends BaseComponent { }) } - _removeBackdrop() { - this._backdrop.parentNode.removeChild(this._backdrop) - this._backdrop = null - } - _showBackdrop(callback) { - const isAnimated = this._isAnimated() - if (this._isShown && this._config.backdrop) { - this._backdrop = document.createElement('div') - this._backdrop.className = CLASS_NAME_BACKDROP - - if (isAnimated) { - this._backdrop.classList.add(CLASS_NAME_FADE) - } - - document.body.appendChild(this._backdrop) - - EventHandler.on(this._element, EVENT_CLICK_DISMISS, event => { - if (this._ignoreBackdropClick) { - this._ignoreBackdropClick = false - return - } - - if (event.target !== event.currentTarget) { - return - } - - if (this._config.backdrop === 'static') { - this._triggerBackdropTransition() - } else { - this.hide() - } - }) - - if (isAnimated) { - reflow(this._backdrop) + EventHandler.on(this._element, EVENT_CLICK_DISMISS, event => { + if (this._ignoreBackdropClick) { + this._ignoreBackdropClick = false + return } - this._backdrop.classList.add(CLASS_NAME_SHOW) - - if (!isAnimated) { - callback() + if (event.target !== event.currentTarget) { return } - const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop) - - EventHandler.one(this._backdrop, 'transitionend', callback) - emulateTransitionEnd(this._backdrop, backdropTransitionDuration) - } else if (!this._isShown && this._backdrop) { - this._backdrop.classList.remove(CLASS_NAME_SHOW) - - const callbackRemove = () => { - this._removeBackdrop() - callback() + if (this._config.backdrop === true) { + this.hide() + } else if (this._config.backdrop === 'static') { + this._triggerBackdropTransition() } + }) - if (isAnimated) { - const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop) - EventHandler.one(this._backdrop, 'transitionend', callbackRemove) - emulateTransitionEnd(this._backdrop, backdropTransitionDuration) - } else { - callbackRemove() - } - } else { - callback() - } + this._backdrop.show(callback) } _isAnimated() { -- cgit v1.2.3 From bf0936748602c8109fd916c64b4560799fa1c3f8 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Wed, 5 May 2021 22:32:12 +0300 Subject: Release v5.0.0 (#33647) * Bump version to 5.0.0 * Fix npm tag * Dist --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index fabb151cb..773e4263f 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.0-beta3): modal.js + * Bootstrap (v5.0.0): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ -- cgit v1.2.3 From 90b1a6907ed7bb3397fe6bd223f09eb12122d7a3 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Sun, 11 Apr 2021 02:27:18 +0300 Subject: Merge js-components 'transitionend' listener callbacks into one method --- js/src/modal.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 773e4263f..6701c896f 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -176,14 +176,7 @@ class Modal extends BaseComponent { EventHandler.off(this._element, EVENT_CLICK_DISMISS) EventHandler.off(this._dialog, EVENT_MOUSEDOWN_DISMISS) - if (isAnimated) { - const transitionDuration = getTransitionDurationFromElement(this._element) - - EventHandler.one(this._element, 'transitionend', event => this._hideModal(event)) - emulateTransitionEnd(this._element, transitionDuration) - } else { - this._hideModal() - } + this._queueCallback(() => this._hideModal(), this._element, isAnimated) } dispose() { @@ -271,14 +264,7 @@ class Modal extends BaseComponent { }) } - if (isAnimated) { - const transitionDuration = getTransitionDurationFromElement(this._dialog) - - EventHandler.one(this._dialog, 'transitionend', transitionComplete) - emulateTransitionEnd(this._dialog, transitionDuration) - } else { - transitionComplete() - } + this._queueCallback(transitionComplete, this._dialog, isAnimated) } _enforceFocus() { -- cgit v1.2.3 From 03842b5f259d6007db02c465e6c55929e551e9cd Mon Sep 17 00:00:00 2001 From: GeoSot Date: Tue, 11 May 2021 09:04:42 +0300 Subject: Refactor: move disposing properties into the base class (#33740) Moves more functionality to `base-component`, transferring the responsibility of disposal to parent class. Each component, dusting disposal, sets its protected properties to `null`. So the same can be done in one place for all children components . --- js/src/modal.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 6701c896f..44f2a0cbb 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -183,6 +183,7 @@ class Modal extends BaseComponent { [window, this._dialog] .forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY)) + this._backdrop.dispose() super.dispose() /** @@ -191,14 +192,6 @@ class Modal extends BaseComponent { * It will remove `EVENT_CLICK_DATA_API` event that should remain */ EventHandler.off(document, EVENT_FOCUSIN) - - this._config = null - this._dialog = null - this._backdrop.dispose() - this._backdrop = null - this._isShown = null - this._ignoreBackdropClick = null - this._isTransitioning = null } handleUpdate() { -- cgit v1.2.3 From 9fe36edf683af02574bf6bbd6c9b27de93bd31b1 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Tue, 11 May 2021 10:49:30 +0300 Subject: Extract static `DATA_KEY` & `EVENT_KEY` to base-component (#33635) * Force each plugin that extends base-components to implement a static method `NAME()` * Remove redundant `NAME` argument from 'Utils.defineJQueryPlugin' & fix test --- js/src/modal.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 44f2a0cbb..058d4a36b 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -93,8 +93,8 @@ class Modal extends BaseComponent { return Default } - static get DATA_KEY() { - return DATA_KEY + static get NAME() { + return NAME } // Public @@ -441,6 +441,6 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( * add .Modal to jQuery only if jQuery is present */ -defineJQueryPlugin(NAME, Modal) +defineJQueryPlugin(Modal) export default Modal -- cgit v1.2.3 From 58b1be927f43c779377e478df2d119f2ddf956ca Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Thu, 13 May 2021 19:22:20 +0300 Subject: Release v5.0.1 (#33972) * Bump version to 5.0.1. * Dist --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 058d4a36b..d4436bf4f 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.0): modal.js + * Bootstrap (v5.0.1): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ -- cgit v1.2.3 From 2757fbe28e1039fb629f4c289aacf4f1cc6009c2 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Tue, 18 May 2021 09:26:22 +0300 Subject: Reset inside a Dialog does not work if `data-dismiss="modal"` is set (#33928) --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index d4436bf4f..2dc7e75d9 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -145,7 +145,7 @@ class Modal extends BaseComponent { } hide(event) { - if (event) { + if (event && ['A', 'AREA'].includes(event.target.tagName)) { event.preventDefault() } -- cgit v1.2.3 From b513a19003815b9c300df6b54419fa0123bff9c6 Mon Sep 17 00:00:00 2001 From: alpadev <2838324+alpadev@users.noreply.github.com> Date: Mon, 24 May 2021 17:52:36 +0200 Subject: Fix prevented show event disables modals with fade class from being displayed again (#34085) Fix modal, in case is faded, a prevented show event can cause show method to not be executed again. --- js/src/modal.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 2dc7e75d9..b05fe8de7 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -108,20 +108,20 @@ class Modal extends BaseComponent { return } - if (this._isAnimated()) { - this._isTransitioning = true - } - const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { relatedTarget }) - if (this._isShown || showEvent.defaultPrevented) { + if (showEvent.defaultPrevented) { return } this._isShown = true + if (this._isAnimated()) { + this._isTransitioning = true + } + scrollBarHide() document.body.classList.add(CLASS_NAME_OPEN) -- cgit v1.2.3 From 4a5029ea29ac75243dfec68153051292fc70f5cf Mon Sep 17 00:00:00 2001 From: alpadev <2838324+alpadev@users.noreply.github.com> Date: Thu, 3 Jun 2021 13:44:16 +0200 Subject: Fix handling of transitionend events dispatched by nested elements(#33845) Fix handling of transitionend events dispatched by nested elements Properly handle events from nested elements Change `emulateTransitionEnd` to `executeAfterTransition` && --- js/src/modal.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index b05fe8de7..e8eee3b4d 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -7,9 +7,7 @@ import { defineJQueryPlugin, - emulateTransitionEnd, getElementFromSelector, - getTransitionDurationFromElement, isRTL, isVisible, reflow, @@ -339,25 +337,28 @@ class Modal extends BaseComponent { return } - const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight + const { classList, scrollHeight, style } = this._element + const isModalOverflowing = scrollHeight > document.documentElement.clientHeight + + // return if the following background transition hasn't yet completed + if ((!isModalOverflowing && style.overflowY === 'hidden') || classList.contains(CLASS_NAME_STATIC)) { + return + } if (!isModalOverflowing) { - this._element.style.overflowY = 'hidden' + style.overflowY = 'hidden' } - this._element.classList.add(CLASS_NAME_STATIC) - const modalTransitionDuration = getTransitionDurationFromElement(this._dialog) - EventHandler.off(this._element, 'transitionend') - EventHandler.one(this._element, 'transitionend', () => { - this._element.classList.remove(CLASS_NAME_STATIC) + classList.add(CLASS_NAME_STATIC) + this._queueCallback(() => { + classList.remove(CLASS_NAME_STATIC) if (!isModalOverflowing) { - EventHandler.one(this._element, 'transitionend', () => { - this._element.style.overflowY = '' - }) - emulateTransitionEnd(this._element, modalTransitionDuration) + this._queueCallback(() => { + style.overflowY = '' + }, this._dialog) } - }) - emulateTransitionEnd(this._element, modalTransitionDuration) + }, this._dialog) + this._element.focus() } -- cgit v1.2.3 From c98657b8303150bfda3bdea750055b83a29b27a3 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Thu, 3 Jun 2021 18:53:27 +0300 Subject: Add `getOrCreateInstance` method in base-component (#33276) Co-authored-by: Rohit Sharma Co-authored-by: XhmikosR --- js/src/modal.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index e8eee3b4d..74b608303 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -209,7 +209,7 @@ class Modal extends BaseComponent { config = { ...Default, ...Manipulator.getDataAttributes(this._element), - ...config + ...(typeof config === 'object' ? config : {}) } typeCheckConfig(NAME, config, DefaultType) return config @@ -389,7 +389,7 @@ class Modal extends BaseComponent { static jQueryInterface(config, relatedTarget) { return this.each(function () { - const data = Modal.getInstance(this) || new Modal(this, typeof config === 'object' ? config : {}) + const data = Modal.getOrCreateInstance(this, config) if (typeof config !== 'string') { return @@ -430,7 +430,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( }) }) - const data = Modal.getInstance(target) || new Modal(target) + const data = Modal.getOrCreateInstance(target) data.toggle(this) }) -- cgit v1.2.3 From cb47b8c9640abcc19c17908475153849b9d4ad60 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Sun, 6 Jun 2021 09:26:36 +0300 Subject: Refactor scrollbar.js to be used as a Class (#33947) --- js/src/modal.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 74b608303..1d23b3d89 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -16,7 +16,7 @@ import { import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' import SelectorEngine from './dom/selector-engine' -import { getWidth as getScrollBarWidth, hide as scrollBarHide, reset as scrollBarReset } from './util/scrollbar' +import ScrollBarHelper from './util/scrollbar' import BaseComponent from './base-component' import Backdrop from './util/backdrop' @@ -83,6 +83,7 @@ class Modal extends BaseComponent { this._isShown = false this._ignoreBackdropClick = false this._isTransitioning = false + this._scrollBar = new ScrollBarHelper() } // Getters @@ -120,7 +121,7 @@ class Modal extends BaseComponent { this._isTransitioning = true } - scrollBarHide() + this._scrollBar.hide() document.body.classList.add(CLASS_NAME_OPEN) @@ -301,7 +302,7 @@ class Modal extends BaseComponent { this._backdrop.hide(() => { document.body.classList.remove(CLASS_NAME_OPEN) this._resetAdjustments() - scrollBarReset() + this._scrollBar.reset() EventHandler.trigger(this._element, EVENT_HIDDEN) }) } @@ -368,7 +369,7 @@ class Modal extends BaseComponent { _adjustDialog() { const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight - const scrollbarWidth = getScrollBarWidth() + const scrollbarWidth = this._scrollBar.getWidth() const isBodyOverflowing = scrollbarWidth > 0 if ((!isBodyOverflowing && isModalOverflowing && !isRTL()) || (isBodyOverflowing && !isModalOverflowing && isRTL())) { -- cgit v1.2.3 From 688bce4fa695cc360a0d084e34f029b0c192b223 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Tue, 22 Jun 2021 21:29:16 +0300 Subject: Release v5.0.2 (#34276) * Bump version to v5.0.2. * Dist --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 1d23b3d89..8dac75265 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.1): modal.js + * Bootstrap (v5.0.2): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ -- cgit v1.2.3 From dfafb9a60c5f15d341fc8992542aead014114058 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Mon, 19 Jul 2021 16:56:05 +0300 Subject: modal: change `data-dismiss` so that it can be outside of a modal using `bs-target` (#33403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change data-dismiss, so can be outside modal, using a bs-target * Update site/content/docs/5.0/components/modal.md Co-authored-by: Gaël Poupard --- js/src/modal.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 8dac75265..0e8346d6f 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -62,6 +62,7 @@ const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' const CLASS_NAME_STATIC = 'modal-static' +const SELECTOR = '.modal' const SELECTOR_DIALOG = '.modal-dialog' const SELECTOR_MODAL_BODY = '.modal-body' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]' @@ -130,8 +131,6 @@ class Modal extends BaseComponent { this._setEscapeEvent() this._setResizeEvent() - EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, event => this.hide(event)) - EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, event => { if (event.target === this._element) { @@ -436,6 +435,13 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( data.toggle(this) }) +EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_DISMISS, function (event) { + const target = getElementFromSelector(this) || this.closest(SELECTOR) + const modal = Modal.getOrCreateInstance(target) + + modal.hide(event) +}) + /** * ------------------------------------------------------------------------ * jQuery -- cgit v1.2.3 From 7646f6bd33a03132e446fb060880bbf051a1639f Mon Sep 17 00:00:00 2001 From: Ryan Berliner <22206986+RyanBerliner@users.noreply.github.com> Date: Tue, 27 Jul 2021 01:01:04 -0400 Subject: Add shift-tab keyboard support for dialogs (modal & Offcanvas components) (#33865) * consolidate dialog focus trap logic * add shift-tab support to focustrap * remove redundant null check of trap element Co-authored-by: GeoSot * remove area support forom focusableChildren * fix no expectations warning in focustrap tests Co-authored-by: GeoSot Co-authored-by: XhmikosR --- js/src/modal.js | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 0e8346d6f..53a3ccfd1 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -19,6 +19,7 @@ import SelectorEngine from './dom/selector-engine' import ScrollBarHelper from './util/scrollbar' import BaseComponent from './base-component' import Backdrop from './util/backdrop' +import FocusTrap from './util/focustrap' /** * ------------------------------------------------------------------------ @@ -49,7 +50,6 @@ const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}` const EVENT_HIDDEN = `hidden${EVENT_KEY}` const EVENT_SHOW = `show${EVENT_KEY}` const EVENT_SHOWN = `shown${EVENT_KEY}` -const EVENT_FOCUSIN = `focusin${EVENT_KEY}` const EVENT_RESIZE = `resize${EVENT_KEY}` const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}` const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}` @@ -81,6 +81,7 @@ class Modal extends BaseComponent { this._config = this._getConfig(config) this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element) this._backdrop = this._initializeBackDrop() + this._focustrap = this._initializeFocusTrap() this._isShown = false this._ignoreBackdropClick = false this._isTransitioning = false @@ -167,7 +168,7 @@ class Modal extends BaseComponent { this._setEscapeEvent() this._setResizeEvent() - EventHandler.off(document, EVENT_FOCUSIN) + this._focustrap.deactivate() this._element.classList.remove(CLASS_NAME_SHOW) @@ -182,14 +183,8 @@ class Modal extends BaseComponent { .forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY)) this._backdrop.dispose() + this._focustrap.deactivate() super.dispose() - - /** - * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API` - * Do not move `document` in `htmlElements` array - * It will remove `EVENT_CLICK_DATA_API` event that should remain - */ - EventHandler.off(document, EVENT_FOCUSIN) } handleUpdate() { @@ -205,6 +200,12 @@ class Modal extends BaseComponent { }) } + _initializeFocusTrap() { + return new FocusTrap({ + trapElement: this._element + }) + } + _getConfig(config) { config = { ...Default, @@ -240,13 +241,9 @@ class Modal extends BaseComponent { this._element.classList.add(CLASS_NAME_SHOW) - if (this._config.focus) { - this._enforceFocus() - } - const transitionComplete = () => { if (this._config.focus) { - this._element.focus() + this._focustrap.activate() } this._isTransitioning = false @@ -258,17 +255,6 @@ class Modal extends BaseComponent { this._queueCallback(transitionComplete, this._dialog, isAnimated) } - _enforceFocus() { - EventHandler.off(document, EVENT_FOCUSIN) // guard against infinite focus loop - EventHandler.on(document, EVENT_FOCUSIN, event => { - if (document !== event.target && - this._element !== event.target && - !this._element.contains(event.target)) { - this._element.focus() - } - }) - } - _setEscapeEvent() { if (this._isShown) { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { -- cgit v1.2.3 From 4bfd8a2cbcb10610b4078cefa45756b4a96301a0 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Wed, 28 Jul 2021 17:39:32 +0300 Subject: Use a streamlined way to trigger component dismiss (#34170) * use a streamlined way to trigger component dismiss * add documentation Co-authored-by: XhmikosR --- js/src/modal.js | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 53a3ccfd1..bb8d97e48 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -20,6 +20,7 @@ import ScrollBarHelper from './util/scrollbar' import BaseComponent from './base-component' import Backdrop from './util/backdrop' import FocusTrap from './util/focustrap' +import { enableDismissTrigger } from './util/component-functions' /** * ------------------------------------------------------------------------ @@ -62,11 +63,9 @@ const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' const CLASS_NAME_STATIC = 'modal-static' -const SELECTOR = '.modal' const SELECTOR_DIALOG = '.modal-dialog' const SELECTOR_MODAL_BODY = '.modal-body' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]' -const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]' /** * ------------------------------------------------------------------------ @@ -143,11 +142,7 @@ class Modal extends BaseComponent { this._showBackdrop(() => this._showElement(relatedTarget)) } - hide(event) { - if (event && ['A', 'AREA'].includes(event.target.tagName)) { - event.preventDefault() - } - + hide() { if (!this._isShown || this._isTransitioning) { return } @@ -421,12 +416,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( data.toggle(this) }) -EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_DISMISS, function (event) { - const target = getElementFromSelector(this) || this.closest(SELECTOR) - const modal = Modal.getOrCreateInstance(target) - - modal.hide(event) -}) +enableDismissTrigger(Modal) /** * ------------------------------------------------------------------------ -- cgit v1.2.3 From 6d707f4801750f1454351d6afe93a80ce4516d1a Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Fri, 30 Jul 2021 01:23:00 +0300 Subject: Enable a few eslint-config-xo rules (#34620) * unicorn/prefer-dom-node-append * unicorn/prefer-dom-node-remove --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index bb8d97e48..097ecd656 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -217,7 +217,7 @@ class Modal extends BaseComponent { if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { // Don't move modal's DOM position - document.body.appendChild(this._element) + document.body.append(this._element) } this._element.style.display = 'block' -- cgit v1.2.3 From f20fece3a8cdd0e76a42c2737524b7652bf54d26 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Wed, 4 Aug 2021 18:41:51 +0300 Subject: Prepare v5.1.0. (#34674) --- js/src/modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 097ecd656..8453dbc9d 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): modal.js + * Bootstrap (v5.1.0): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ -- cgit v1.2.3 From 1e5e65567049cc5a7521530fbc1149f8c35b96f9 Mon Sep 17 00:00:00 2001 From: GeoSot Date: Tue, 10 Aug 2021 17:55:34 +0300 Subject: Fix modal when is triggered by `bs-toggle`, to hide other open instances (#34701) --- js/src/modal.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'js/src/modal.js') diff --git a/js/src/modal.js b/js/src/modal.js index 8453dbc9d..7d44c31e8 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -63,6 +63,7 @@ const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' const CLASS_NAME_STATIC = 'modal-static' +const OPEN_SELECTOR = '.modal.show' const SELECTOR_DIALOG = '.modal-dialog' const SELECTOR_MODAL_BODY = '.modal-body' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]' @@ -411,6 +412,12 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( }) }) + // avoid conflict when clicking moddal toggler while another one is open + const allReadyOpen = SelectorEngine.findOne(OPEN_SELECTOR) + if (allReadyOpen) { + Modal.getInstance(allReadyOpen).hide() + } + const data = Modal.getOrCreateInstance(target) data.toggle(this) -- cgit v1.2.3