diff options
Diffstat (limited to 'vendor/twbs/bootstrap/js/dist/modal.js')
-rw-r--r-- | vendor/twbs/bootstrap/js/dist/modal.js | 260 |
1 files changed, 207 insertions, 53 deletions
diff --git a/vendor/twbs/bootstrap/js/dist/modal.js b/vendor/twbs/bootstrap/js/dist/modal.js index f26ae4c2c..d327a56dc 100644 --- a/vendor/twbs/bootstrap/js/dist/modal.js +++ b/vendor/twbs/bootstrap/js/dist/modal.js @@ -1,21 +1,27 @@ /*! - * Bootstrap modal.js v5.0.2 (https://getbootstrap.com/) + * Bootstrap modal.js v5.1.1 (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/selector-engine.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./base-component.js')) : - typeof define === 'function' && define.amd ? define(['./dom/selector-engine', './dom/event-handler', './dom/manipulator', './base-component'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Modal = factory(global.SelectorEngine, global.EventHandler, global.Manipulator, global.Base)); -}(this, (function (SelectorEngine, EventHandler, Manipulator, 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 SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine); var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler); var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator); + var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine); var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent); + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.1): util/index.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ const MILLISECONDS_MULTIPLIER = 1000; const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) @@ -102,7 +108,7 @@ } if (typeof obj === 'string' && obj.length > 0) { - return SelectorEngine__default['default'].findOne(obj); + return document.querySelector(obj); } return null; @@ -128,7 +134,35 @@ return getComputedStyle(element).getPropertyValue('visibility') === 'visible'; }; - const reflow = element => element.offsetHeight; + const isDisabled = element => { + if (!element || element.nodeType !== Node.ELEMENT_NODE) { + return true; + } + + if (element.classList.contains('disabled')) { + return true; + } + + 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 + */ + + + const reflow = element => { + // eslint-disable-next-line no-unused-expressions + element.offsetHeight; + }; const getjQuery = () => { const { @@ -218,7 +252,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): util/scrollBar.js + * Bootstrap (v5.1.1): util/scrollBar.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -322,11 +356,12 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): util/backdrop.js + * Bootstrap (v5.1.1): util/backdrop.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ - const Default$1 = { + const Default$2 = { + className: 'modal-backdrop', isVisible: true, // if false, we use the backdrop helper without adding any element to the dom isAnimated: false, @@ -334,17 +369,17 @@ // give the choice to place backdrop under different elements clickCallback: null }; - const DefaultType$1 = { + const DefaultType$2 = { + className: 'string', isVisible: 'boolean', isAnimated: 'boolean', rootElement: '(element|string)', clickCallback: '(function|null)' }; - const NAME$1 = 'backdrop'; - const CLASS_NAME_BACKDROP = 'modal-backdrop'; + const NAME$2 = 'backdrop'; const CLASS_NAME_FADE$1 = 'fade'; const CLASS_NAME_SHOW$1 = 'show'; - const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$1}`; + const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$2}`; class Backdrop { constructor(config) { @@ -390,7 +425,7 @@ _getElement() { if (!this._element) { const backdrop = document.createElement('div'); - backdrop.className = CLASS_NAME_BACKDROP; + backdrop.className = this._config.className; if (this._config.isAnimated) { backdrop.classList.add(CLASS_NAME_FADE$1); @@ -403,12 +438,12 @@ } _getConfig(config) { - config = { ...Default$1, + 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$1, config, DefaultType$1); + typeCheckConfig(NAME$2, config, DefaultType$2); return config; } @@ -417,7 +452,7 @@ return; } - this._config.rootElement.appendChild(this._getElement()); + this._config.rootElement.append(this._getElement()); EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => { execute(this._config.clickCallback); @@ -445,7 +480,136 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): modal.js + * Bootstrap (v5.1.1): 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.1): 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.1): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -475,7 +639,6 @@ 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}`; @@ -486,10 +649,10 @@ 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"]'; - const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]'; /** * ------------------------------------------------------------------------ * Class Definition @@ -502,6 +665,7 @@ 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; @@ -551,7 +715,6 @@ this._setResizeEvent(); - EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, event => this.hide(event)); EventHandler__default['default'].on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { EventHandler__default['default'].one(this._element, EVENT_MOUSEUP_DISMISS, event => { if (event.target === this._element) { @@ -563,11 +726,7 @@ this._showBackdrop(() => this._showElement(relatedTarget)); } - hide(event) { - if (event && ['A', 'AREA'].includes(event.target.tagName)) { - event.preventDefault(); - } - + hide() { if (!this._isShown || this._isTransitioning) { return; } @@ -590,7 +749,7 @@ this._setResizeEvent(); - EventHandler__default['default'].off(document, EVENT_FOCUSIN); + this._focustrap.deactivate(); this._element.classList.remove(CLASS_NAME_SHOW); @@ -605,14 +764,9 @@ this._backdrop.dispose(); - 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 - */ + this._focustrap.deactivate(); - EventHandler__default['default'].off(document, EVENT_FOCUSIN); + super.dispose(); } handleUpdate() { @@ -628,6 +782,12 @@ }); } + _initializeFocusTrap() { + return new FocusTrap({ + trapElement: this._element + }); + } + _getConfig(config) { config = { ...Default, ...Manipulator__default['default'].getDataAttributes(this._element), @@ -644,7 +804,7 @@ 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'; @@ -667,13 +827,9 @@ 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; @@ -685,16 +841,6 @@ this._queueCallback(transitionComplete, this._dialog, isAnimated); } - _enforceFocus() { - EventHandler__default['default'].off(document, EVENT_FOCUSIN); // guard against infinite focus loop - - EventHandler__default['default'].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__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, event => { @@ -869,10 +1015,18 @@ this.focus(); } }); - }); + }); // avoid conflict when clicking moddal toggler while another one is open + + const allReadyOpen = SelectorEngine__default['default'].findOne(OPEN_SELECTOR); + + if (allReadyOpen) { + Modal.getInstance(allReadyOpen).hide(); + } + const data = Modal.getOrCreateInstance(target); data.toggle(this); }); + enableDismissTrigger(Modal); /** * ------------------------------------------------------------------------ * jQuery |