diff options
| author | XhmikosR <[email protected]> | 2021-08-18 07:29:56 +0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-08-18 07:29:56 +0300 |
| commit | 433a148c9e61aa942801fd8101dfa5c4045fdaed (patch) | |
| tree | f41db59fd06019169df5ea0338213ec0e298f226 /js/dist/modal.js | |
| parent | b97cfa163b5098db70e03b27c91fca5dde9c267e (diff) | |
| parent | 18b3e1ac71f73d006756684a285c5a818e2d1454 (diff) | |
| download | bootstrap-global-focus-vars.tar.xz bootstrap-global-focus-vars.zip | |
Merge branch 'main' into global-focus-varsglobal-focus-vars
Diffstat (limited to 'js/dist/modal.js')
| -rw-r--r-- | js/dist/modal.js | 1196 |
1 files changed, 695 insertions, 501 deletions
diff --git a/js/dist/modal.js b/js/dist/modal.js index 6f34c2b1c..79779a84e 100644 --- a/js/dist/modal.js +++ b/js/dist/modal.js @@ -1,94 +1,43 @@ /*! - * Bootstrap modal.js v5.0.0-beta2 (https://getbootstrap.com/) + * Bootstrap modal.js v5.1.0 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) : - typeof define === 'function' && define.amd ? define(['./dom/data', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Modal = factory(global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base)); -}(this, (function (Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict'; + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) : + typeof define === 'function' && define.amd ? define(['./dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Modal = factory(global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base)); +}(this, (function (EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict'; function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data); var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler); var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator); var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine); var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent); - function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; - } - - function _extends() { - _extends = Object.assign || function (target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target; - }; - - return _extends.apply(this, arguments); - } - - function _inheritsLoose(subClass, superClass) { - subClass.prototype = Object.create(superClass.prototype); - subClass.prototype.constructor = subClass; - - _setPrototypeOf(subClass, superClass); - } - - function _setPrototypeOf(o, p) { - _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { - o.__proto__ = p; - return o; - }; - - return _setPrototypeOf(o, p); - } - /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.0-beta2): util/index.js + * Bootstrap (v5.1.0): util/index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ - var MILLISECONDS_MULTIPLIER = 1000; - var TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) + const MILLISECONDS_MULTIPLIER = 1000; + const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) - var toType = function toType(obj) { + const toType = obj => { if (obj === null || obj === undefined) { - return "" + obj; + return `${obj}`; } return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); }; - var getSelector = function getSelector(element) { - var selector = element.getAttribute('data-bs-target'); + const getSelector = element => { + let selector = element.getAttribute('data-bs-target'); if (!selector || selector === '#') { - var hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes, + let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes, // so everything starting with `#` or `.`. If a "real" URL is used as the selector, // `document.querySelector` will rightfully complain it is invalid. // See https://github.com/twbs/bootstrap/issues/32273 @@ -99,7 +48,7 @@ if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) { - hrefAttr = '#' + hrefAttr.split('#')[1]; + hrefAttr = `#${hrefAttr.split('#')[1]}`; } selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null; @@ -108,23 +57,23 @@ return selector; }; - var getElementFromSelector = function getElementFromSelector(element) { - var selector = getSelector(element); + const getElementFromSelector = element => { + const selector = getSelector(element); return selector ? document.querySelector(selector) : null; }; - var getTransitionDurationFromElement = function getTransitionDurationFromElement(element) { + const getTransitionDurationFromElement = element => { if (!element) { return 0; } // Get transition-duration of the element - var _window$getComputedSt = window.getComputedStyle(element), - transitionDuration = _window$getComputedSt.transitionDuration, - transitionDelay = _window$getComputedSt.transitionDelay; - - var floatTransitionDuration = Number.parseFloat(transitionDuration); - var floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found + let { + transitionDuration, + transitionDelay + } = window.getComputedStyle(element); + const floatTransitionDuration = Number.parseFloat(transitionDuration); + const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found if (!floatTransitionDuration && !floatTransitionDelay) { return 0; @@ -136,65 +85,89 @@ return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; }; - var triggerTransitionEnd = function triggerTransitionEnd(element) { + const triggerTransitionEnd = element => { element.dispatchEvent(new Event(TRANSITION_END)); }; - var isElement = function isElement(obj) { - return (obj[0] || obj).nodeType; + const isElement = obj => { + if (!obj || typeof obj !== 'object') { + return false; + } + + if (typeof obj.jquery !== 'undefined') { + obj = obj[0]; + } + + return typeof obj.nodeType !== 'undefined'; }; - var emulateTransitionEnd = function emulateTransitionEnd(element, duration) { - var called = false; - var durationPadding = 5; - var emulatedDuration = duration + durationPadding; + const getElement = obj => { + if (isElement(obj)) { + // it's a jQuery object or a node element + return obj.jquery ? obj[0] : obj; + } - function listener() { - called = true; - element.removeEventListener(TRANSITION_END, listener); + if (typeof obj === 'string' && obj.length > 0) { + return document.querySelector(obj); } - element.addEventListener(TRANSITION_END, listener); - setTimeout(function () { - if (!called) { - triggerTransitionEnd(element); - } - }, emulatedDuration); + return null; }; - var typeCheckConfig = function typeCheckConfig(componentName, config, configTypes) { - Object.keys(configTypes).forEach(function (property) { - var expectedTypes = configTypes[property]; - var value = config[property]; - var valueType = value && isElement(value) ? 'element' : toType(value); + const typeCheckConfig = (componentName, config, configTypes) => { + Object.keys(configTypes).forEach(property => { + const expectedTypes = configTypes[property]; + const value = config[property]; + const valueType = value && isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { - throw new TypeError(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); + throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); } }); }; - var isVisible = function isVisible(element) { - if (!element) { + const isVisible = element => { + if (!isElement(element) || element.getClientRects().length === 0) { return false; } - if (element.style && element.parentNode && element.parentNode.style) { - var elementStyle = getComputedStyle(element); - var parentNodeStyle = getComputedStyle(element.parentNode); - return elementStyle.display !== 'none' && parentNodeStyle.display !== 'none' && elementStyle.visibility !== 'hidden'; + return getComputedStyle(element).getPropertyValue('visibility') === 'visible'; + }; + + const isDisabled = element => { + if (!element || element.nodeType !== Node.ELEMENT_NODE) { + return true; + } + + if (element.classList.contains('disabled')) { + return true; } - return false; + if (typeof element.disabled !== 'undefined') { + return element.disabled; + } + + return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; }; + /** + * Trick to restart an element's animation + * + * @param {HTMLElement} element + * @return void + * + * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation + */ + - var reflow = function reflow(element) { - return element.offsetHeight; + const reflow = element => { + // eslint-disable-next-line no-unused-expressions + element.offsetHeight; }; - var getjQuery = function getjQuery() { - var _window = window, - jQuery = _window.jQuery; + const getjQuery = () => { + const { + jQuery + } = window; if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { return jQuery; @@ -203,27 +176,37 @@ return null; }; - var onDOMContentLoaded = function onDOMContentLoaded(callback) { + const DOMContentLoadedCallbacks = []; + + const onDOMContentLoaded = callback => { if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', callback); + // add listener on the first call when the document is in loading state + if (!DOMContentLoadedCallbacks.length) { + document.addEventListener('DOMContentLoaded', () => { + DOMContentLoadedCallbacks.forEach(callback => callback()); + }); + } + + DOMContentLoadedCallbacks.push(callback); } else { callback(); } }; - var isRTL = document.documentElement.dir === 'rtl'; + const isRTL = () => document.documentElement.dir === 'rtl'; - var defineJQueryPlugin = function defineJQueryPlugin(name, plugin) { - onDOMContentLoaded(function () { - var $ = getjQuery(); + const defineJQueryPlugin = plugin => { + onDOMContentLoaded(() => { + const $ = getjQuery(); /* istanbul ignore if */ if ($) { - var JQUERY_NO_CONFLICT = $.fn[name]; + const name = plugin.NAME; + const JQUERY_NO_CONFLICT = $.fn[name]; $.fn[name] = plugin.jQueryInterface; $.fn[name].Constructor = plugin; - $.fn[name].noConflict = function () { + $.fn[name].noConflict = () => { $.fn[name] = JQUERY_NO_CONFLICT; return plugin.jQueryInterface; }; @@ -231,107 +214,499 @@ }); }; + const execute = callback => { + if (typeof callback === 'function') { + callback(); + } + }; + + const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { + if (!waitForTransition) { + execute(callback); + return; + } + + const durationPadding = 5; + const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding; + let called = false; + + const handler = ({ + target + }) => { + if (target !== transitionElement) { + return; + } + + called = true; + transitionElement.removeEventListener(TRANSITION_END, handler); + execute(callback); + }; + + transitionElement.addEventListener(TRANSITION_END, handler); + setTimeout(() => { + if (!called) { + triggerTransitionEnd(transitionElement); + } + }, emulatedDuration); + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.0): util/scrollBar.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; + const SELECTOR_STICKY_CONTENT = '.sticky-top'; + + class ScrollBarHelper { + constructor() { + this._element = document.body; + } + + getWidth() { + // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes + const documentWidth = document.documentElement.clientWidth; + return Math.abs(window.innerWidth - documentWidth); + } + + hide() { + const width = this.getWidth(); + + this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width + + + this._setElementAttributes(this._element, 'paddingRight', calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth + + + this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width); + + this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width); + } + + _disableOverFlow() { + this._saveInitialAttribute(this._element, 'overflow'); + + this._element.style.overflow = 'hidden'; + } + + _setElementAttributes(selector, styleProp, callback) { + const scrollbarWidth = this.getWidth(); + + const manipulationCallBack = element => { + if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { + return; + } + + this._saveInitialAttribute(element, styleProp); + + const calculatedValue = window.getComputedStyle(element)[styleProp]; + element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`; + }; + + this._applyManipulationCallback(selector, manipulationCallBack); + } + + reset() { + this._resetElementAttributes(this._element, 'overflow'); + + this._resetElementAttributes(this._element, 'paddingRight'); + + this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight'); + + this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight'); + } + + _saveInitialAttribute(element, styleProp) { + const actualValue = element.style[styleProp]; + + if (actualValue) { + Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue); + } + } + + _resetElementAttributes(selector, styleProp) { + const manipulationCallBack = element => { + const value = Manipulator__default['default'].getDataAttribute(element, styleProp); + + if (typeof value === 'undefined') { + element.style.removeProperty(styleProp); + } else { + Manipulator__default['default'].removeDataAttribute(element, styleProp); + element.style[styleProp] = value; + } + }; + + this._applyManipulationCallback(selector, manipulationCallBack); + } + + _applyManipulationCallback(selector, callBack) { + if (isElement(selector)) { + callBack(selector); + } else { + SelectorEngine__default['default'].find(selector, this._element).forEach(callBack); + } + } + + isOverflowing() { + return this.getWidth() > 0; + } + + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.0): util/backdrop.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + const Default$2 = { + className: 'modal-backdrop', + isVisible: true, + // if false, we use the backdrop helper without adding any element to the dom + isAnimated: false, + rootElement: 'body', + // give the choice to place backdrop under different elements + clickCallback: null + }; + const DefaultType$2 = { + className: 'string', + isVisible: 'boolean', + isAnimated: 'boolean', + rootElement: '(element|string)', + clickCallback: '(function|null)' + }; + const NAME$2 = 'backdrop'; + const CLASS_NAME_FADE$1 = 'fade'; + const CLASS_NAME_SHOW$1 = 'show'; + const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$2}`; + + class Backdrop { + constructor(config) { + this._config = this._getConfig(config); + this._isAppended = false; + this._element = null; + } + + show(callback) { + if (!this._config.isVisible) { + execute(callback); + return; + } + + this._append(); + + if (this._config.isAnimated) { + reflow(this._getElement()); + } + + this._getElement().classList.add(CLASS_NAME_SHOW$1); + + this._emulateAnimation(() => { + execute(callback); + }); + } + + hide(callback) { + if (!this._config.isVisible) { + execute(callback); + return; + } + + this._getElement().classList.remove(CLASS_NAME_SHOW$1); + + this._emulateAnimation(() => { + this.dispose(); + execute(callback); + }); + } // Private + + + _getElement() { + if (!this._element) { + const backdrop = document.createElement('div'); + backdrop.className = this._config.className; + + if (this._config.isAnimated) { + backdrop.classList.add(CLASS_NAME_FADE$1); + } + + this._element = backdrop; + } + + return this._element; + } + + _getConfig(config) { + config = { ...Default$2, + ...(typeof config === 'object' ? config : {}) + }; // use getElement() with the default "body" to get a fresh Element on each instantiation + + config.rootElement = getElement(config.rootElement); + typeCheckConfig(NAME$2, config, DefaultType$2); + return config; + } + + _append() { + if (this._isAppended) { + return; + } + + this._config.rootElement.append(this._getElement()); + + EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => { + execute(this._config.clickCallback); + }); + this._isAppended = true; + } + + dispose() { + if (!this._isAppended) { + return; + } + + EventHandler__default['default'].off(this._element, EVENT_MOUSEDOWN); + + this._element.remove(); + + this._isAppended = false; + } + + _emulateAnimation(callback) { + executeAfterTransition(callback, this._getElement(), this._config.isAnimated); + } + + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.0): util/focustrap.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + const Default$1 = { + trapElement: null, + // The element to trap focus inside of + autofocus: true + }; + const DefaultType$1 = { + trapElement: 'element', + autofocus: 'boolean' + }; + const NAME$1 = 'focustrap'; + const DATA_KEY$1 = 'bs.focustrap'; + const EVENT_KEY$1 = `.${DATA_KEY$1}`; + const EVENT_FOCUSIN = `focusin${EVENT_KEY$1}`; + const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$1}`; + const TAB_KEY = 'Tab'; + const TAB_NAV_FORWARD = 'forward'; + const TAB_NAV_BACKWARD = 'backward'; + + class FocusTrap { + constructor(config) { + this._config = this._getConfig(config); + this._isActive = false; + this._lastTabNavDirection = null; + } + + activate() { + const { + trapElement, + autofocus + } = this._config; + + if (this._isActive) { + return; + } + + if (autofocus) { + trapElement.focus(); + } + + EventHandler__default['default'].off(document, EVENT_KEY$1); // guard against infinite focus loop + + EventHandler__default['default'].on(document, EVENT_FOCUSIN, event => this._handleFocusin(event)); + EventHandler__default['default'].on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)); + this._isActive = true; + } + + deactivate() { + if (!this._isActive) { + return; + } + + this._isActive = false; + EventHandler__default['default'].off(document, EVENT_KEY$1); + } // Private + + + _handleFocusin(event) { + const { + target + } = event; + const { + trapElement + } = this._config; + + if (target === document || target === trapElement || trapElement.contains(target)) { + return; + } + + const elements = SelectorEngine__default['default'].focusableChildren(trapElement); + + if (elements.length === 0) { + trapElement.focus(); + } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { + elements[elements.length - 1].focus(); + } else { + elements[0].focus(); + } + } + + _handleKeydown(event) { + if (event.key !== TAB_KEY) { + return; + } + + this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD; + } + + _getConfig(config) { + config = { ...Default$1, + ...(typeof config === 'object' ? config : {}) + }; + typeCheckConfig(NAME$1, config, DefaultType$1); + return config; + } + + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.0): util/component-functions.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + const enableDismissTrigger = (component, method = 'hide') => { + const clickEvent = `click.dismiss${component.EVENT_KEY}`; + const name = component.NAME; + EventHandler__default['default'].on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) { + if (['A', 'AREA'].includes(this.tagName)) { + event.preventDefault(); + } + + if (isDisabled(this)) { + return; + } + + const target = getElementFromSelector(this) || this.closest(`.${name}`); + const instance = component.getOrCreateInstance(target); // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method + + instance[method](); + }); + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.0): modal.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ - var NAME = 'modal'; - var DATA_KEY = 'bs.modal'; - var EVENT_KEY = "." + DATA_KEY; - var DATA_API_KEY = '.data-api'; - var ESCAPE_KEY = 'Escape'; - var Default = { + const NAME = 'modal'; + const DATA_KEY = 'bs.modal'; + const EVENT_KEY = `.${DATA_KEY}`; + const DATA_API_KEY = '.data-api'; + const ESCAPE_KEY = 'Escape'; + const Default = { backdrop: true, keyboard: true, focus: true }; - var DefaultType = { + const DefaultType = { backdrop: '(boolean|string)', keyboard: 'boolean', focus: 'boolean' }; - var EVENT_HIDE = "hide" + EVENT_KEY; - var EVENT_HIDE_PREVENTED = "hidePrevented" + EVENT_KEY; - var EVENT_HIDDEN = "hidden" + EVENT_KEY; - var EVENT_SHOW = "show" + EVENT_KEY; - var EVENT_SHOWN = "shown" + EVENT_KEY; - var EVENT_FOCUSIN = "focusin" + EVENT_KEY; - var EVENT_RESIZE = "resize" + EVENT_KEY; - var EVENT_CLICK_DISMISS = "click.dismiss" + EVENT_KEY; - var EVENT_KEYDOWN_DISMISS = "keydown.dismiss" + EVENT_KEY; - var EVENT_MOUSEUP_DISMISS = "mouseup.dismiss" + EVENT_KEY; - var EVENT_MOUSEDOWN_DISMISS = "mousedown.dismiss" + EVENT_KEY; - var EVENT_CLICK_DATA_API = "click" + EVENT_KEY + DATA_API_KEY; - var CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure'; - var CLASS_NAME_BACKDROP = 'modal-backdrop'; - var CLASS_NAME_OPEN = 'modal-open'; - var CLASS_NAME_FADE = 'fade'; - var CLASS_NAME_SHOW = 'show'; - var CLASS_NAME_STATIC = 'modal-static'; - var SELECTOR_DIALOG = '.modal-dialog'; - var SELECTOR_MODAL_BODY = '.modal-body'; - var SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]'; - var SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]'; - var SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; - var SELECTOR_STICKY_CONTENT = '.sticky-top'; + const EVENT_HIDE = `hide${EVENT_KEY}`; + 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_RESIZE = `resize${EVENT_KEY}`; + const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`; + const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`; + 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_OPEN = 'modal-open'; + const CLASS_NAME_FADE = 'fade'; + const CLASS_NAME_SHOW = 'show'; + const CLASS_NAME_STATIC = 'modal-static'; + const SELECTOR_DIALOG = '.modal-dialog'; + const SELECTOR_MODAL_BODY = '.modal-body'; + const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ - var Modal = /*#__PURE__*/function (_BaseComponent) { - _inheritsLoose(Modal, _BaseComponent); - - function Modal(element, config) { - var _this; - - _this = _BaseComponent.call(this, element) || this; - _this._config = _this._getConfig(config); - _this._dialog = SelectorEngine__default['default'].findOne(SELECTOR_DIALOG, element); - _this._backdrop = null; - _this._isShown = false; - _this._isBodyOverflowing = false; - _this._ignoreBackdropClick = false; - _this._isTransitioning = false; - _this._scrollbarWidth = 0; - return _this; + class Modal extends BaseComponent__default['default'] { + constructor(element, config) { + super(element); + this._config = this._getConfig(config); + this._dialog = SelectorEngine__default['default'].findOne(SELECTOR_DIALOG, this._element); + this._backdrop = this._initializeBackDrop(); + this._focustrap = this._initializeFocusTrap(); + this._isShown = false; + this._ignoreBackdropClick = false; + this._isTransitioning = false; + this._scrollBar = new ScrollBarHelper(); } // Getters - var _proto = Modal.prototype; + static get Default() { + return Default; + } + + static get NAME() { + return NAME; + } // Public - // Public - _proto.toggle = function toggle(relatedTarget) { - return this._isShown ? this.hide() : this.show(relatedTarget); - }; - _proto.show = function show(relatedTarget) { - var _this2 = this; + toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + } + show(relatedTarget) { if (this._isShown || this._isTransitioning) { return; } - if (this._element.classList.contains(CLASS_NAME_FADE)) { - this._isTransitioning = true; - } - - var showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW, { - relatedTarget: relatedTarget + const showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW, { + relatedTarget }); - if (this._isShown || showEvent.defaultPrevented) { + if (showEvent.defaultPrevented) { return; } this._isShown = true; - this._checkScrollbar(); + if (this._isAnimated()) { + this._isTransitioning = true; + } + + this._scrollBar.hide(); - this._setScrollbar(); + document.body.classList.add(CLASS_NAME_OPEN); this._adjustDialog(); @@ -339,34 +714,23 @@ this._setResizeEvent(); - EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, function (event) { - return _this2.hide(event); - }); - EventHandler__default['default'].on(this._dialog, EVENT_MOUSEDOWN_DISMISS, function () { - EventHandler__default['default'].one(_this2._element, EVENT_MOUSEUP_DISMISS, function (event) { - if (event.target === _this2._element) { - _this2._ignoreBackdropClick = true; + EventHandler__default['default'].on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { + EventHandler__default['default'].one(this._element, EVENT_MOUSEUP_DISMISS, event => { + if (event.target === this._element) { + this._ignoreBackdropClick = true; } }); }); - this._showBackdrop(function () { - return _this2._showElement(relatedTarget); - }); - }; - - _proto.hide = function hide(event) { - var _this3 = this; - - if (event) { - event.preventDefault(); - } + this._showBackdrop(() => this._showElement(relatedTarget)); + } + hide() { if (!this._isShown || this._isTransitioning) { return; } - var hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); + const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); if (hideEvent.defaultPrevented) { return; @@ -374,9 +738,9 @@ this._isShown = false; - var transition = this._element.classList.contains(CLASS_NAME_FADE); + const isAnimated = this._isAnimated(); - if (transition) { + if (isAnimated) { this._isTransitioning = true; } @@ -384,69 +748,62 @@ this._setResizeEvent(); - EventHandler__default['default'].off(document, EVENT_FOCUSIN); + this._focustrap.deactivate(); this._element.classList.remove(CLASS_NAME_SHOW); EventHandler__default['default'].off(this._element, EVENT_CLICK_DISMISS); EventHandler__default['default'].off(this._dialog, EVENT_MOUSEDOWN_DISMISS); - if (transition) { - var transitionDuration = getTransitionDurationFromElement(this._element); - EventHandler__default['default'].one(this._element, 'transitionend', function (event) { - return _this3._hideModal(event); - }); - emulateTransitionEnd(this._element, transitionDuration); - } else { - this._hideModal(); - } - }; + this._queueCallback(() => this._hideModal(), this._element, isAnimated); + } - _proto.dispose = function dispose() { - [window, this._element, this._dialog].forEach(function (htmlElement) { - return EventHandler__default['default'].off(htmlElement, EVENT_KEY); - }); + dispose() { + [window, this._dialog].forEach(htmlElement => EventHandler__default['default'].off(htmlElement, EVENT_KEY)); - _BaseComponent.prototype.dispose.call(this); - /** - * `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__default['default'].off(document, EVENT_FOCUSIN); - this._config = null; - this._dialog = null; - this._backdrop = null; - this._isShown = null; - this._isBodyOverflowing = null; - this._ignoreBackdropClick = null; - this._isTransitioning = null; - this._scrollbarWidth = null; - }; + this._backdrop.dispose(); - _proto.handleUpdate = function handleUpdate() { + this._focustrap.deactivate(); + + super.dispose(); + } + + handleUpdate() { this._adjustDialog(); } // Private - ; - _proto._getConfig = function _getConfig(config) { - config = _extends({}, Default, config); + + _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() + }); + } + + _initializeFocusTrap() { + return new FocusTrap({ + trapElement: this._element + }); + } + + _getConfig(config) { + config = { ...Default, + ...Manipulator__default['default'].getDataAttributes(this._element), + ...(typeof config === 'object' ? config : {}) + }; typeCheckConfig(NAME, config, DefaultType); return config; - }; - - _proto._showElement = function _showElement(relatedTarget) { - var _this4 = this; + } - var transition = this._element.classList.contains(CLASS_NAME_FADE); + _showElement(relatedTarget) { + const isAnimated = this._isAnimated(); - var modalBody = SelectorEngine__default['default'].findOne(SELECTOR_MODAL_BODY, this._dialog); + const modalBody = SelectorEngine__default['default'].findOne(SELECTOR_MODAL_BODY, this._dialog); 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'; @@ -463,81 +820,50 @@ modalBody.scrollTop = 0; } - if (transition) { + if (isAnimated) { reflow(this._element); } this._element.classList.add(CLASS_NAME_SHOW); - if (this._config.focus) { - this._enforceFocus(); - } - - var transitionComplete = function transitionComplete() { - if (_this4._config.focus) { - _this4._element.focus(); + const transitionComplete = () => { + if (this._config.focus) { + this._focustrap.activate(); } - _this4._isTransitioning = false; - EventHandler__default['default'].trigger(_this4._element, EVENT_SHOWN, { - relatedTarget: relatedTarget + this._isTransitioning = false; + EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, { + relatedTarget }); }; - if (transition) { - var transitionDuration = getTransitionDurationFromElement(this._dialog); - EventHandler__default['default'].one(this._dialog, 'transitionend', transitionComplete); - emulateTransitionEnd(this._dialog, transitionDuration); - } else { - transitionComplete(); - } - }; - - _proto._enforceFocus = function _enforceFocus() { - var _this5 = this; - - EventHandler__default['default'].off(document, EVENT_FOCUSIN); // guard against infinite focus loop - - EventHandler__default['default'].on(document, EVENT_FOCUSIN, function (event) { - if (document !== event.target && _this5._element !== event.target && !_this5._element.contains(event.target)) { - _this5._element.focus(); - } - }); - }; - - _proto._setEscapeEvent = function _setEscapeEvent() { - var _this6 = this; + this._queueCallback(transitionComplete, this._dialog, isAnimated); + } + _setEscapeEvent() { if (this._isShown) { - EventHandler__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, function (event) { - if (_this6._config.keyboard && event.key === ESCAPE_KEY) { + EventHandler__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, event => { + if (this._config.keyboard && event.key === ESCAPE_KEY) { event.preventDefault(); - - _this6.hide(); - } else if (!_this6._config.keyboard && event.key === ESCAPE_KEY) { - _this6._triggerBackdropTransition(); + this.hide(); + } else if (!this._config.keyboard && event.key === ESCAPE_KEY) { + this._triggerBackdropTransition(); } }); } else { EventHandler__default['default'].off(this._element, EVENT_KEYDOWN_DISMISS); } - }; - - _proto._setResizeEvent = function _setResizeEvent() { - var _this7 = this; + } + _setResizeEvent() { if (this._isShown) { - EventHandler__default['default'].on(window, EVENT_RESIZE, function () { - return _this7._adjustDialog(); - }); + EventHandler__default['default'].on(window, EVENT_RESIZE, () => this._adjustDialog()); } else { EventHandler__default['default'].off(window, EVENT_RESIZE); } - }; - - _proto._hideModal = function _hideModal() { - var _this8 = this; + } + _hideModal() { this._element.style.display = 'none'; this._element.setAttribute('aria-hidden', true); @@ -548,245 +874,121 @@ this._isTransitioning = false; - this._showBackdrop(function () { + this._backdrop.hide(() => { document.body.classList.remove(CLASS_NAME_OPEN); - _this8._resetAdjustments(); + this._resetAdjustments(); - _this8._resetScrollbar(); + this._scrollBar.reset(); - EventHandler__default['default'].trigger(_this8._element, EVENT_HIDDEN); + EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN); }); - }; - - _proto._removeBackdrop = function _removeBackdrop() { - this._backdrop.parentNode.removeChild(this._backdrop); - - this._backdrop = null; - }; - - _proto._showBackdrop = function _showBackdrop(callback) { - var _this9 = this; - - var animate = this._element.classList.contains(CLASS_NAME_FADE) ? CLASS_NAME_FADE : ''; - - if (this._isShown && this._config.backdrop) { - this._backdrop = document.createElement('div'); - this._backdrop.className = CLASS_NAME_BACKDROP; - - if (animate) { - this._backdrop.classList.add(animate); - } - - document.body.appendChild(this._backdrop); - EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, function (event) { - if (_this9._ignoreBackdropClick) { - _this9._ignoreBackdropClick = false; - return; - } - - if (event.target !== event.currentTarget) { - return; - } - - if (_this9._config.backdrop === 'static') { - _this9._triggerBackdropTransition(); - } else { - _this9.hide(); - } - }); + } - if (animate) { - reflow(this._backdrop); + _showBackdrop(callback) { + EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, event => { + if (this._ignoreBackdropClick) { + this._ignoreBackdropClick = false; + return; } - this._backdrop.classList.add(CLASS_NAME_SHOW); - - if (!animate) { - callback(); + if (event.target !== event.currentTarget) { return; } - var backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop); - EventHandler__default['default'].one(this._backdrop, 'transitionend', callback); - emulateTransitionEnd(this._backdrop, backdropTransitionDuration); - } else if (!this._isShown && this._backdrop) { - this._backdrop.classList.remove(CLASS_NAME_SHOW); + if (this._config.backdrop === true) { + this.hide(); + } else if (this._config.backdrop === 'static') { + this._triggerBackdropTransition(); + } + }); - var callbackRemove = function callbackRemove() { - _this9._removeBackdrop(); + this._backdrop.show(callback); + } - callback(); - }; + _isAnimated() { + return this._element.classList.contains(CLASS_NAME_FADE); + } - if (this._element.classList.contains(CLASS_NAME_FADE)) { - var _backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop); + _triggerBackdropTransition() { + const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE_PREVENTED); - EventHandler__default['default'].one(this._backdrop, 'transitionend', callbackRemove); - emulateTransitionEnd(this._backdrop, _backdropTransitionDuration); - } else { - callbackRemove(); - } - } else { - callback(); + if (hideEvent.defaultPrevented) { + return; } - }; - - _proto._triggerBackdropTransition = function _triggerBackdropTransition() { - var _this10 = this; - var hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE_PREVENTED); + const { + classList, + scrollHeight, + style + } = this._element; + const isModalOverflowing = scrollHeight > document.documentElement.clientHeight; // return if the following background transition hasn't yet completed - if (hideEvent.defaultPrevented) { + if (!isModalOverflowing && style.overflowY === 'hidden' || classList.contains(CLASS_NAME_STATIC)) { return; } - var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; - if (!isModalOverflowing) { - this._element.style.overflowY = 'hidden'; + style.overflowY = 'hidden'; } - this._element.classList.add(CLASS_NAME_STATIC); + classList.add(CLASS_NAME_STATIC); - var modalTransitionDuration = getTransitionDurationFromElement(this._dialog); - EventHandler__default['default'].off(this._element, 'transitionend'); - EventHandler__default['default'].one(this._element, 'transitionend', function () { - _this10._element.classList.remove(CLASS_NAME_STATIC); + this._queueCallback(() => { + classList.remove(CLASS_NAME_STATIC); if (!isModalOverflowing) { - EventHandler__default['default'].one(_this10._element, 'transitionend', function () { - _this10._element.style.overflowY = ''; - }); - emulateTransitionEnd(_this10._element, modalTransitionDuration); + this._queueCallback(() => { + style.overflowY = ''; + }, this._dialog); } - }); - emulateTransitionEnd(this._element, modalTransitionDuration); + }, this._dialog); this._element.focus(); } // ---------------------------------------------------------------------- // the following methods are used to handle overflowing modals // ---------------------------------------------------------------------- - ; - _proto._adjustDialog = function _adjustDialog() { - var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; - if (!this._isBodyOverflowing && isModalOverflowing && !isRTL || this._isBodyOverflowing && !isModalOverflowing && isRTL) { - this._element.style.paddingLeft = this._scrollbarWidth + "px"; - } + _adjustDialog() { + const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; - if (this._isBodyOverflowing && !isModalOverflowing && !isRTL || !this._isBodyOverflowing && isModalOverflowing && isRTL) { - this._element.style.paddingRight = this._scrollbarWidth + "px"; - } - }; + const scrollbarWidth = this._scrollBar.getWidth(); - _proto._resetAdjustments = function _resetAdjustments() { - this._element.style.paddingLeft = ''; - this._element.style.paddingRight = ''; - }; + const isBodyOverflowing = scrollbarWidth > 0; - _proto._checkScrollbar = function _checkScrollbar() { - var rect = document.body.getBoundingClientRect(); - this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth; - this._scrollbarWidth = this._getScrollbarWidth(); - }; - - _proto._setScrollbar = function _setScrollbar() { - var _this11 = this; - - if (this._isBodyOverflowing) { - this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', function (calculatedValue) { - return calculatedValue + _this11._scrollbarWidth; - }); - - this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', function (calculatedValue) { - return calculatedValue - _this11._scrollbarWidth; - }); - - this._setElementAttributes('body', 'paddingRight', function (calculatedValue) { - return calculatedValue + _this11._scrollbarWidth; - }); + if (!isBodyOverflowing && isModalOverflowing && !isRTL() || isBodyOverflowing && !isModalOverflowing && isRTL()) { + this._element.style.paddingLeft = `${scrollbarWidth}px`; } - document.body.classList.add(CLASS_NAME_OPEN); - }; - - _proto._setElementAttributes = function _setElementAttributes(selector, styleProp, callback) { - SelectorEngine__default['default'].find(selector).forEach(function (element) { - var actualValue = element.style[styleProp]; - var calculatedValue = window.getComputedStyle(element)[styleProp]; - Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue); - element.style[styleProp] = callback(Number.parseFloat(calculatedValue)) + 'px'; - }); - }; - - _proto._resetScrollbar = function _resetScrollbar() { - this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight'); - - this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight'); - - this._resetElementAttributes('body', 'paddingRight'); - }; - - _proto._resetElementAttributes = function _resetElementAttributes(selector, styleProp) { - SelectorEngine__default['default'].find(selector).forEach(function (element) { - var value = Manipulator__default['default'].getDataAttribute(element, styleProp); - - if (typeof value === 'undefined' && element === document.body) { - element.style[styleProp] = ''; - } else { - Manipulator__default['default'].removeDataAttribute(element, styleProp); - element.style[styleProp] = value; - } - }); - }; + if (isBodyOverflowing && !isModalOverflowing && !isRTL() || !isBodyOverflowing && isModalOverflowing && isRTL()) { + this._element.style.paddingRight = `${scrollbarWidth}px`; + } + } - _proto._getScrollbarWidth = function _getScrollbarWidth() { - // thx d.walsh - var scrollDiv = document.createElement('div'); - scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER; - document.body.appendChild(scrollDiv); - var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - return scrollbarWidth; + _resetAdjustments() { + this._element.style.paddingLeft = ''; + this._element.style.paddingRight = ''; } // Static - ; - Modal.jQueryInterface = function jQueryInterface(config, relatedTarget) { - return this.each(function () { - var data = Data__default['default'].getData(this, DATA_KEY); - var _config = _extends({}, Default, Manipulator__default['default'].getDataAttributes(this), typeof config === 'object' && config ? config : {}); + static jQueryInterface(config, relatedTarget) { + return this.each(function () { + const data = Modal.getOrCreateInstance(this, 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}"`); } - }); - }; - _createClass(Modal, null, [{ - key: "Default", - get: function get() { - return Default; - } - }, { - key: "DATA_KEY", - get: function get() { - return DATA_KEY; - } - }]); + data[config](relatedTarget); + }); + } - return Modal; - }(BaseComponent__default['default']); + } /** * ------------------------------------------------------------------------ * Data Api implementation @@ -795,36 +997,28 @@ EventHandler__default['default'].on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { - var _this12 = this; - - var target = getElementFromSelector(this); + const target = getElementFromSelector(this); - if (this.tagName === 'A' || this.tagName === 'AREA') { + if (['A', 'AREA'].includes(this.tagName)) { event.preventDefault(); } - EventHandler__default['default'].one(target, EVENT_SHOW, function (showEvent) { + EventHandler__default['default'].one(target, EVENT_SHOW, showEvent => { if (showEvent.defaultPrevented) { // only register focus restorer if modal will actually get shown return; } - EventHandler__default['default'].one(target, EVENT_HIDDEN, function () { - if (isVisible(_this12)) { - _this12.focus(); + EventHandler__default['default'].one(target, EVENT_HIDDEN, () => { + if (isVisible(this)) { + this.focus(); } }); }); - var data = Data__default['default'].getData(target, DATA_KEY); - - if (!data) { - var config = _extends({}, Manipulator__default['default'].getDataAttributes(target), Manipulator__default['default'].getDataAttributes(this)); - - data = new Modal(target, config); - } - + const data = Modal.getOrCreateInstance(target); data.toggle(this); }); + enableDismissTrigger(Modal); /** * ------------------------------------------------------------------------ * jQuery @@ -832,7 +1026,7 @@ * add .Modal to jQuery only if jQuery is present */ - defineJQueryPlugin(NAME, Modal); + defineJQueryPlugin(Modal); return Modal; |
