release 3.10.0

This commit is contained in:
dwaju 2021-11-15 09:28:22 +01:00
parent 862c6e1b0e
commit 0fa19988ce
181 changed files with 5284 additions and 3520 deletions

View File

@ -1,5 +1,5 @@
MDB5 MDB5
Version: FREE 3.9.0 Version: FREE 3.10.0
Documentation: Documentation:
https://mdbootstrap.com/docs/standard/ https://mdbootstrap.com/docs/standard/

10
css/mdb.dark.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12
css/mdb.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
css/mdb.rtl.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -19,174 +19,28 @@
</head> </head>
<body> <body>
<!-- Start your project here--> <!-- Start your project here-->
<!-- Container for demo purpose --> <div class="container">
<div class="container my-5 py-5"> <div class="d-flex justify-content-center align-items-center" style="height: 100vh;">
<!--Counter--> <div class="text-center">
<section class="text-center"> <img
<!-- Time Counter --> class="mb-4"
<h1 class="mb-0 text-black">Black November <span class="text-danger fw-bold">Waiting List</span></h1> src="https://mdbootstrap.com/img/logo/mdb-transparent-250px.png"
<hr class="my-5"> style="width: 250px; height: 90px;"
<p class="text-black lead">All offers will be <span class="text-danger fw-bold">limited</span>. />
Don't lose your chance, be the <span class="text-danger fw-bold">first</span> to get notified.</p> <h5 class="mb-3">Thank you for using our product. We're glad you're with us.</h5>
</section> <p class="mb-3">MDB Team</p>
<!--Counter--> <a
<!-- Section: Waiting List --> class="btn btn-primary btn-lg"
<section class="my-5"> href="https://mdbootstrap.com/docs/standard/getting-started/"
<style> target="_blank"
.fw-900 { role="button"
font-weight: 900; >Start MDB tutorial</a
} >
</style>
<div class="bg-dark text-white text-center text-xl-start rounded-6">
<div class="container px-4" style="padding-top: 5rem; padding-bottom: 5rem;">
<div class="row mx-xl-1 d-flex justify-content-center justify-xl-content-start align-items-center">
<div class="col-md-10 col-lg-7 col-xl-7">
<h2 class="fs-1 fw-900">Join the waiting list <span class="text-danger fw-bold">NOW</span>
</h2>
<p class="lead fw-normal mb-4 pb-md-1 pb-xl-0 mb-xl-0">
You will only receive emails related to the Black November promotions and after the promotion is over,
you will be unsubscribed. We won't spam you.
</p>
</div>
<div class="col-md-10 col-lg-7 col-xl-5">
<div class="d-md-flex mb-3 mb-md-2 ms-xl-4">
<div class="flex-fill me-md-1 mb-3 mb-md-0">
<form action="https://app.convertkit.com/forms/2663020/subscriptions" class="seva-form formkit-form"
method="post" data-sv-form="2663020" data-uid="30443eba65" data-format="inline" data-version="5"
data-options="{&quot;settings&quot;:{&quot;after_subscribe&quot;:{&quot;action&quot;:&quot;message&quot;,&quot;success_message&quot;:&quot;Success! Now check your email to confirm your subscription.&quot;,&quot;redirect_url&quot;:&quot;https://mdbootstrap.com/confirm/&quot;},&quot;analytics&quot;:{&quot;google&quot;:null,&quot;facebook&quot;:null,&quot;segment&quot;:null,&quot;pinterest&quot;:null,&quot;sparkloop&quot;:null,&quot;googletagmanager&quot;:null},&quot;modal&quot;:{&quot;trigger&quot;:&quot;timer&quot;,&quot;scroll_percentage&quot;:null,&quot;timer&quot;:5,&quot;devices&quot;:&quot;all&quot;,&quot;show_once_every&quot;:15},&quot;powered_by&quot;:{&quot;show&quot;:false,&quot;url&quot;:&quot;https://convertkit.com?utm_campaign=poweredby&amp;utm_content=form&amp;utm_medium=referral&amp;utm_source=dynamic&quot;},&quot;recaptcha&quot;:{&quot;enabled&quot;:true},&quot;return_visitor&quot;:{&quot;action&quot;:&quot;show&quot;,&quot;custom_content&quot;:&quot;&quot;},&quot;slide_in&quot;:{&quot;display_in&quot;:&quot;bottom_right&quot;,&quot;trigger&quot;:&quot;timer&quot;,&quot;scroll_percentage&quot;:null,&quot;timer&quot;:5,&quot;devices&quot;:&quot;all&quot;,&quot;show_once_every&quot;:15},&quot;sticky_bar&quot;:{&quot;display_in&quot;:&quot;top&quot;,&quot;trigger&quot;:&quot;timer&quot;,&quot;scroll_percentage&quot;:null,&quot;timer&quot;:5,&quot;devices&quot;:&quot;all&quot;,&quot;show_once_every&quot;:15}},&quot;version&quot;:&quot;5&quot;}">
<!--Errors-->
<ul class="text-danger fw-bold" data-element="errors" data-group="alert"></ul>
<!--Fields-->
<div data-element="fields" data-stacked="false"
class="d-flex d-inline-block justify-content-center">
<!--Email address-->
<div class="form-outline form-white w-100">
<input type="text" id="form1" name="email_address" required="" type="email"
class="form-control form-control-lg" />
<label class="form-label" for="form1">Your email address</label>
</div>
<!--Button-->
<button class="btn btn-danger ms-2" data-element="submit">
JOIN
</button>
</div>
</form>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
</div>
<p class="text-muted text-center">
<small>By subscribing you agree to receive Black November notifications from the data
administrator StartupFlow s.c. Kijowska 7, Warsaw.
<a href="https://mdbootstrap.com/general/privacy-policy/" class="text-decoration-underline text-reset">Privacy
Policy</a>.
</small>
</p>
</section>
<!-- Section: Waiting List -->
<!--Products-->
<section class="my-5 pt-5">
<p class="lead text-center">Explore products that will be discounted:</p>
<!--Row-->
<div class="row">
<!--Standard-->
<div class="col-md-3">
<div class="card shadow-2-strong">
<div class="bg-image hover-overlay ripple" data-mdb-ripple-color="light">
<img src="https://v1.mdbootstrap.com/wp-content/uploads/2021/10/bootstrap-standard.webp"
class="img-fluid" />
<a href="https://mdbootstrap.com/docs/standard/pro/" target="_blank">
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15)"></div>
</a>
</div>
<div class="card-body">
<h5 class="card-title">MDB Standard PRO</h5>
<p class="card-text">
Components, templates, plugins, premium support and much more for the <strong>latest Bootstrap v5 as
well as v4</strong>.
</p>
<div class="text-end">
<a href="https://mdbootstrap.com/docs/standard/pro/" type="button"
class="btn btn-sm btn-link text-muted" target="_blank">View product <i
class="fas fa-external-link-alt"></i></a>
</div>
</div>
</div>
</div>
<!--Angular-->
<div class="col-md-3">
<div class="card shadow-2-strong">
<div class="bg-image hover-overlay ripple" data-mdb-ripple-color="light">
<img src="https://v1.mdbootstrap.com/wp-content/uploads/2021/10/angular.webp" class="img-fluid" />
<a href="https://mdbootstrap.com/docs/b5/angular/pro/" target="_blank">
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15)"></div>
</a>
</div>
<div class="card-body">
<h5 class="card-title">MDB Angular PRO</h5>
<p class="card-text">
Components, templates, plugins, premium support and much more for the <strong>latest Bootstrap v5 as
well as v4</strong>.
</p>
<div class="text-end">
<a href="https://mdbootstrap.com/docs/b5/angular/pro/" type="button" class="btn btn-sm btn-link text-muted"
target="_blank">View product <i class="fas fa-external-link-alt"></i></a>
</div>
</div>
</div>
</div>
<!--React-->
<div class="col-md-3">
<div class="card shadow-2-strong">
<div class="bg-image hover-overlay ripple" data-mdb-ripple-color="light">
<img src="https://v1.mdbootstrap.com/wp-content/uploads/2021/10/react.webp" class="img-fluid" />
<a href="https://mdbootstrap.com/docs/b5/react/pro/" target="_blank">
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15)"></div>
</a>
</div>
<div class="card-body">
<h5 class="card-title">MDB React PRO</h5>
<p class="card-text">
Components, templates, plugins, premium support and much more for the <strong>latest Bootstrap v5 as
well as v4</strong>.
</p>
<div class="text-end">
<a href="https://mdbootstrap.com/docs/b5/react/pro/" type="button" class="btn btn-sm btn-link text-muted"
target="_blank">View product <i class="fas fa-external-link-alt"></i></a>
</div>
</div>
</div>
</div>
<!--Vue-->
<div class="col-md-3">
<div class="card shadow-2-strong">
<div class="bg-image hover-overlay ripple" data-mdb-ripple-color="light">
<img src="https://v1.mdbootstrap.com/wp-content/uploads/2021/10/vue.webp" class="img-fluid" />
<a href="https://mdbootstrap.com/docs/b5/vue/pro/" target="_blank">
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15)"></div>
</a>
</div>
<div class="card-body">
<h5 class="card-title">MDB Vue PRO</h5>
<p class="card-text">
Components, templates, plugins, premium support and much more for the <strong>latest Bootstrap v5 as
well as v4</strong>.
</p>
<div class="text-end">
<a href="https://mdbootstrap.com/docs/b5/vue/pro/" type="button" class="btn btn-sm btn-link text-muted"
target="_blank">View product <i class="fas fa-external-link-alt"></i></a>
</div>
</div>
</div>
</div>
</div>
</section>
<!--Products-->
</div>
<!-- Container for demo purpose -->
<!-- End your project here--> <!-- End your project here-->
<!-- MDB --> <!-- MDB -->
<script type="text/javascript" src="js/mdb.min.js"></script> <script type="text/javascript" src="js/mdb.min.js"></script>
<!-- Custom scripts --> <!-- Custom scripts -->

4
js/mdb.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{ {
"name": "mdb-ui-kit", "name": "mdb-ui-kit",
"version": "3.9.0", "version": "3.10.0",
"main": "js/mdb.min.js", "main": "js/mdb.min.js",
"homepage": "https://mdbootstrap.com/docs/standard/", "homepage": "https://mdbootstrap.com/docs/standard/",
"repository": "https://github.com/mdbootstrap/mdb-ui-kit.git", "repository": "https://github.com/mdbootstrap/mdb-ui-kit.git",

View File

@ -1,40 +1,30 @@
/*! /*!
* Bootstrap alert.js v5.0.1 (https://getbootstrap.com/) * Bootstrap alert.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(require('./dom/event-handler.js'), require('./base-component.js')))
require('./dom/selector-engine.js'),
require('./dom/data.js'),
require('./dom/event-handler.js'),
require('./base-component.js')
))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(['./dom/event-handler', './base-component'], factory)
'./dom/selector-engine',
'./dom/data',
'./dom/event-handler',
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Alert = factory( (global.Alert = factory(global.EventHandler, global.Base)));
global.SelectorEngine, })(this, function (EventHandler, BaseComponent) {
global.Data,
global.EventHandler,
global.Base
)));
})(this, function (SelectorEngine, Data, EventHandler, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const getSelector = (element) => { const getSelector = (element) => {
let selector = element.getAttribute('data-bs-target'); let selector = element.getAttribute('data-bs-target');
@ -64,6 +54,22 @@
return selector ? document.querySelector(selector) : null; return selector ? document.querySelector(selector) : null;
}; };
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';
};
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -74,9 +80,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -103,7 +118,38 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): alert.js * Bootstrap (v5.1.3): 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.3): alert.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -116,12 +162,8 @@
const NAME = 'alert'; const NAME = 'alert';
const DATA_KEY = 'bs.alert'; const DATA_KEY = 'bs.alert';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const DATA_API_KEY = '.data-api';
const SELECTOR_DISMISS = '[data-bs-dismiss="alert"]';
const EVENT_CLOSE = `close${EVENT_KEY}`; const EVENT_CLOSE = `close${EVENT_KEY}`;
const EVENT_CLOSED = `closed${EVENT_KEY}`; const EVENT_CLOSED = `closed${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const CLASS_NAME_ALERT = 'alert';
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
/** /**
@ -130,70 +172,48 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Alert extends BaseComponent__default['default'] { class Alert extends BaseComponent__default.default {
// Getters // Getters
static get NAME() { static get NAME() {
return NAME; return NAME;
} // Public } // Public
close(element) { close() {
const rootElement = element ? this._getRootElement(element) : this._element; const closeEvent = EventHandler__default.default.trigger(this._element, EVENT_CLOSE);
const customEvent = this._triggerCloseEvent(rootElement); if (closeEvent.defaultPrevented) {
if (customEvent === null || customEvent.defaultPrevented) {
return; return;
} }
this._removeElement(rootElement); this._element.classList.remove(CLASS_NAME_SHOW);
const isAnimated = this._element.classList.contains(CLASS_NAME_FADE);
this._queueCallback(() => this._destroyElement(), this._element, isAnimated);
} // Private } // Private
_getRootElement(element) { _destroyElement() {
return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`); this._element.remove();
}
_triggerCloseEvent(element) { EventHandler__default.default.trigger(this._element, EVENT_CLOSED);
return EventHandler__default['default'].trigger(element, EVENT_CLOSE); this.dispose();
}
_removeElement(element) {
element.classList.remove(CLASS_NAME_SHOW);
const isAnimated = element.classList.contains(CLASS_NAME_FADE);
this._queueCallback(() => this._destroyElement(element), element, isAnimated);
}
_destroyElement(element) {
if (element.parentNode) {
element.parentNode.removeChild(element);
}
EventHandler__default['default'].trigger(element, EVENT_CLOSED);
} // Static } // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data__default['default'].get(this, DATA_KEY); const data = Alert.getOrCreateInstance(this);
if (!data) { if (typeof config !== 'string') {
data = new Alert(this); return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
} }
if (config === 'close') {
data[config](this); data[config](this);
}
}); });
} }
static handleDismiss(alertInstance) {
return function (event) {
if (event) {
event.preventDefault();
}
alertInstance.close(this);
};
}
} }
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -201,12 +221,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( enableDismissTrigger(Alert, 'close');
document,
EVENT_CLICK_DATA_API,
SELECTOR_DISMISS,
Alert.handleDismiss(new Alert())
);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

File diff suppressed because one or more lines are too long

View File

@ -1,30 +1,30 @@
/*! /*!
* Bootstrap base-component.js v5.0.1 (https://getbootstrap.com/) * Bootstrap base-component.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(require('./dom/data.js'), require('./dom/event-handler.js')))
require('./dom/data.js'),
require('./dom/selector-engine.js'),
require('./dom/event-handler.js')
))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define(['./dom/data', './dom/selector-engine', './dom/event-handler'], factory) ? define(['./dom/data', './dom/event-handler'], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Base = factory(global.Data, global.SelectorEngine, global.EventHandler))); (global.Base = factory(global.Data, global.EventHandler)));
})(this, function (Data, SelectorEngine, EventHandler) { })(this, function (Data, EventHandler) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data);
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MILLISECONDS_MULTIPLIER = 1000; const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
@ -72,39 +72,49 @@
} }
if (typeof obj === 'string' && obj.length > 0) { if (typeof obj === 'string' && obj.length > 0) {
return SelectorEngine__default['default'].findOne(obj); return document.querySelector(obj);
} }
return null; return null;
}; };
const emulateTransitionEnd = (element, duration) => {
let called = false;
const durationPadding = 5;
const emulatedDuration = duration + durationPadding;
function listener() {
called = true;
element.removeEventListener(TRANSITION_END, listener);
}
element.addEventListener(TRANSITION_END, listener);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(element);
}
}, emulatedDuration);
};
const execute = (callback) => { const execute = (callback) => {
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(); 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.0.1): base-component.js * Bootstrap (v5.1.3): base-component.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -114,7 +124,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
const VERSION = '5.0.1'; const VERSION = '5.1.3';
class BaseComponent { class BaseComponent {
constructor(element) { constructor(element) {
@ -125,31 +135,30 @@
} }
this._element = element; this._element = element;
Data__default['default'].set(this._element, this.constructor.DATA_KEY, this); Data__default.default.set(this._element, this.constructor.DATA_KEY, this);
} }
dispose() { dispose() {
Data__default['default'].remove(this._element, this.constructor.DATA_KEY); Data__default.default.remove(this._element, this.constructor.DATA_KEY);
EventHandler__default['default'].off(this._element, this.constructor.EVENT_KEY); EventHandler__default.default.off(this._element, this.constructor.EVENT_KEY);
Object.getOwnPropertyNames(this).forEach((propertyName) => { Object.getOwnPropertyNames(this).forEach((propertyName) => {
this[propertyName] = null; this[propertyName] = null;
}); });
} }
_queueCallback(callback, element, isAnimated = true) { _queueCallback(callback, element, isAnimated = true) {
if (!isAnimated) { executeAfterTransition(callback, element, isAnimated);
execute(callback);
return;
}
const transitionDuration = getTransitionDurationFromElement(element);
EventHandler__default['default'].one(element, 'transitionend', () => execute(callback));
emulateTransitionEnd(element, transitionDuration);
} }
/** Static */ /** Static */
static getInstance(element) { static getInstance(element) {
return Data__default['default'].get(element, this.DATA_KEY); return Data__default.default.get(getElement(element), this.DATA_KEY);
}
static getOrCreateInstance(element, config = {}) {
return (
this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
);
} }
static get VERSION() { static get VERSION() {

File diff suppressed because one or more lines are too long

View File

@ -1,40 +1,30 @@
/*! /*!
* Bootstrap button.js v5.0.1 (https://getbootstrap.com/) * Bootstrap button.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(require('./dom/event-handler.js'), require('./base-component.js')))
require('./dom/selector-engine.js'),
require('./dom/data.js'),
require('./dom/event-handler.js'),
require('./base-component.js')
))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(['./dom/event-handler', './base-component'], factory)
'./dom/selector-engine',
'./dom/data',
'./dom/event-handler',
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Button = factory( (global.Button = factory(global.EventHandler, global.Base)));
global.SelectorEngine, })(this, function (EventHandler, BaseComponent) {
global.Data,
global.EventHandler,
global.Base
)));
})(this, function (SelectorEngine, Data, EventHandler, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -46,9 +36,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -75,7 +74,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): button.js * Bootstrap (v5.1.3): button.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -98,7 +97,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Button extends BaseComponent__default['default'] { class Button extends BaseComponent__default.default {
// Getters // Getters
static get NAME() { static get NAME() {
return NAME; return NAME;
@ -111,11 +110,7 @@
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data__default['default'].get(this, DATA_KEY); const data = Button.getOrCreateInstance(this);
if (!data) {
data = new Button(this);
}
if (config === 'toggle') { if (config === 'toggle') {
data[config](); data[config]();
@ -129,19 +124,14 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_CLICK_DATA_API, EVENT_CLICK_DATA_API,
SELECTOR_DATA_TOGGLE, SELECTOR_DATA_TOGGLE,
(event) => { (event) => {
event.preventDefault(); event.preventDefault();
const button = event.target.closest(SELECTOR_DATA_TOGGLE); const button = event.target.closest(SELECTOR_DATA_TOGGLE);
let data = Data__default['default'].get(button, DATA_KEY); const data = Button.getOrCreateInstance(button);
if (!data) {
data = new Button(button);
}
data.toggle(); data.toggle();
} }
); );

File diff suppressed because one or more lines are too long

View File

@ -1,46 +1,45 @@
/*! /*!
* Bootstrap carousel.js v5.0.1 (https://getbootstrap.com/) * Bootstrap carousel.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('./dom/selector-engine.js'),
require('./dom/data.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./dom/selector-engine.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(
'./dom/selector-engine', ['./dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'],
'./dom/data', factory
'./dom/event-handler', )
'./dom/manipulator',
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Carousel = factory( (global.Carousel = factory(
global.SelectorEngine,
global.Data,
global.EventHandler, global.EventHandler,
global.Manipulator, global.Manipulator,
global.SelectorEngine,
global.Base global.Base
))); )));
})(this, function (SelectorEngine, Data, EventHandler, Manipulator, BaseComponent) { })(this, function (EventHandler, Manipulator, SelectorEngine, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
const toType = (obj) => { const toType = (obj) => {
@ -113,24 +112,25 @@
}; };
const isVisible = (element) => { const isVisible = (element) => {
if (!element) { if (!isElement(element) || element.getClientRects().length === 0) {
return false; return false;
} }
if (element.style && element.parentNode && element.parentNode.style) { return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
const elementStyle = getComputedStyle(element);
const parentNodeStyle = getComputedStyle(element.parentNode);
return (
elementStyle.display !== 'none' &&
parentNodeStyle.display !== 'none' &&
elementStyle.visibility !== 'hidden'
);
}
return 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) => element.offsetHeight; const reflow = (element) => {
// eslint-disable-next-line no-unused-expressions
element.offsetHeight;
};
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -142,9 +142,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -170,10 +179,36 @@
} }
}); });
}; };
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
let index = list.indexOf(activeElement); // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
if (index === -1) {
return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];
}
const listLength = list.length;
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): carousel.js * Bootstrap (v5.1.3): carousel.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -212,6 +247,10 @@
const ORDER_PREV = 'prev'; const ORDER_PREV = 'prev';
const DIRECTION_LEFT = 'left'; const DIRECTION_LEFT = 'left';
const DIRECTION_RIGHT = 'right'; const DIRECTION_RIGHT = 'right';
const KEY_TO_DIRECTION = {
[ARROW_LEFT_KEY]: DIRECTION_RIGHT,
[ARROW_RIGHT_KEY]: DIRECTION_LEFT,
};
const EVENT_SLIDE = `slide${EVENT_KEY}`; const EVENT_SLIDE = `slide${EVENT_KEY}`;
const EVENT_SLID = `slid${EVENT_KEY}`; const EVENT_SLID = `slid${EVENT_KEY}`;
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
@ -250,7 +289,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Carousel extends BaseComponent__default['default'] { class Carousel extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
this._items = null; this._items = null;
@ -262,7 +301,7 @@
this.touchStartX = 0; this.touchStartX = 0;
this.touchDeltaX = 0; this.touchDeltaX = 0;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._indicatorsElement = SelectorEngine__default['default'].findOne( this._indicatorsElement = SelectorEngine__default.default.findOne(
SELECTOR_INDICATORS, SELECTOR_INDICATORS,
this._element this._element
); );
@ -282,10 +321,8 @@
} // Public } // Public
next() { next() {
if (!this._isSliding) {
this._slide(ORDER_NEXT); this._slide(ORDER_NEXT);
} }
}
nextWhenVisible() { nextWhenVisible() {
// Don't call next when the page isn't visible // Don't call next when the page isn't visible
@ -296,17 +333,15 @@
} }
prev() { prev() {
if (!this._isSliding) {
this._slide(ORDER_PREV); this._slide(ORDER_PREV);
} }
}
pause(event) { pause(event) {
if (!event) { if (!event) {
this._isPaused = true; this._isPaused = true;
} }
if (SelectorEngine__default['default'].findOne(SELECTOR_NEXT_PREV, this._element)) { if (SelectorEngine__default.default.findOne(SELECTOR_NEXT_PREV, this._element)) {
triggerTransitionEnd(this._element); triggerTransitionEnd(this._element);
this.cycle(true); this.cycle(true);
} }
@ -336,7 +371,7 @@
} }
to(index) { to(index) {
this._activeElement = SelectorEngine__default['default'].findOne( this._activeElement = SelectorEngine__default.default.findOne(
SELECTOR_ACTIVE_ITEM, SELECTOR_ACTIVE_ITEM,
this._element this._element
); );
@ -348,7 +383,7 @@
} }
if (this._isSliding) { if (this._isSliding) {
EventHandler__default['default'].one(this._element, EVENT_SLID, () => this.to(index)); EventHandler__default.default.one(this._element, EVENT_SLID, () => this.to(index));
return; return;
} }
@ -364,7 +399,11 @@
} // Private } // Private
_getConfig(config) { _getConfig(config) {
config = { ...Default, ...config }; config = {
...Default,
...Manipulator__default.default.getDataAttributes(this._element),
...(typeof config === 'object' ? config : {}),
};
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
} }
@ -388,16 +427,16 @@
_addEventListeners() { _addEventListeners() {
if (this._config.keyboard) { if (this._config.keyboard) {
EventHandler__default['default'].on(this._element, EVENT_KEYDOWN, (event) => EventHandler__default.default.on(this._element, EVENT_KEYDOWN, (event) =>
this._keydown(event) this._keydown(event)
); );
} }
if (this._config.pause === 'hover') { if (this._config.pause === 'hover') {
EventHandler__default['default'].on(this._element, EVENT_MOUSEENTER, (event) => EventHandler__default.default.on(this._element, EVENT_MOUSEENTER, (event) =>
this.pause(event) this.pause(event)
); );
EventHandler__default['default'].on(this._element, EVENT_MOUSELEAVE, (event) => EventHandler__default.default.on(this._element, EVENT_MOUSELEAVE, (event) =>
this.cycle(event) this.cycle(event)
); );
} }
@ -408,11 +447,15 @@
} }
_addTouchEventListeners() { _addTouchEventListeners() {
const start = (event) => { const hasPointerPenTouch = (event) => {
if ( return (
this._pointerEvent && this._pointerEvent &&
(event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH) (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
) { );
};
const start = (event) => {
if (hasPointerPenTouch(event)) {
this.touchStartX = event.clientX; this.touchStartX = event.clientX;
} else if (!this._pointerEvent) { } else if (!this._pointerEvent) {
this.touchStartX = event.touches[0].clientX; this.touchStartX = event.touches[0].clientX;
@ -428,10 +471,7 @@
}; };
const end = (event) => { const end = (event) => {
if ( if (hasPointerPenTouch(event)) {
this._pointerEvent &&
(event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
) {
this.touchDeltaX = event.clientX - this.touchStartX; this.touchDeltaX = event.clientX - this.touchStartX;
} }
@ -458,25 +498,21 @@
} }
}; };
SelectorEngine__default['default'] SelectorEngine__default.default.find(SELECTOR_ITEM_IMG, this._element).forEach((itemImg) => {
.find(SELECTOR_ITEM_IMG, this._element) EventHandler__default.default.on(itemImg, EVENT_DRAG_START, (event) =>
.forEach((itemImg) => { event.preventDefault()
EventHandler__default['default'].on(itemImg, EVENT_DRAG_START, (e) => e.preventDefault()); );
}); });
if (this._pointerEvent) { if (this._pointerEvent) {
EventHandler__default['default'].on(this._element, EVENT_POINTERDOWN, (event) => EventHandler__default.default.on(this._element, EVENT_POINTERDOWN, (event) => start(event));
start(event) EventHandler__default.default.on(this._element, EVENT_POINTERUP, (event) => end(event));
);
EventHandler__default['default'].on(this._element, EVENT_POINTERUP, (event) => end(event));
this._element.classList.add(CLASS_NAME_POINTER_EVENT); this._element.classList.add(CLASS_NAME_POINTER_EVENT);
} else { } else {
EventHandler__default['default'].on(this._element, EVENT_TOUCHSTART, (event) => EventHandler__default.default.on(this._element, EVENT_TOUCHSTART, (event) => start(event));
start(event) EventHandler__default.default.on(this._element, EVENT_TOUCHMOVE, (event) => move(event));
); EventHandler__default.default.on(this._element, EVENT_TOUCHEND, (event) => end(event));
EventHandler__default['default'].on(this._element, EVENT_TOUCHMOVE, (event) => move(event));
EventHandler__default['default'].on(this._element, EVENT_TOUCHEND, (event) => end(event));
} }
} }
@ -485,52 +521,36 @@
return; return;
} }
if (event.key === ARROW_LEFT_KEY) { const direction = KEY_TO_DIRECTION[event.key];
if (direction) {
event.preventDefault(); event.preventDefault();
this._slide(DIRECTION_RIGHT); this._slide(direction);
} else if (event.key === ARROW_RIGHT_KEY) {
event.preventDefault();
this._slide(DIRECTION_LEFT);
} }
} }
_getItemIndex(element) { _getItemIndex(element) {
this._items = this._items =
element && element.parentNode element && element.parentNode
? SelectorEngine__default['default'].find(SELECTOR_ITEM, element.parentNode) ? SelectorEngine__default.default.find(SELECTOR_ITEM, element.parentNode)
: []; : [];
return this._items.indexOf(element); return this._items.indexOf(element);
} }
_getItemByOrder(order, activeElement) { _getItemByOrder(order, activeElement) {
const isNext = order === ORDER_NEXT; const isNext = order === ORDER_NEXT;
const isPrev = order === ORDER_PREV; return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);
const activeIndex = this._getItemIndex(activeElement);
const lastItemIndex = this._items.length - 1;
const isGoingToWrap =
(isPrev && activeIndex === 0) || (isNext && activeIndex === lastItemIndex);
if (isGoingToWrap && !this._config.wrap) {
return activeElement;
}
const delta = isPrev ? -1 : 1;
const itemIndex = (activeIndex + delta) % this._items.length;
return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
} }
_triggerSlideEvent(relatedTarget, eventDirectionName) { _triggerSlideEvent(relatedTarget, eventDirectionName) {
const targetIndex = this._getItemIndex(relatedTarget); const targetIndex = this._getItemIndex(relatedTarget);
const fromIndex = this._getItemIndex( const fromIndex = this._getItemIndex(
SelectorEngine__default['default'].findOne(SELECTOR_ACTIVE_ITEM, this._element) SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element)
); );
return EventHandler__default['default'].trigger(this._element, EVENT_SLIDE, { return EventHandler__default.default.trigger(this._element, EVENT_SLIDE, {
relatedTarget, relatedTarget,
direction: eventDirectionName, direction: eventDirectionName,
from: fromIndex, from: fromIndex,
@ -540,13 +560,13 @@
_setActiveIndicatorElement(element) { _setActiveIndicatorElement(element) {
if (this._indicatorsElement) { if (this._indicatorsElement) {
const activeIndicator = SelectorEngine__default['default'].findOne( const activeIndicator = SelectorEngine__default.default.findOne(
SELECTOR_ACTIVE, SELECTOR_ACTIVE,
this._indicatorsElement this._indicatorsElement
); );
activeIndicator.classList.remove(CLASS_NAME_ACTIVE); activeIndicator.classList.remove(CLASS_NAME_ACTIVE);
activeIndicator.removeAttribute('aria-current'); activeIndicator.removeAttribute('aria-current');
const indicators = SelectorEngine__default['default'].find( const indicators = SelectorEngine__default.default.find(
SELECTOR_INDICATOR, SELECTOR_INDICATOR,
this._indicatorsElement this._indicatorsElement
); );
@ -567,7 +587,7 @@
_updateInterval() { _updateInterval() {
const element = const element =
this._activeElement || this._activeElement ||
SelectorEngine__default['default'].findOne(SELECTOR_ACTIVE_ITEM, this._element); SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
if (!element) { if (!element) {
return; return;
@ -586,7 +606,7 @@
_slide(directionOrOrder, element) { _slide(directionOrOrder, element) {
const order = this._directionToOrder(directionOrOrder); const order = this._directionToOrder(directionOrOrder);
const activeElement = SelectorEngine__default['default'].findOne( const activeElement = SelectorEngine__default.default.findOne(
SELECTOR_ACTIVE_ITEM, SELECTOR_ACTIVE_ITEM,
this._element this._element
); );
@ -609,6 +629,10 @@
return; return;
} }
if (this._isSliding) {
return;
}
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
if (slideEvent.defaultPrevented) { if (slideEvent.defaultPrevented) {
@ -631,7 +655,7 @@
this._activeElement = nextElement; this._activeElement = nextElement;
const triggerSlidEvent = () => { const triggerSlidEvent = () => {
EventHandler__default['default'].trigger(this._element, EVENT_SLID, { EventHandler__default.default.trigger(this._element, EVENT_SLID, {
relatedTarget: nextElement, relatedTarget: nextElement,
direction: eventDirectionName, direction: eventDirectionName,
from: activeElementIndex, from: activeElementIndex,
@ -691,8 +715,8 @@
} // Static } // Static
static carouselInterface(element, config) { static carouselInterface(element, config) {
let data = Data__default['default'].get(element, DATA_KEY); const data = Carousel.getOrCreateInstance(element, config);
let _config = { ...Default, ...Manipulator__default['default'].getDataAttributes(element) }; let { _config } = data;
if (typeof config === 'object') { if (typeof config === 'object') {
_config = { ..._config, ...config }; _config = { ..._config, ...config };
@ -700,10 +724,6 @@
const action = typeof config === 'string' ? config : _config.slide; const action = typeof config === 'string' ? config : _config.slide;
if (!data) {
data = new Carousel(element, _config);
}
if (typeof config === 'number') { if (typeof config === 'number') {
data.to(config); data.to(config);
} else if (typeof action === 'string') { } else if (typeof action === 'string') {
@ -732,8 +752,8 @@
} }
const config = { const config = {
...Manipulator__default['default'].getDataAttributes(target), ...Manipulator__default.default.getDataAttributes(target),
...Manipulator__default['default'].getDataAttributes(this), ...Manipulator__default.default.getDataAttributes(this),
}; };
const slideIndex = this.getAttribute('data-bs-slide-to'); const slideIndex = this.getAttribute('data-bs-slide-to');
@ -744,7 +764,7 @@
Carousel.carouselInterface(target, config); Carousel.carouselInterface(target, config);
if (slideIndex) { if (slideIndex) {
Data__default['default'].get(target, DATA_KEY).to(slideIndex); Carousel.getInstance(target).to(slideIndex);
} }
event.preventDefault(); event.preventDefault();
@ -756,20 +776,17 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_CLICK_DATA_API, EVENT_CLICK_DATA_API,
SELECTOR_DATA_SLIDE, SELECTOR_DATA_SLIDE,
Carousel.dataApiClickHandler Carousel.dataApiClickHandler
); );
EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, () => { EventHandler__default.default.on(window, EVENT_LOAD_DATA_API, () => {
const carousels = SelectorEngine__default['default'].find(SELECTOR_DATA_RIDE); const carousels = SelectorEngine__default.default.find(SELECTOR_DATA_RIDE);
for (let i = 0, len = carousels.length; i < len; i++) { for (let i = 0, len = carousels.length; i < len; i++) {
Carousel.carouselInterface( Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));
carousels[i],
Data__default['default'].get(carousels[i], DATA_KEY)
);
} }
}); });
/** /**

File diff suppressed because one or more lines are too long

View File

@ -1,45 +1,54 @@
/*! /*!
* Bootstrap collapse.js v5.0.1 (https://getbootstrap.com/) * Bootstrap collapse.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('./dom/selector-engine.js'),
require('./dom/data.js'), require('./dom/data.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./dom/selector-engine.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(
'./dom/selector-engine', [
'./dom/data', './dom/data',
'./dom/event-handler', './dom/event-handler',
'./dom/manipulator', './dom/manipulator',
'./dom/selector-engine',
'./base-component', './base-component',
], factory) ],
factory
)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Collapse = factory( (global.Collapse = factory(
global.SelectorEngine,
global.Data, global.Data,
global.EventHandler, global.EventHandler,
global.Manipulator, global.Manipulator,
global.SelectorEngine,
global.Base global.Base
))); )));
})(this, function (SelectorEngine, Data, EventHandler, Manipulator, BaseComponent) { })(this, function (Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data);
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const toType = (obj) => { const toType = (obj) => {
if (obj === null || obj === undefined) { if (obj === null || obj === undefined) {
@ -109,7 +118,7 @@
} }
if (typeof obj === 'string' && obj.length > 0) { if (typeof obj === 'string' && obj.length > 0) {
return SelectorEngine__default['default'].findOne(obj); return document.querySelector(obj);
} }
return null; return null;
@ -128,8 +137,19 @@
} }
}); });
}; };
/**
* 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) => element.offsetHeight; const reflow = (element) => {
// eslint-disable-next-line no-unused-expressions
element.offsetHeight;
};
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -141,9 +161,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -170,7 +199,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): collapse.js * Bootstrap (v5.1.3): collapse.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -186,11 +215,11 @@
const DATA_API_KEY = '.data-api'; const DATA_API_KEY = '.data-api';
const Default = { const Default = {
toggle: true, toggle: true,
parent: '', parent: null,
}; };
const DefaultType = { const DefaultType = {
toggle: 'boolean', toggle: 'boolean',
parent: '(string|element)', parent: '(null|element)',
}; };
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
@ -201,9 +230,11 @@
const CLASS_NAME_COLLAPSE = 'collapse'; const CLASS_NAME_COLLAPSE = 'collapse';
const CLASS_NAME_COLLAPSING = 'collapsing'; const CLASS_NAME_COLLAPSING = 'collapsing';
const CLASS_NAME_COLLAPSED = 'collapsed'; const CLASS_NAME_COLLAPSED = 'collapsed';
const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;
const CLASS_NAME_HORIZONTAL = 'collapse-horizontal';
const WIDTH = 'width'; const WIDTH = 'width';
const HEIGHT = 'height'; const HEIGHT = 'height';
const SELECTOR_ACTIVES = '.show, .collapsing'; const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]'; const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -211,21 +242,18 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Collapse extends BaseComponent__default['default'] { class Collapse extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
this._isTransitioning = false; this._isTransitioning = false;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._triggerArray = SelectorEngine__default['default'].find( this._triggerArray = [];
`${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` + const toggleList = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE);
`${SELECTOR_DATA_TOGGLE}[data-bs-target="#${this._element.id}"]`
);
const toggleList = SelectorEngine__default['default'].find(SELECTOR_DATA_TOGGLE);
for (let i = 0, len = toggleList.length; i < len; i++) { for (let i = 0, len = toggleList.length; i < len; i++) {
const elem = toggleList[i]; const elem = toggleList[i];
const selector = getSelectorFromElement(elem); const selector = getSelectorFromElement(elem);
const filterElement = SelectorEngine__default['default'] const filterElement = SelectorEngine__default.default
.find(selector) .find(selector)
.filter((foundElem) => foundElem === this._element); .filter((foundElem) => foundElem === this._element);
@ -236,10 +264,10 @@
} }
} }
this._parent = this._config.parent ? this._getParent() : null; this._initializeChildren();
if (!this._config.parent) { if (!this._config.parent) {
this._addAriaAndCollapsedClass(this._element, this._triggerArray); this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());
} }
if (this._config.toggle) { if (this._config.toggle) {
@ -256,7 +284,7 @@
} // Public } // Public
toggle() { toggle() {
if (this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isShown()) {
this.hide(); this.hide();
} else { } else {
this.show(); this.show();
@ -264,59 +292,51 @@
} }
show() { show() {
if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isTransitioning || this._isShown()) {
return; return;
} }
let actives; let actives = [];
let activesData; let activesData;
if (this._parent) { if (this._config.parent) {
actives = SelectorEngine__default['default'] const children = SelectorEngine__default.default.find(
.find(SELECTOR_ACTIVES, this._parent) CLASS_NAME_DEEPER_CHILDREN,
.filter((elem) => { this._config.parent
if (typeof this._config.parent === 'string') { );
return elem.getAttribute('data-bs-parent') === this._config.parent; actives = SelectorEngine__default.default
.find(SELECTOR_ACTIVES, this._config.parent)
.filter((elem) => !children.includes(elem)); // remove children if greater depth
} }
return elem.classList.contains(CLASS_NAME_COLLAPSE); const container = SelectorEngine__default.default.findOne(this._selector);
});
if (actives.length === 0) { if (actives.length) {
actives = null;
}
}
const container = SelectorEngine__default['default'].findOne(this._selector);
if (actives) {
const tempActiveData = actives.find((elem) => container !== elem); const tempActiveData = actives.find((elem) => container !== elem);
activesData = tempActiveData activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null;
? Data__default['default'].get(tempActiveData, DATA_KEY)
: null;
if (activesData && activesData._isTransitioning) { if (activesData && activesData._isTransitioning) {
return; return;
} }
} }
const startEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW); const startEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW);
if (startEvent.defaultPrevented) { if (startEvent.defaultPrevented) {
return; return;
} }
if (actives) {
actives.forEach((elemActive) => { actives.forEach((elemActive) => {
if (container !== elemActive) { if (container !== elemActive) {
Collapse.collapseInterface(elemActive, 'hide'); Collapse.getOrCreateInstance(elemActive, {
toggle: false,
}).hide();
} }
if (!activesData) { if (!activesData) {
Data__default['default'].set(elemActive, DATA_KEY, null); Data__default.default.set(elemActive, DATA_KEY, null);
} }
}); });
}
const dimension = this._getDimension(); const dimension = this._getDimension();
@ -326,23 +346,19 @@
this._element.style[dimension] = 0; this._element.style[dimension] = 0;
if (this._triggerArray.length) { this._addAriaAndCollapsedClass(this._triggerArray, true);
this._triggerArray.forEach((element) => {
element.classList.remove(CLASS_NAME_COLLAPSED);
element.setAttribute('aria-expanded', true);
});
}
this.setTransitioning(true); this._isTransitioning = true;
const complete = () => { const complete = () => {
this._isTransitioning = false;
this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSING);
this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);
this._element.style[dimension] = ''; this._element.style[dimension] = '';
this.setTransitioning(false); EventHandler__default.default.trigger(this._element, EVENT_SHOWN);
EventHandler__default['default'].trigger(this._element, EVENT_SHOWN);
}; };
const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
@ -354,11 +370,11 @@
} }
hide() { hide() {
if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isTransitioning || !this._isShown()) {
return; return;
} }
const startEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); const startEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE);
if (startEvent.defaultPrevented) { if (startEvent.defaultPrevented) {
return; return;
@ -375,28 +391,25 @@
const triggerArrayLength = this._triggerArray.length; const triggerArrayLength = this._triggerArray.length;
if (triggerArrayLength > 0) {
for (let i = 0; i < triggerArrayLength; i++) { for (let i = 0; i < triggerArrayLength; i++) {
const trigger = this._triggerArray[i]; const trigger = this._triggerArray[i];
const elem = getElementFromSelector(trigger); const elem = getElementFromSelector(trigger);
if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { if (elem && !this._isShown(elem)) {
trigger.classList.add(CLASS_NAME_COLLAPSED); this._addAriaAndCollapsedClass([trigger], false);
trigger.setAttribute('aria-expanded', false);
}
} }
} }
this.setTransitioning(true); this._isTransitioning = true;
const complete = () => { const complete = () => {
this.setTransitioning(false); this._isTransitioning = false;
this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSING);
this._element.classList.add(CLASS_NAME_COLLAPSE); this._element.classList.add(CLASS_NAME_COLLAPSE);
EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN); EventHandler__default.default.trigger(this._element, EVENT_HIDDEN);
}; };
this._element.style[dimension] = ''; this._element.style[dimension] = '';
@ -404,40 +417,53 @@
this._queueCallback(complete, this._element, true); this._queueCallback(complete, this._element, true);
} }
setTransitioning(isTransitioning) { _isShown(element = this._element) {
this._isTransitioning = isTransitioning; return element.classList.contains(CLASS_NAME_SHOW);
} // Private } // Private
_getConfig(config) { _getConfig(config) {
config = { ...Default, ...config }; config = {
...Default,
...Manipulator__default.default.getDataAttributes(this._element),
...config,
};
config.toggle = Boolean(config.toggle); // Coerce string values config.toggle = Boolean(config.toggle); // Coerce string values
config.parent = getElement(config.parent);
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
} }
_getDimension() { _getDimension() {
return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT; return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;
} }
_getParent() { _initializeChildren() {
let { parent } = this._config; if (!this._config.parent) {
parent = getElement(parent); return;
const selector = `${SELECTOR_DATA_TOGGLE}[data-bs-parent="${parent}"]`; }
SelectorEngine__default['default'].find(selector, parent).forEach((element) => {
const selected = getElementFromSelector(element); const children = SelectorEngine__default.default.find(
CLASS_NAME_DEEPER_CHILDREN,
this._addAriaAndCollapsedClass(selected, [element]); this._config.parent
}); );
return parent; SelectorEngine__default.default
} .find(SELECTOR_DATA_TOGGLE, this._config.parent)
.filter((elem) => !children.includes(elem))
_addAriaAndCollapsedClass(element, triggerArray) { .forEach((element) => {
if (!element || !triggerArray.length) { const selected = getElementFromSelector(element);
if (selected) {
this._addAriaAndCollapsedClass([element], this._isShown(selected));
}
});
}
_addAriaAndCollapsedClass(triggerArray, isOpen) {
if (!triggerArray.length) {
return; return;
} }
const isOpen = element.classList.contains(CLASS_NAME_SHOW);
triggerArray.forEach((elem) => { triggerArray.forEach((elem) => {
if (isOpen) { if (isOpen) {
elem.classList.remove(CLASS_NAME_COLLAPSED); elem.classList.remove(CLASS_NAME_COLLAPSED);
@ -449,21 +475,15 @@
}); });
} // Static } // Static
static collapseInterface(element, config) { static jQueryInterface(config) {
let data = Data__default['default'].get(element, DATA_KEY); return this.each(function () {
const _config = { const _config = {};
...Default,
...Manipulator__default['default'].getDataAttributes(element),
...(typeof config === 'object' && config ? config : {}),
};
if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) { if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false; _config.toggle = false;
} }
if (!data) { const data = Collapse.getOrCreateInstance(this, _config);
data = new Collapse(element, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -472,11 +492,6 @@
data[config](); data[config]();
} }
}
static jQueryInterface(config) {
return this.each(function () {
Collapse.collapseInterface(this, config);
}); });
} }
} }
@ -486,7 +501,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_CLICK_DATA_API, EVENT_CLICK_DATA_API,
SELECTOR_DATA_TOGGLE, SELECTOR_DATA_TOGGLE,
@ -499,26 +514,12 @@
event.preventDefault(); event.preventDefault();
} }
const triggerData = Manipulator__default['default'].getDataAttributes(this);
const selector = getSelectorFromElement(this); const selector = getSelectorFromElement(this);
const selectorElements = SelectorEngine__default['default'].find(selector); const selectorElements = SelectorEngine__default.default.find(selector);
selectorElements.forEach((element) => { selectorElements.forEach((element) => {
const data = Data__default['default'].get(element, DATA_KEY); Collapse.getOrCreateInstance(element, {
let config; toggle: false,
}).toggle();
if (data) {
// update parent attribute
if (data._parent === null && typeof triggerData.parent === 'string') {
data._config.parent = triggerData.parent;
data._parent = data._getParent();
}
config = 'toggle';
} else {
config = triggerData;
}
Collapse.collapseInterface(element, config);
}); });
} }
); );

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/*! /*!
* Bootstrap data.js v5.0.1 (https://getbootstrap.com/) * Bootstrap data.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
@ -15,7 +15,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/data.js * Bootstrap (v5.1.3): dom/data.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -26,7 +26,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
const elementMap = new Map(); const elementMap = new Map();
var data = { const data = {
set(element, key, instance) { set(element, key, instance) {
if (!elementMap.has(element)) { if (!elementMap.has(element)) {
elementMap.set(element, new Map()); elementMap.set(element, new Map());

View File

@ -1 +1 @@
{"version":3,"file":"data.js","sources":["../../src/dom/data.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.0.1): dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst elementMap = new Map()\n\nexport default {\n set(element, key, instance) {\n if (!elementMap.has(element)) {\n elementMap.set(element, new Map())\n }\n\n const instanceMap = elementMap.get(element)\n\n // make it clear we only want one instance per element\n // can be removed later when multiple key/instances are fine to be used\n if (!instanceMap.has(key) && instanceMap.size !== 0) {\n // eslint-disable-next-line no-console\n console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)\n return\n }\n\n instanceMap.set(key, instance)\n },\n\n get(element, key) {\n if (elementMap.has(element)) {\n return elementMap.get(element).get(key) || null\n }\n\n return null\n },\n\n remove(element, key) {\n if (!elementMap.has(element)) {\n return\n }\n\n const instanceMap = elementMap.get(element)\n\n instanceMap.delete(key)\n\n // free up element references if there are no instances left for an element\n if (instanceMap.size === 0) {\n elementMap.delete(element)\n }\n }\n}\n"],"names":["elementMap","Map","set","element","key","instance","has","instanceMap","get","size","console","error","Array","from","keys","remove","delete"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;EAEA,MAAMA,UAAU,GAAG,IAAIC,GAAJ,EAAnB;AAEA,aAAe;EACbC,EAAAA,GAAG,CAACC,OAAD,EAAUC,GAAV,EAAeC,QAAf,EAAyB;EAC1B,QAAI,CAACL,UAAU,CAACM,GAAX,CAAeH,OAAf,CAAL,EAA8B;EAC5BH,MAAAA,UAAU,CAACE,GAAX,CAAeC,OAAf,EAAwB,IAAIF,GAAJ,EAAxB;EACD;;EAED,UAAMM,WAAW,GAAGP,UAAU,CAACQ,GAAX,CAAeL,OAAf,CAApB,CAL0B;EAQ1B;;EACA,QAAI,CAACI,WAAW,CAACD,GAAZ,CAAgBF,GAAhB,CAAD,IAAyBG,WAAW,CAACE,IAAZ,KAAqB,CAAlD,EAAqD;EACnD;EACAC,MAAAA,OAAO,CAACC,KAAR,CAAe,+EAA8EC,KAAK,CAACC,IAAN,CAAWN,WAAW,CAACO,IAAZ,EAAX,EAA+B,CAA/B,CAAkC,GAA/H;EACA;EACD;;EAEDP,IAAAA,WAAW,CAACL,GAAZ,CAAgBE,GAAhB,EAAqBC,QAArB;EACD,GAjBY;;EAmBbG,EAAAA,GAAG,CAACL,OAAD,EAAUC,GAAV,EAAe;EAChB,QAAIJ,UAAU,CAACM,GAAX,CAAeH,OAAf,CAAJ,EAA6B;EAC3B,aAAOH,UAAU,CAACQ,GAAX,CAAeL,OAAf,EAAwBK,GAAxB,CAA4BJ,GAA5B,KAAoC,IAA3C;EACD;;EAED,WAAO,IAAP;EACD,GAzBY;;EA2BbW,EAAAA,MAAM,CAACZ,OAAD,EAAUC,GAAV,EAAe;EACnB,QAAI,CAACJ,UAAU,CAACM,GAAX,CAAeH,OAAf,CAAL,EAA8B;EAC5B;EACD;;EAED,UAAMI,WAAW,GAAGP,UAAU,CAACQ,GAAX,CAAeL,OAAf,CAApB;EAEAI,IAAAA,WAAW,CAACS,MAAZ,CAAmBZ,GAAnB,EAPmB;;EAUnB,QAAIG,WAAW,CAACE,IAAZ,KAAqB,CAAzB,EAA4B;EAC1BT,MAAAA,UAAU,CAACgB,MAAX,CAAkBb,OAAlB;EACD;EACF;;EAxCY,CAAf;;;;;;;;"} {"version":3,"file":"data.js","sources":["../../src/dom/data.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst elementMap = new Map()\n\nexport default {\n set(element, key, instance) {\n if (!elementMap.has(element)) {\n elementMap.set(element, new Map())\n }\n\n const instanceMap = elementMap.get(element)\n\n // make it clear we only want one instance per element\n // can be removed later when multiple key/instances are fine to be used\n if (!instanceMap.has(key) && instanceMap.size !== 0) {\n // eslint-disable-next-line no-console\n console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)\n return\n }\n\n instanceMap.set(key, instance)\n },\n\n get(element, key) {\n if (elementMap.has(element)) {\n return elementMap.get(element).get(key) || null\n }\n\n return null\n },\n\n remove(element, key) {\n if (!elementMap.has(element)) {\n return\n }\n\n const instanceMap = elementMap.get(element)\n\n instanceMap.delete(key)\n\n // free up element references if there are no instances left for an element\n if (instanceMap.size === 0) {\n elementMap.delete(element)\n }\n }\n}\n"],"names":["elementMap","Map","set","element","key","instance","has","instanceMap","get","size","console","error","Array","from","keys","remove","delete"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;EAEA,MAAMA,UAAU,GAAG,IAAIC,GAAJ,EAAnB;AAEA,eAAe;EACbC,EAAAA,GAAG,CAACC,OAAD,EAAUC,GAAV,EAAeC,QAAf,EAAyB;EAC1B,QAAI,CAACL,UAAU,CAACM,GAAX,CAAeH,OAAf,CAAL,EAA8B;EAC5BH,MAAAA,UAAU,CAACE,GAAX,CAAeC,OAAf,EAAwB,IAAIF,GAAJ,EAAxB;EACD;;EAED,UAAMM,WAAW,GAAGP,UAAU,CAACQ,GAAX,CAAeL,OAAf,CAApB,CAL0B;EAQ1B;;EACA,QAAI,CAACI,WAAW,CAACD,GAAZ,CAAgBF,GAAhB,CAAD,IAAyBG,WAAW,CAACE,IAAZ,KAAqB,CAAlD,EAAqD;EACnD;EACAC,MAAAA,OAAO,CAACC,KAAR,CAAe,+EAA8EC,KAAK,CAACC,IAAN,CAAWN,WAAW,CAACO,IAAZ,EAAX,EAA+B,CAA/B,CAAkC,GAA/H;EACA;EACD;;EAEDP,IAAAA,WAAW,CAACL,GAAZ,CAAgBE,GAAhB,EAAqBC,QAArB;EACD,GAjBY;;EAmBbG,EAAAA,GAAG,CAACL,OAAD,EAAUC,GAAV,EAAe;EAChB,QAAIJ,UAAU,CAACM,GAAX,CAAeH,OAAf,CAAJ,EAA6B;EAC3B,aAAOH,UAAU,CAACQ,GAAX,CAAeL,OAAf,EAAwBK,GAAxB,CAA4BJ,GAA5B,KAAoC,IAA3C;EACD;;EAED,WAAO,IAAP;EACD,GAzBY;;EA2BbW,EAAAA,MAAM,CAACZ,OAAD,EAAUC,GAAV,EAAe;EACnB,QAAI,CAACJ,UAAU,CAACM,GAAX,CAAeH,OAAf,CAAL,EAA8B;EAC5B;EACD;;EAED,UAAMI,WAAW,GAAGP,UAAU,CAACQ,GAAX,CAAeL,OAAf,CAApB;EAEAI,IAAAA,WAAW,CAACS,MAAZ,CAAmBZ,GAAnB,EAPmB;;EAUnB,QAAIG,WAAW,CAACE,IAAZ,KAAqB,CAAzB,EAA4B;EAC1BT,MAAAA,UAAU,CAACgB,MAAX,CAAkBb,OAAlB;EACD;EACF;;EAxCY,CAAf;;;;;;;;"}

View File

@ -1,5 +1,5 @@
/*! /*!
* Bootstrap event-handler.js v5.0.1 (https://getbootstrap.com/) * Bootstrap event-handler.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
@ -13,6 +13,13 @@
})(this, function () { })(this, function () {
'use strict'; 'use strict';
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -25,7 +32,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/event-handler.js * Bootstrap (v5.1.3): dom/event-handler.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -133,7 +140,6 @@
event.delegateTarget = target; event.delegateTarget = target;
if (handler.oneOff) { if (handler.oneOff) {
// eslint-disable-next-line unicorn/consistent-destructuring
EventHandler.off(element, event.type, selector, fn); EventHandler.off(element, event.type, selector, fn);
} }

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/*! /*!
* Bootstrap manipulator.js v5.0.1 (https://getbootstrap.com/) * Bootstrap manipulator.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
@ -15,7 +15,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/manipulator.js * Bootstrap (v5.1.3): dom/manipulator.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -75,8 +75,8 @@
offset(element) { offset(element) {
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
return { return {
top: rect.top + document.body.scrollTop, top: rect.top + window.pageYOffset,
left: rect.left + document.body.scrollLeft, left: rect.left + window.pageXOffset,
}; };
}, },

View File

@ -1 +1 @@
{"version":3,"file":"manipulator.js","sources":["../../src/dom/manipulator.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.0.1): dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nfunction normalizeData(val) {\n if (val === 'true') {\n return true\n }\n\n if (val === 'false') {\n return false\n }\n\n if (val === Number(val).toString()) {\n return Number(val)\n }\n\n if (val === '' || val === 'null') {\n return null\n }\n\n return val\n}\n\nfunction normalizeDataKey(key) {\n return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)\n}\n\nconst Manipulator = {\n setDataAttribute(element, key, value) {\n element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value)\n },\n\n removeDataAttribute(element, key) {\n element.removeAttribute(`data-bs-${normalizeDataKey(key)}`)\n },\n\n getDataAttributes(element) {\n if (!element) {\n return {}\n }\n\n const attributes = {}\n\n Object.keys(element.dataset)\n .filter(key => key.startsWith('bs'))\n .forEach(key => {\n let pureKey = key.replace(/^bs/, '')\n pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length)\n attributes[pureKey] = normalizeData(element.dataset[key])\n })\n\n return attributes\n },\n\n getDataAttribute(element, key) {\n return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`))\n },\n\n offset(element) {\n const rect = element.getBoundingClientRect()\n\n return {\n top: rect.top + document.body.scrollTop,\n left: rect.left + document.body.scrollLeft\n }\n },\n\n position(element) {\n return {\n top: element.offsetTop,\n left: element.offsetLeft\n }\n }\n}\n\nexport default Manipulator\n"],"names":["normalizeData","val","Number","toString","normalizeDataKey","key","replace","chr","toLowerCase","Manipulator","setDataAttribute","element","value","setAttribute","removeDataAttribute","removeAttribute","getDataAttributes","attributes","Object","keys","dataset","filter","startsWith","forEach","pureKey","charAt","slice","length","getDataAttribute","getAttribute","offset","rect","getBoundingClientRect","top","document","body","scrollTop","left","scrollLeft","position","offsetTop","offsetLeft"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;EAEA,SAASA,aAAT,CAAuBC,GAAvB,EAA4B;EAC1B,MAAIA,GAAG,KAAK,MAAZ,EAAoB;EAClB,WAAO,IAAP;EACD;;EAED,MAAIA,GAAG,KAAK,OAAZ,EAAqB;EACnB,WAAO,KAAP;EACD;;EAED,MAAIA,GAAG,KAAKC,MAAM,CAACD,GAAD,CAAN,CAAYE,QAAZ,EAAZ,EAAoC;EAClC,WAAOD,MAAM,CAACD,GAAD,CAAb;EACD;;EAED,MAAIA,GAAG,KAAK,EAAR,IAAcA,GAAG,KAAK,MAA1B,EAAkC;EAChC,WAAO,IAAP;EACD;;EAED,SAAOA,GAAP;EACD;;EAED,SAASG,gBAAT,CAA0BC,GAA1B,EAA+B;EAC7B,SAAOA,GAAG,CAACC,OAAJ,CAAY,QAAZ,EAAsBC,GAAG,IAAK,IAAGA,GAAG,CAACC,WAAJ,EAAkB,EAAnD,CAAP;EACD;;QAEKC,WAAW,GAAG;EAClBC,EAAAA,gBAAgB,CAACC,OAAD,EAAUN,GAAV,EAAeO,KAAf,EAAsB;EACpCD,IAAAA,OAAO,CAACE,YAAR,CAAsB,WAAUT,gBAAgB,CAACC,GAAD,CAAM,EAAtD,EAAyDO,KAAzD;EACD,GAHiB;;EAKlBE,EAAAA,mBAAmB,CAACH,OAAD,EAAUN,GAAV,EAAe;EAChCM,IAAAA,OAAO,CAACI,eAAR,CAAyB,WAAUX,gBAAgB,CAACC,GAAD,CAAM,EAAzD;EACD,GAPiB;;EASlBW,EAAAA,iBAAiB,CAACL,OAAD,EAAU;EACzB,QAAI,CAACA,OAAL,EAAc;EACZ,aAAO,EAAP;EACD;;EAED,UAAMM,UAAU,GAAG,EAAnB;EAEAC,IAAAA,MAAM,CAACC,IAAP,CAAYR,OAAO,CAACS,OAApB,EACGC,MADH,CACUhB,GAAG,IAAIA,GAAG,CAACiB,UAAJ,CAAe,IAAf,CADjB,EAEGC,OAFH,CAEWlB,GAAG,IAAI;EACd,UAAImB,OAAO,GAAGnB,GAAG,CAACC,OAAJ,CAAY,KAAZ,EAAmB,EAAnB,CAAd;EACAkB,MAAAA,OAAO,GAAGA,OAAO,CAACC,MAAR,CAAe,CAAf,EAAkBjB,WAAlB,KAAkCgB,OAAO,CAACE,KAAR,CAAc,CAAd,EAAiBF,OAAO,CAACG,MAAzB,CAA5C;EACAV,MAAAA,UAAU,CAACO,OAAD,CAAV,GAAsBxB,aAAa,CAACW,OAAO,CAACS,OAAR,CAAgBf,GAAhB,CAAD,CAAnC;EACD,KANH;EAQA,WAAOY,UAAP;EACD,GAzBiB;;EA2BlBW,EAAAA,gBAAgB,CAACjB,OAAD,EAAUN,GAAV,EAAe;EAC7B,WAAOL,aAAa,CAACW,OAAO,CAACkB,YAAR,CAAsB,WAAUzB,gBAAgB,CAACC,GAAD,CAAM,EAAtD,CAAD,CAApB;EACD,GA7BiB;;EA+BlByB,EAAAA,MAAM,CAACnB,OAAD,EAAU;EACd,UAAMoB,IAAI,GAAGpB,OAAO,CAACqB,qBAAR,EAAb;EAEA,WAAO;EACLC,MAAAA,GAAG,EAAEF,IAAI,CAACE,GAAL,GAAWC,QAAQ,CAACC,IAAT,CAAcC,SADzB;EAELC,MAAAA,IAAI,EAAEN,IAAI,CAACM,IAAL,GAAYH,QAAQ,CAACC,IAAT,CAAcG;EAF3B,KAAP;EAID,GAtCiB;;EAwClBC,EAAAA,QAAQ,CAAC5B,OAAD,EAAU;EAChB,WAAO;EACLsB,MAAAA,GAAG,EAAEtB,OAAO,CAAC6B,SADR;EAELH,MAAAA,IAAI,EAAE1B,OAAO,CAAC8B;EAFT,KAAP;EAID;;EA7CiB;;;;;;;;"} {"version":3,"file":"manipulator.js","sources":["../../src/dom/manipulator.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nfunction normalizeData(val) {\n if (val === 'true') {\n return true\n }\n\n if (val === 'false') {\n return false\n }\n\n if (val === Number(val).toString()) {\n return Number(val)\n }\n\n if (val === '' || val === 'null') {\n return null\n }\n\n return val\n}\n\nfunction normalizeDataKey(key) {\n return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)\n}\n\nconst Manipulator = {\n setDataAttribute(element, key, value) {\n element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value)\n },\n\n removeDataAttribute(element, key) {\n element.removeAttribute(`data-bs-${normalizeDataKey(key)}`)\n },\n\n getDataAttributes(element) {\n if (!element) {\n return {}\n }\n\n const attributes = {}\n\n Object.keys(element.dataset)\n .filter(key => key.startsWith('bs'))\n .forEach(key => {\n let pureKey = key.replace(/^bs/, '')\n pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length)\n attributes[pureKey] = normalizeData(element.dataset[key])\n })\n\n return attributes\n },\n\n getDataAttribute(element, key) {\n return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`))\n },\n\n offset(element) {\n const rect = element.getBoundingClientRect()\n\n return {\n top: rect.top + window.pageYOffset,\n left: rect.left + window.pageXOffset\n }\n },\n\n position(element) {\n return {\n top: element.offsetTop,\n left: element.offsetLeft\n }\n }\n}\n\nexport default Manipulator\n"],"names":["normalizeData","val","Number","toString","normalizeDataKey","key","replace","chr","toLowerCase","Manipulator","setDataAttribute","element","value","setAttribute","removeDataAttribute","removeAttribute","getDataAttributes","attributes","Object","keys","dataset","filter","startsWith","forEach","pureKey","charAt","slice","length","getDataAttribute","getAttribute","offset","rect","getBoundingClientRect","top","window","pageYOffset","left","pageXOffset","position","offsetTop","offsetLeft"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;EAEA,SAASA,aAAT,CAAuBC,GAAvB,EAA4B;EAC1B,MAAIA,GAAG,KAAK,MAAZ,EAAoB;EAClB,WAAO,IAAP;EACD;;EAED,MAAIA,GAAG,KAAK,OAAZ,EAAqB;EACnB,WAAO,KAAP;EACD;;EAED,MAAIA,GAAG,KAAKC,MAAM,CAACD,GAAD,CAAN,CAAYE,QAAZ,EAAZ,EAAoC;EAClC,WAAOD,MAAM,CAACD,GAAD,CAAb;EACD;;EAED,MAAIA,GAAG,KAAK,EAAR,IAAcA,GAAG,KAAK,MAA1B,EAAkC;EAChC,WAAO,IAAP;EACD;;EAED,SAAOA,GAAP;EACD;;EAED,SAASG,gBAAT,CAA0BC,GAA1B,EAA+B;EAC7B,SAAOA,GAAG,CAACC,OAAJ,CAAY,QAAZ,EAAsBC,GAAG,IAAK,IAAGA,GAAG,CAACC,WAAJ,EAAkB,EAAnD,CAAP;EACD;;QAEKC,WAAW,GAAG;EAClBC,EAAAA,gBAAgB,CAACC,OAAD,EAAUN,GAAV,EAAeO,KAAf,EAAsB;EACpCD,IAAAA,OAAO,CAACE,YAAR,CAAsB,WAAUT,gBAAgB,CAACC,GAAD,CAAM,EAAtD,EAAyDO,KAAzD;EACD,GAHiB;;EAKlBE,EAAAA,mBAAmB,CAACH,OAAD,EAAUN,GAAV,EAAe;EAChCM,IAAAA,OAAO,CAACI,eAAR,CAAyB,WAAUX,gBAAgB,CAACC,GAAD,CAAM,EAAzD;EACD,GAPiB;;EASlBW,EAAAA,iBAAiB,CAACL,OAAD,EAAU;EACzB,QAAI,CAACA,OAAL,EAAc;EACZ,aAAO,EAAP;EACD;;EAED,UAAMM,UAAU,GAAG,EAAnB;EAEAC,IAAAA,MAAM,CAACC,IAAP,CAAYR,OAAO,CAACS,OAApB,EACGC,MADH,CACUhB,GAAG,IAAIA,GAAG,CAACiB,UAAJ,CAAe,IAAf,CADjB,EAEGC,OAFH,CAEWlB,GAAG,IAAI;EACd,UAAImB,OAAO,GAAGnB,GAAG,CAACC,OAAJ,CAAY,KAAZ,EAAmB,EAAnB,CAAd;EACAkB,MAAAA,OAAO,GAAGA,OAAO,CAACC,MAAR,CAAe,CAAf,EAAkBjB,WAAlB,KAAkCgB,OAAO,CAACE,KAAR,CAAc,CAAd,EAAiBF,OAAO,CAACG,MAAzB,CAA5C;EACAV,MAAAA,UAAU,CAACO,OAAD,CAAV,GAAsBxB,aAAa,CAACW,OAAO,CAACS,OAAR,CAAgBf,GAAhB,CAAD,CAAnC;EACD,KANH;EAQA,WAAOY,UAAP;EACD,GAzBiB;;EA2BlBW,EAAAA,gBAAgB,CAACjB,OAAD,EAAUN,GAAV,EAAe;EAC7B,WAAOL,aAAa,CAACW,OAAO,CAACkB,YAAR,CAAsB,WAAUzB,gBAAgB,CAACC,GAAD,CAAM,EAAtD,CAAD,CAApB;EACD,GA7BiB;;EA+BlByB,EAAAA,MAAM,CAACnB,OAAD,EAAU;EACd,UAAMoB,IAAI,GAAGpB,OAAO,CAACqB,qBAAR,EAAb;EAEA,WAAO;EACLC,MAAAA,GAAG,EAAEF,IAAI,CAACE,GAAL,GAAWC,MAAM,CAACC,WADlB;EAELC,MAAAA,IAAI,EAAEL,IAAI,CAACK,IAAL,GAAYF,MAAM,CAACG;EAFpB,KAAP;EAID,GAtCiB;;EAwClBC,EAAAA,QAAQ,CAAC3B,OAAD,EAAU;EAChB,WAAO;EACLsB,MAAAA,GAAG,EAAEtB,OAAO,CAAC4B,SADR;EAELH,MAAAA,IAAI,EAAEzB,OAAO,CAAC6B;EAFT,KAAP;EAID;;EA7CiB;;;;;;;;"}

View File

@ -1,5 +1,5 @@
/*! /*!
* Bootstrap selector-engine.js v5.0.1 (https://getbootstrap.com/) * Bootstrap selector-engine.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
@ -15,15 +15,52 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/selector-engine.js * Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const isElement = (obj) => {
if (!obj || typeof obj !== 'object') {
return false;
}
if (typeof obj.jquery !== 'undefined') {
obj = obj[0];
}
return typeof obj.nodeType !== 'undefined';
};
const isVisible = (element) => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
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;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
/** /**
* ------------------------------------------------------------------------ * --------------------------------------------------------------------------
* Constants * Bootstrap (v5.1.3): dom/selector-engine.js
* ------------------------------------------------------------------------ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/ */
const NODE_TEXT = 3; const NODE_TEXT = 3;
const SelectorEngine = { const SelectorEngine = {
@ -85,6 +122,22 @@
return []; return [];
}, },
focusableChildren(element) {
const focusables = [
'a',
'button',
'input',
'textarea',
'select',
'details',
'[tabindex]',
'[contenteditable="true"]',
]
.map((selector) => `${selector}:not([tabindex^="-"])`)
.join(', ');
return this.find(focusables, element).filter((el) => !isDisabled(el) && isVisible(el));
},
}; };
return SelectorEngine; return SelectorEngine;

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/*! /*!
* Bootstrap dropdown.js v5.0.1 (https://getbootstrap.com/) * Bootstrap dropdown.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
@ -7,44 +7,43 @@
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('@popperjs/core'), require('@popperjs/core'),
require('./dom/selector-engine.js'),
require('./dom/data.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./dom/selector-engine.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(
[
'@popperjs/core', '@popperjs/core',
'./dom/selector-engine',
'./dom/data',
'./dom/event-handler', './dom/event-handler',
'./dom/manipulator', './dom/manipulator',
'./dom/selector-engine',
'./base-component', './base-component',
], factory) ],
factory
)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Dropdown = factory( (global.Dropdown = factory(
global.Popper, global.Popper,
global.SelectorEngine,
global.Data,
global.EventHandler, global.EventHandler,
global.Manipulator, global.Manipulator,
global.SelectorEngine,
global.Base global.Base
))); )));
})(this, function (Popper, SelectorEngine, Data, EventHandler, Manipulator, BaseComponent) { })(this, function (Popper, EventHandler, Manipulator, SelectorEngine, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
function _interopNamespace(e) { function _interopNamespace(e) {
if (e && e.__esModule) return e; if (e && e.__esModule) return e;
var n = Object.create(null); const n = Object.create(null);
if (e) { if (e) {
Object.keys(e).forEach(function (k) { for (const k in e) {
if (k !== 'default') { if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k); const d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty( Object.defineProperty(
n, n,
k, k,
@ -52,24 +51,28 @@
? d ? d
: { : {
enumerable: true, enumerable: true,
get: function () { get: () => e[k],
return e[k];
},
} }
); );
} }
});
} }
n['default'] = e; }
n.default = e;
return Object.freeze(n); return Object.freeze(n);
} }
var Popper__namespace = /*#__PURE__*/ _interopNamespace(Popper); const Popper__namespace = /*#__PURE__*/ _interopNamespace(Popper);
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const toType = (obj) => { const toType = (obj) => {
if (obj === null || obj === undefined) { if (obj === null || obj === undefined) {
@ -129,7 +132,7 @@
} }
if (typeof obj === 'string' && obj.length > 0) { if (typeof obj === 'string' && obj.length > 0) {
return SelectorEngine__default['default'].findOne(obj); return document.querySelector(obj);
} }
return null; return null;
@ -150,21 +153,11 @@
}; };
const isVisible = (element) => { const isVisible = (element) => {
if (!element) { if (!isElement(element) || element.getClientRects().length === 0) {
return false; return false;
} }
if (element.style && element.parentNode && element.parentNode.style) { return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
const elementStyle = getComputedStyle(element);
const parentNodeStyle = getComputedStyle(element.parentNode);
return (
elementStyle.display !== 'none' &&
parentNodeStyle.display !== 'none' &&
elementStyle.visibility !== 'hidden'
);
}
return false;
}; };
const isDisabled = (element) => { const isDisabled = (element) => {
@ -195,9 +188,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -223,10 +225,36 @@
} }
}); });
}; };
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
let index = list.indexOf(activeElement); // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
if (index === -1) {
return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];
}
const listLength = list.length;
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dropdown.js * Bootstrap (v5.1.3): dropdown.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -252,7 +280,6 @@
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_CLICK = `click${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`;
@ -293,15 +320,13 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Dropdown extends BaseComponent__default['default'] { class Dropdown extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
this._popper = null; this._popper = null;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._menu = this._getMenuElement(); this._menu = this._getMenuElement();
this._inNavbar = this._detectNavbar(); this._inNavbar = this._detectNavbar();
this._addEventListeners();
} // Getters } // Getters
static get Default() { static get Default() {
@ -317,30 +342,18 @@
} // Public } // Public
toggle() { toggle() {
if (isDisabled(this._element)) { return this._isShown() ? this.hide() : this.show();
return;
}
const isActive = this._element.classList.contains(CLASS_NAME_SHOW);
if (isActive) {
this.hide();
return;
}
this.show();
} }
show() { show() {
if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW)) { if (isDisabled(this._element) || this._isShown(this._menu)) {
return; return;
} }
const parent = Dropdown.getParentFromElement(this._element);
const relatedTarget = { const relatedTarget = {
relatedTarget: this._element, relatedTarget: this._element,
}; };
const showEvent = EventHandler__default['default'].trigger( const showEvent = EventHandler__default.default.trigger(
this._element, this._element,
EVENT_SHOW, EVENT_SHOW,
relatedTarget relatedTarget
@ -348,35 +361,14 @@
if (showEvent.defaultPrevented) { if (showEvent.defaultPrevented) {
return; return;
} // Totally disable Popper for Dropdowns in Navbar }
const parent = Dropdown.getParentFromElement(this._element); // Totally disable Popper for Dropdowns in Navbar
if (this._inNavbar) { if (this._inNavbar) {
Manipulator__default['default'].setDataAttribute(this._menu, 'popper', 'none'); Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'none');
} else { } else {
if (typeof Popper__namespace === 'undefined') { this._createPopper(parent);
throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");
}
let referenceElement = this._element;
if (this._config.reference === 'parent') {
referenceElement = parent;
} else if (isElement(this._config.reference)) {
referenceElement = getElement(this._config.reference);
} else if (typeof this._config.reference === 'object') {
referenceElement = this._config.reference;
}
const popperConfig = this._getPopperConfig();
const isDisplayStatic = popperConfig.modifiers.find(
(modifier) => modifier.name === 'applyStyles' && modifier.enabled === false
);
this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig);
if (isDisplayStatic) {
Manipulator__default['default'].setDataAttribute(this._menu, 'popper', 'static');
}
} // If this is a touch-enabled device we add extra } // If this is a touch-enabled device we add extra
// empty mouseover listeners to the body's immediate children; // empty mouseover listeners to the body's immediate children;
// only needed because of broken event delegation on iOS // only needed because of broken event delegation on iOS
@ -385,22 +377,22 @@
if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) { if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) {
[] []
.concat(...document.body.children) .concat(...document.body.children)
.forEach((elem) => EventHandler__default['default'].on(elem, 'mouseover', noop)); .forEach((elem) => EventHandler__default.default.on(elem, 'mouseover', noop));
} }
this._element.focus(); this._element.focus();
this._element.setAttribute('aria-expanded', true); this._element.setAttribute('aria-expanded', true);
this._menu.classList.toggle(CLASS_NAME_SHOW); this._menu.classList.add(CLASS_NAME_SHOW);
this._element.classList.toggle(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, relatedTarget); EventHandler__default.default.trigger(this._element, EVENT_SHOWN, relatedTarget);
} }
hide() { hide() {
if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW)) { if (isDisabled(this._element) || !this._isShown(this._menu)) {
return; return;
} }
@ -427,15 +419,8 @@
} }
} // Private } // Private
_addEventListeners() {
EventHandler__default['default'].on(this._element, EVENT_CLICK, (event) => {
event.preventDefault();
this.toggle();
});
}
_completeHide(relatedTarget) { _completeHide(relatedTarget) {
const hideEvent = EventHandler__default['default'].trigger( const hideEvent = EventHandler__default.default.trigger(
this._element, this._element,
EVENT_HIDE, EVENT_HIDE,
relatedTarget relatedTarget
@ -449,7 +434,7 @@
if ('ontouchstart' in document.documentElement) { if ('ontouchstart' in document.documentElement) {
[] []
.concat(...document.body.children) .concat(...document.body.children)
.forEach((elem) => EventHandler__default['default'].off(elem, 'mouseover', noop)); .forEach((elem) => EventHandler__default.default.off(elem, 'mouseover', noop));
} }
if (this._popper) { if (this._popper) {
@ -462,14 +447,14 @@
this._element.setAttribute('aria-expanded', 'false'); this._element.setAttribute('aria-expanded', 'false');
Manipulator__default['default'].removeDataAttribute(this._menu, 'popper'); Manipulator__default.default.removeDataAttribute(this._menu, 'popper');
EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN, relatedTarget); EventHandler__default.default.trigger(this._element, EVENT_HIDDEN, relatedTarget);
} }
_getConfig(config) { _getConfig(config) {
config = { config = {
...this.constructor.Default, ...this.constructor.Default,
...Manipulator__default['default'].getDataAttributes(this._element), ...Manipulator__default.default.getDataAttributes(this._element),
...config, ...config,
}; };
typeCheckConfig(NAME, config, this.constructor.DefaultType); typeCheckConfig(NAME, config, this.constructor.DefaultType);
@ -488,8 +473,39 @@
return config; return config;
} }
_createPopper(parent) {
if (typeof Popper__namespace === 'undefined') {
throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");
}
let referenceElement = this._element;
if (this._config.reference === 'parent') {
referenceElement = parent;
} else if (isElement(this._config.reference)) {
referenceElement = getElement(this._config.reference);
} else if (typeof this._config.reference === 'object') {
referenceElement = this._config.reference;
}
const popperConfig = this._getPopperConfig();
const isDisplayStatic = popperConfig.modifiers.find(
(modifier) => modifier.name === 'applyStyles' && modifier.enabled === false
);
this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig);
if (isDisplayStatic) {
Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'static');
}
}
_isShown(element = this._element) {
return element.classList.contains(CLASS_NAME_SHOW);
}
_getMenuElement() { _getMenuElement() {
return SelectorEngine__default['default'].next(this._element, SELECTOR_MENU)[0]; return SelectorEngine__default.default.next(this._element, SELECTOR_MENU)[0];
} }
_getPlacement() { _getPlacement() {
@ -566,50 +582,32 @@
}; };
} }
_selectMenuItem(event) { _selectMenuItem({ key, target }) {
const items = SelectorEngine__default['default'] const items = SelectorEngine__default.default
.find(SELECTOR_VISIBLE_ITEMS, this._menu) .find(SELECTOR_VISIBLE_ITEMS, this._menu)
.filter(isVisible); .filter(isVisible);
if (!items.length) { if (!items.length) {
return; return;
} } // if target isn't included in items (e.g. when expanding the dropdown)
// allow cycling to get the last item in case key equals ARROW_UP_KEY
let index = items.indexOf(event.target); // Up getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
if (event.key === ARROW_UP_KEY && index > 0) {
index--;
} // Down
if (event.key === ARROW_DOWN_KEY && index < items.length - 1) {
index++;
} // index is -1 if the first keydown is an ArrowUp
index = index === -1 ? 0 : index;
items[index].focus();
} // Static } // Static
static dropdownInterface(element, config) { static jQueryInterface(config) {
let data = Data__default['default'].get(element, DATA_KEY); return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
const _config = typeof config === 'object' ? config : null; if (typeof config !== 'string') {
return;
if (!data) {
data = new Dropdown(element, _config);
} }
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`); throw new TypeError(`No method named "${config}"`);
} }
data[config](); data[config]();
}
}
static jQueryInterface(config) {
return this.each(function () {
Dropdown.dropdownInterface(this, config);
}); });
} }
@ -621,16 +619,16 @@
return; return;
} }
const toggles = SelectorEngine__default['default'].find(SELECTOR_DATA_TOGGLE); const toggles = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE);
for (let i = 0, len = toggles.length; i < len; i++) { for (let i = 0, len = toggles.length; i < len; i++) {
const context = Data__default['default'].get(toggles[i], DATA_KEY); const context = Dropdown.getInstance(toggles[i]);
if (!context || context._config.autoClose === false) { if (!context || context._config.autoClose === false) {
continue; continue;
} }
if (!context._element.classList.contains(CLASS_NAME_SHOW)) { if (!context._isShown()) {
continue; continue;
} }
@ -703,28 +701,29 @@
return; return;
} }
const getToggleButton = () => const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE)
this.matches(SELECTOR_DATA_TOGGLE)
? this ? this
: SelectorEngine__default['default'].prev(this, SELECTOR_DATA_TOGGLE)[0]; : SelectorEngine__default.default.prev(this, SELECTOR_DATA_TOGGLE)[0];
const instance = Dropdown.getOrCreateInstance(getToggleButton);
if (event.key === ESCAPE_KEY) { if (event.key === ESCAPE_KEY) {
getToggleButton().focus(); instance.hide();
Dropdown.clearMenus();
return; return;
} }
if (!isActive && (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY)) { if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {
getToggleButton().click(); if (!isActive) {
instance.show();
}
instance._selectMenuItem(event);
return; return;
} }
if (!isActive || event.key === SPACE_KEY) { if (!isActive || event.key === SPACE_KEY) {
Dropdown.clearMenus(); Dropdown.clearMenus();
return;
} }
Dropdown.getInstance(getToggleButton())._selectMenuItem(event);
} }
} }
/** /**
@ -733,27 +732,27 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_KEYDOWN_DATA_API, EVENT_KEYDOWN_DATA_API,
SELECTOR_DATA_TOGGLE, SELECTOR_DATA_TOGGLE,
Dropdown.dataApiKeydownHandler Dropdown.dataApiKeydownHandler
); );
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_KEYDOWN_DATA_API, EVENT_KEYDOWN_DATA_API,
SELECTOR_MENU, SELECTOR_MENU,
Dropdown.dataApiKeydownHandler Dropdown.dataApiKeydownHandler
); );
EventHandler__default['default'].on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus); EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus);
EventHandler__default['default'].on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); EventHandler__default.default.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_CLICK_DATA_API, EVENT_CLICK_DATA_API,
SELECTOR_DATA_TOGGLE, SELECTOR_DATA_TOGGLE,
function (event) { function (event) {
event.preventDefault(); event.preventDefault();
Dropdown.dropdownInterface(this); Dropdown.getOrCreateInstance(this).toggle();
} }
); );
/** /**

File diff suppressed because one or more lines are too long

View File

@ -1,42 +1,45 @@
/*! /*!
* Bootstrap modal.js v5.0.1 (https://getbootstrap.com/) * Bootstrap modal.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('./dom/selector-engine.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./dom/selector-engine.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(
'./dom/selector-engine', ['./dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'],
'./dom/event-handler', factory
'./dom/manipulator', )
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Modal = factory( (global.Modal = factory(
global.SelectorEngine,
global.EventHandler, global.EventHandler,
global.Manipulator, global.Manipulator,
global.SelectorEngine,
global.Base global.Base
))); )));
})(this, function (SelectorEngine, EventHandler, Manipulator, BaseComponent) { })(this, function (EventHandler, Manipulator, SelectorEngine, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MILLISECONDS_MULTIPLIER = 1000; const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
@ -116,22 +119,17 @@
return typeof obj.nodeType !== 'undefined'; return typeof obj.nodeType !== 'undefined';
}; };
const emulateTransitionEnd = (element, duration) => { const getElement = (obj) => {
let called = false; if (isElement(obj)) {
const durationPadding = 5; // it's a jQuery object or a node element
const emulatedDuration = duration + durationPadding; return obj.jquery ? obj[0] : obj;
function listener() {
called = true;
element.removeEventListener(TRANSITION_END, listener);
} }
element.addEventListener(TRANSITION_END, listener); if (typeof obj === 'string' && obj.length > 0) {
setTimeout(() => { return document.querySelector(obj);
if (!called) {
triggerTransitionEnd(element);
} }
}, emulatedDuration);
return null;
}; };
const typeCheckConfig = (componentName, config, configTypes) => { const typeCheckConfig = (componentName, config, configTypes) => {
@ -149,24 +147,41 @@
}; };
const isVisible = (element) => { const isVisible = (element) => {
if (!element) { if (!isElement(element) || element.getClientRects().length === 0) {
return false; return false;
} }
if (element.style && element.parentNode && element.parentNode.style) { return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
const elementStyle = getComputedStyle(element);
const parentNodeStyle = getComputedStyle(element.parentNode);
return (
elementStyle.display !== 'none' &&
parentNodeStyle.display !== 'none' &&
elementStyle.visibility !== 'hidden'
);
}
return false;
}; };
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 getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -178,9 +193,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -213,111 +237,173 @@
} }
}; };
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.0.1): util/scrollBar.js * Bootstrap (v5.1.3): util/scrollBar.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * 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_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
const SELECTOR_STICKY_CONTENT = '.sticky-top'; const SELECTOR_STICKY_CONTENT = '.sticky-top';
const getWidth = () => { class ScrollBarHelper {
constructor() {
this._element = document.body;
}
getWidth() {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
const documentWidth = document.documentElement.clientWidth; const documentWidth = document.documentElement.clientWidth;
return Math.abs(window.innerWidth - documentWidth); return Math.abs(window.innerWidth - documentWidth);
}; }
const hide = (width = getWidth()) => { hide() {
_disableOverFlow(); // give padding to element to balances the hidden scrollbar width const width = this.getWidth();
_setElementAttributes('body', 'paddingRight', (calculatedValue) => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements, to keep shown fullwidth this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width
_setElementAttributes( 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, SELECTOR_FIXED_CONTENT,
'paddingRight', 'paddingRight',
(calculatedValue) => calculatedValue + width (calculatedValue) => calculatedValue + width
); );
_setElementAttributes( this._setElementAttributes(
SELECTOR_STICKY_CONTENT, SELECTOR_STICKY_CONTENT,
'marginRight', 'marginRight',
(calculatedValue) => calculatedValue - width (calculatedValue) => calculatedValue - width
); );
};
const _disableOverFlow = () => {
const actualValue = document.body.style.overflow;
if (actualValue) {
Manipulator__default['default'].setDataAttribute(document.body, 'overflow', actualValue);
} }
document.body.style.overflow = 'hidden'; _disableOverFlow() {
}; this._saveInitialAttribute(this._element, 'overflow');
const _setElementAttributes = (selector, styleProp, callback) => { this._element.style.overflow = 'hidden';
const scrollbarWidth = getWidth(); }
SelectorEngine__default['default'].find(selector).forEach((element) => {
if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) { _setElementAttributes(selector, styleProp, callback) {
const scrollbarWidth = this.getWidth();
const manipulationCallBack = (element) => {
if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
return; return;
} }
const actualValue = element.style[styleProp]; this._saveInitialAttribute(element, styleProp);
const calculatedValue = window.getComputedStyle(element)[styleProp]; const calculatedValue = window.getComputedStyle(element)[styleProp];
Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue);
element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`; element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
});
}; };
const reset = () => { this._applyManipulationCallback(selector, manipulationCallBack);
_resetElementAttributes('body', 'overflow'); }
_resetElementAttributes('body', 'paddingRight'); reset() {
this._resetElementAttributes(this._element, 'overflow');
_resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight'); this._resetElementAttributes(this._element, 'paddingRight');
_resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight'); this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
};
const _resetElementAttributes = (selector, styleProp) => { this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
SelectorEngine__default['default'].find(selector).forEach((element) => { }
const value = Manipulator__default['default'].getDataAttribute(element, styleProp);
_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') { if (typeof value === 'undefined') {
element.style.removeProperty(styleProp); element.style.removeProperty(styleProp);
} else { } else {
Manipulator__default['default'].removeDataAttribute(element, styleProp); Manipulator__default.default.removeDataAttribute(element, styleProp);
element.style[styleProp] = value; 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.0.1): util/backdrop.js * Bootstrap (v5.1.3): util/backdrop.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const Default$1 = { const Default$2 = {
className: 'modal-backdrop',
isVisible: true, isVisible: true,
// if false, we use the backdrop helper without adding any element to the dom // if false, we use the backdrop helper without adding any element to the dom
isAnimated: false, isAnimated: false,
rootElement: document.body, rootElement: 'body',
// give the choice to place backdrop under different elements // give the choice to place backdrop under different elements
clickCallback: null, clickCallback: null,
}; };
const DefaultType$1 = { const DefaultType$2 = {
className: 'string',
isVisible: 'boolean', isVisible: 'boolean',
isAnimated: 'boolean', isAnimated: 'boolean',
rootElement: 'element', rootElement: '(element|string)',
clickCallback: '(function|null)', clickCallback: '(function|null)',
}; };
const NAME$1 = 'backdrop'; const NAME$2 = 'backdrop';
const CLASS_NAME_BACKDROP = 'modal-backdrop';
const CLASS_NAME_FADE$1 = 'fade'; const CLASS_NAME_FADE$1 = 'fade';
const CLASS_NAME_SHOW$1 = 'show'; const CLASS_NAME_SHOW$1 = 'show';
const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$1}`; const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$2}`;
class Backdrop { class Backdrop {
constructor(config) { constructor(config) {
@ -362,7 +448,7 @@
_getElement() { _getElement() {
if (!this._element) { if (!this._element) {
const backdrop = document.createElement('div'); const backdrop = document.createElement('div');
backdrop.className = CLASS_NAME_BACKDROP; backdrop.className = this._config.className;
if (this._config.isAnimated) { if (this._config.isAnimated) {
backdrop.classList.add(CLASS_NAME_FADE$1); backdrop.classList.add(CLASS_NAME_FADE$1);
@ -375,9 +461,10 @@
} }
_getConfig(config) { _getConfig(config) {
config = { ...Default$1, ...(typeof config === 'object' ? config : {}) }; config = { ...Default$2, ...(typeof config === 'object' ? config : {}) }; // use getElement() with the default "body" to get a fresh Element on each instantiation
config.rootElement = config.rootElement || document.body;
typeCheckConfig(NAME$1, config, DefaultType$1); config.rootElement = getElement(config.rootElement);
typeCheckConfig(NAME$2, config, DefaultType$2);
return config; return config;
} }
@ -386,9 +473,9 @@
return; return;
} }
this._config.rootElement.appendChild(this._getElement()); this._config.rootElement.append(this._getElement());
EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => { EventHandler__default.default.on(this._getElement(), EVENT_MOUSEDOWN, () => {
execute(this._config.clickCallback); execute(this._config.clickCallback);
}); });
this._isAppended = true; this._isAppended = true;
@ -399,30 +486,148 @@
return; return;
} }
EventHandler__default['default'].off(this._element, EVENT_MOUSEDOWN); EventHandler__default.default.off(this._element, EVENT_MOUSEDOWN);
this._getElement().parentNode.removeChild(this._element); this._element.remove();
this._isAppended = false; this._isAppended = false;
} }
_emulateAnimation(callback) { _emulateAnimation(callback) {
if (!this._config.isAnimated) { executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
execute(callback);
return;
}
const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement());
EventHandler__default['default'].one(this._getElement(), 'transitionend', () =>
execute(callback)
);
emulateTransitionEnd(this._getElement(), backdropTransitionDuration);
} }
} }
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): modal.js * Bootstrap (v5.1.3): util/focustrap.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/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.3): 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.3): modal.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -452,7 +657,6 @@
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_RESIZE = `resize${EVENT_KEY}`; const EVENT_RESIZE = `resize${EVENT_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`; const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
@ -463,25 +667,27 @@
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_STATIC = 'modal-static'; const CLASS_NAME_STATIC = 'modal-static';
const OPEN_SELECTOR = '.modal.show';
const SELECTOR_DIALOG = '.modal-dialog'; const SELECTOR_DIALOG = '.modal-dialog';
const SELECTOR_MODAL_BODY = '.modal-body'; const SELECTOR_MODAL_BODY = '.modal-body';
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]'; const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]';
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* Class Definition * Class Definition
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Modal extends BaseComponent__default['default'] { class Modal extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._dialog = SelectorEngine__default['default'].findOne(SELECTOR_DIALOG, this._element); this._dialog = SelectorEngine__default.default.findOne(SELECTOR_DIALOG, this._element);
this._backdrop = this._initializeBackDrop(); this._backdrop = this._initializeBackDrop();
this._focustrap = this._initializeFocusTrap();
this._isShown = false; this._isShown = false;
this._ignoreBackdropClick = false; this._ignoreBackdropClick = false;
this._isTransitioning = false; this._isTransitioning = false;
this._scrollBar = new ScrollBarHelper();
} // Getters } // Getters
static get Default() { static get Default() {
@ -501,20 +707,22 @@
return; return;
} }
if (this._isAnimated()) { const showEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW, {
this._isTransitioning = true;
}
const showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW, {
relatedTarget, relatedTarget,
}); });
if (this._isShown || showEvent.defaultPrevented) { if (showEvent.defaultPrevented) {
return; return;
} }
this._isShown = true; this._isShown = true;
hide();
if (this._isAnimated()) {
this._isTransitioning = true;
}
this._scrollBar.hide();
document.body.classList.add(CLASS_NAME_OPEN); document.body.classList.add(CLASS_NAME_OPEN);
this._adjustDialog(); this._adjustDialog();
@ -523,14 +731,8 @@
this._setResizeEvent(); this._setResizeEvent();
EventHandler__default['default'].on( EventHandler__default.default.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => {
this._element, EventHandler__default.default.one(this._element, EVENT_MOUSEUP_DISMISS, (event) => {
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) { if (event.target === this._element) {
this._ignoreBackdropClick = true; this._ignoreBackdropClick = true;
} }
@ -540,16 +742,12 @@
this._showBackdrop(() => this._showElement(relatedTarget)); this._showBackdrop(() => this._showElement(relatedTarget));
} }
hide(event) { hide() {
if (event) {
event.preventDefault();
}
if (!this._isShown || this._isTransitioning) { if (!this._isShown || this._isTransitioning) {
return; return;
} }
const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); const hideEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE);
if (hideEvent.defaultPrevented) { if (hideEvent.defaultPrevented) {
return; return;
@ -567,31 +765,26 @@
this._setResizeEvent(); this._setResizeEvent();
EventHandler__default['default'].off(document, EVENT_FOCUSIN); this._focustrap.deactivate();
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_SHOW);
EventHandler__default['default'].off(this._element, EVENT_CLICK_DISMISS); EventHandler__default.default.off(this._element, EVENT_CLICK_DISMISS);
EventHandler__default['default'].off(this._dialog, EVENT_MOUSEDOWN_DISMISS); EventHandler__default.default.off(this._dialog, EVENT_MOUSEDOWN_DISMISS);
this._queueCallback(() => this._hideModal(), this._element, isAnimated); this._queueCallback(() => this._hideModal(), this._element, isAnimated);
} }
dispose() { dispose() {
[window, this._dialog].forEach((htmlElement) => [window, this._dialog].forEach((htmlElement) =>
EventHandler__default['default'].off(htmlElement, EVENT_KEY) EventHandler__default.default.off(htmlElement, EVENT_KEY)
); );
this._backdrop.dispose(); this._backdrop.dispose();
super.dispose(); this._focustrap.deactivate();
/**
* `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); super.dispose();
} }
handleUpdate() { handleUpdate() {
@ -606,11 +799,17 @@
}); });
} }
_initializeFocusTrap() {
return new FocusTrap({
trapElement: this._element,
});
}
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator__default['default'].getDataAttributes(this._element), ...Manipulator__default.default.getDataAttributes(this._element),
...config, ...(typeof config === 'object' ? config : {}),
}; };
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
@ -619,14 +818,11 @@
_showElement(relatedTarget) { _showElement(relatedTarget) {
const isAnimated = this._isAnimated(); const isAnimated = this._isAnimated();
const modalBody = SelectorEngine__default['default'].findOne( const modalBody = SelectorEngine__default.default.findOne(SELECTOR_MODAL_BODY, this._dialog);
SELECTOR_MODAL_BODY,
this._dialog
);
if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
// Don't move modal's DOM position // Don't move modal's DOM position
document.body.appendChild(this._element); document.body.append(this._element);
} }
this._element.style.display = 'block'; this._element.style.display = 'block';
@ -649,17 +845,13 @@
this._element.classList.add(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
if (this._config.focus) {
this._enforceFocus();
}
const transitionComplete = () => { const transitionComplete = () => {
if (this._config.focus) { if (this._config.focus) {
this._element.focus(); this._focustrap.activate();
} }
this._isTransitioning = false; this._isTransitioning = false;
EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, { EventHandler__default.default.trigger(this._element, EVENT_SHOWN, {
relatedTarget, relatedTarget,
}); });
}; };
@ -667,23 +859,9 @@
this._queueCallback(transitionComplete, this._dialog, isAnimated); 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() { _setEscapeEvent() {
if (this._isShown) { if (this._isShown) {
EventHandler__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, (event) => { EventHandler__default.default.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => {
if (this._config.keyboard && event.key === ESCAPE_KEY) { if (this._config.keyboard && event.key === ESCAPE_KEY) {
event.preventDefault(); event.preventDefault();
this.hide(); this.hide();
@ -692,15 +870,15 @@
} }
}); });
} else { } else {
EventHandler__default['default'].off(this._element, EVENT_KEYDOWN_DISMISS); EventHandler__default.default.off(this._element, EVENT_KEYDOWN_DISMISS);
} }
} }
_setResizeEvent() { _setResizeEvent() {
if (this._isShown) { if (this._isShown) {
EventHandler__default['default'].on(window, EVENT_RESIZE, () => this._adjustDialog()); EventHandler__default.default.on(window, EVENT_RESIZE, () => this._adjustDialog());
} else { } else {
EventHandler__default['default'].off(window, EVENT_RESIZE); EventHandler__default.default.off(window, EVENT_RESIZE);
} }
} }
@ -720,13 +898,14 @@
this._resetAdjustments(); this._resetAdjustments();
reset(); this._scrollBar.reset();
EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN);
EventHandler__default.default.trigger(this._element, EVENT_HIDDEN);
}); });
} }
_showBackdrop(callback) { _showBackdrop(callback) {
EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, (event) => { EventHandler__default.default.on(this._element, EVENT_CLICK_DISMISS, (event) => {
if (this._ignoreBackdropClick) { if (this._ignoreBackdropClick) {
this._ignoreBackdropClick = false; this._ignoreBackdropClick = false;
return; return;
@ -751,36 +930,37 @@
} }
_triggerBackdropTransition() { _triggerBackdropTransition() {
const hideEvent = EventHandler__default['default'].trigger( const hideEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE_PREVENTED);
this._element,
EVENT_HIDE_PREVENTED
);
if (hideEvent.defaultPrevented) { if (hideEvent.defaultPrevented) {
return; 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) { if (
this._element.style.overflowY = 'hidden'; (!isModalOverflowing && style.overflowY === 'hidden') ||
classList.contains(CLASS_NAME_STATIC)
) {
return;
} }
this._element.classList.add(CLASS_NAME_STATIC); if (!isModalOverflowing) {
style.overflowY = 'hidden';
}
const modalTransitionDuration = getTransitionDurationFromElement(this._dialog); classList.add(CLASS_NAME_STATIC);
EventHandler__default['default'].off(this._element, 'transitionend');
EventHandler__default['default'].one(this._element, 'transitionend', () => { this._queueCallback(() => {
this._element.classList.remove(CLASS_NAME_STATIC); classList.remove(CLASS_NAME_STATIC);
if (!isModalOverflowing) { if (!isModalOverflowing) {
EventHandler__default['default'].one(this._element, 'transitionend', () => { this._queueCallback(() => {
this._element.style.overflowY = ''; style.overflowY = '';
}); }, this._dialog);
emulateTransitionEnd(this._element, modalTransitionDuration);
} }
}); }, this._dialog);
emulateTransitionEnd(this._element, modalTransitionDuration);
this._element.focus(); this._element.focus();
} // ---------------------------------------------------------------------- } // ----------------------------------------------------------------------
@ -789,7 +969,9 @@
_adjustDialog() { _adjustDialog() {
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
const scrollbarWidth = getWidth();
const scrollbarWidth = this._scrollBar.getWidth();
const isBodyOverflowing = scrollbarWidth > 0; const isBodyOverflowing = scrollbarWidth > 0;
if ( if (
@ -814,8 +996,7 @@
static jQueryInterface(config, relatedTarget) { static jQueryInterface(config, relatedTarget) {
return this.each(function () { return this.each(function () {
const data = const data = Modal.getOrCreateInstance(this, config);
Modal.getInstance(this) || new Modal(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -835,7 +1016,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_CLICK_DATA_API, EVENT_CLICK_DATA_API,
SELECTOR_DATA_TOGGLE, SELECTOR_DATA_TOGGLE,
@ -846,22 +1027,30 @@
event.preventDefault(); event.preventDefault();
} }
EventHandler__default['default'].one(target, EVENT_SHOW, (showEvent) => { EventHandler__default.default.one(target, EVENT_SHOW, (showEvent) => {
if (showEvent.defaultPrevented) { if (showEvent.defaultPrevented) {
// only register focus restorer if modal will actually get shown // only register focus restorer if modal will actually get shown
return; return;
} }
EventHandler__default['default'].one(target, EVENT_HIDDEN, () => { EventHandler__default.default.one(target, EVENT_HIDDEN, () => {
if (isVisible(this)) { if (isVisible(this)) {
this.focus(); this.focus();
} }
}); });
}); }); // avoid conflict when clicking moddal toggler while another one is open
const data = Modal.getInstance(target) || new Modal(target);
const allReadyOpen = SelectorEngine__default.default.findOne(OPEN_SELECTOR);
if (allReadyOpen) {
Modal.getInstance(allReadyOpen).hide();
}
const data = Modal.getOrCreateInstance(target);
data.toggle(this); data.toggle(this);
} }
); );
enableDismissTrigger(Modal);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/*! /*!
* Bootstrap offcanvas.js v5.0.1 (https://getbootstrap.com/) * Bootstrap offcanvas.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
@ -8,39 +8,38 @@
? (module.exports = factory( ? (module.exports = factory(
require('./dom/selector-engine.js'), require('./dom/selector-engine.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./dom/data.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(
'./dom/selector-engine', ['./dom/selector-engine', './dom/manipulator', './dom/event-handler', './base-component'],
'./dom/manipulator', factory
'./dom/data', )
'./dom/event-handler',
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Offcanvas = factory( (global.Offcanvas = factory(
global.SelectorEngine, global.SelectorEngine,
global.Manipulator, global.Manipulator,
global.Data,
global.EventHandler, global.EventHandler,
global.Base global.Base
))); )));
})(this, function (SelectorEngine, Manipulator, Data, EventHandler, BaseComponent) { })(this, function (SelectorEngine, Manipulator, EventHandler, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MILLISECONDS_MULTIPLIER = 1000; const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
@ -120,22 +119,17 @@
return typeof obj.nodeType !== 'undefined'; return typeof obj.nodeType !== 'undefined';
}; };
const emulateTransitionEnd = (element, duration) => { const getElement = (obj) => {
let called = false; if (isElement(obj)) {
const durationPadding = 5; // it's a jQuery object or a node element
const emulatedDuration = duration + durationPadding; return obj.jquery ? obj[0] : obj;
function listener() {
called = true;
element.removeEventListener(TRANSITION_END, listener);
} }
element.addEventListener(TRANSITION_END, listener); if (typeof obj === 'string' && obj.length > 0) {
setTimeout(() => { return document.querySelector(obj);
if (!called) {
triggerTransitionEnd(element);
} }
}, emulatedDuration);
return null;
}; };
const typeCheckConfig = (componentName, config, configTypes) => { const typeCheckConfig = (componentName, config, configTypes) => {
@ -153,21 +147,11 @@
}; };
const isVisible = (element) => { const isVisible = (element) => {
if (!element) { if (!isElement(element) || element.getClientRects().length === 0) {
return false; return false;
} }
if (element.style && element.parentNode && element.parentNode.style) { return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
const elementStyle = getComputedStyle(element);
const parentNodeStyle = getComputedStyle(element.parentNode);
return (
elementStyle.display !== 'none' &&
parentNodeStyle.display !== 'none' &&
elementStyle.visibility !== 'hidden'
);
}
return false;
}; };
const isDisabled = (element) => { const isDisabled = (element) => {
@ -185,8 +169,19 @@
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; 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) => element.offsetHeight; const reflow = (element) => {
// eslint-disable-next-line no-unused-expressions
element.offsetHeight;
};
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -198,9 +193,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -231,111 +235,173 @@
} }
}; };
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.0.1): util/scrollBar.js * Bootstrap (v5.1.3): util/scrollBar.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * 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_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
const SELECTOR_STICKY_CONTENT = '.sticky-top'; const SELECTOR_STICKY_CONTENT = '.sticky-top';
const getWidth = () => { class ScrollBarHelper {
constructor() {
this._element = document.body;
}
getWidth() {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
const documentWidth = document.documentElement.clientWidth; const documentWidth = document.documentElement.clientWidth;
return Math.abs(window.innerWidth - documentWidth); return Math.abs(window.innerWidth - documentWidth);
}; }
const hide = (width = getWidth()) => { hide() {
_disableOverFlow(); // give padding to element to balances the hidden scrollbar width const width = this.getWidth();
_setElementAttributes('body', 'paddingRight', (calculatedValue) => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements, to keep shown fullwidth this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width
_setElementAttributes( 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, SELECTOR_FIXED_CONTENT,
'paddingRight', 'paddingRight',
(calculatedValue) => calculatedValue + width (calculatedValue) => calculatedValue + width
); );
_setElementAttributes( this._setElementAttributes(
SELECTOR_STICKY_CONTENT, SELECTOR_STICKY_CONTENT,
'marginRight', 'marginRight',
(calculatedValue) => calculatedValue - width (calculatedValue) => calculatedValue - width
); );
};
const _disableOverFlow = () => {
const actualValue = document.body.style.overflow;
if (actualValue) {
Manipulator__default['default'].setDataAttribute(document.body, 'overflow', actualValue);
} }
document.body.style.overflow = 'hidden'; _disableOverFlow() {
}; this._saveInitialAttribute(this._element, 'overflow');
const _setElementAttributes = (selector, styleProp, callback) => { this._element.style.overflow = 'hidden';
const scrollbarWidth = getWidth(); }
SelectorEngine__default['default'].find(selector).forEach((element) => {
if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) { _setElementAttributes(selector, styleProp, callback) {
const scrollbarWidth = this.getWidth();
const manipulationCallBack = (element) => {
if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
return; return;
} }
const actualValue = element.style[styleProp]; this._saveInitialAttribute(element, styleProp);
const calculatedValue = window.getComputedStyle(element)[styleProp]; const calculatedValue = window.getComputedStyle(element)[styleProp];
Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue);
element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`; element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
});
}; };
const reset = () => { this._applyManipulationCallback(selector, manipulationCallBack);
_resetElementAttributes('body', 'overflow'); }
_resetElementAttributes('body', 'paddingRight'); reset() {
this._resetElementAttributes(this._element, 'overflow');
_resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight'); this._resetElementAttributes(this._element, 'paddingRight');
_resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight'); this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
};
const _resetElementAttributes = (selector, styleProp) => { this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
SelectorEngine__default['default'].find(selector).forEach((element) => { }
const value = Manipulator__default['default'].getDataAttribute(element, styleProp);
_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') { if (typeof value === 'undefined') {
element.style.removeProperty(styleProp); element.style.removeProperty(styleProp);
} else { } else {
Manipulator__default['default'].removeDataAttribute(element, styleProp); Manipulator__default.default.removeDataAttribute(element, styleProp);
element.style[styleProp] = value; 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.0.1): util/backdrop.js * Bootstrap (v5.1.3): util/backdrop.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const Default$1 = { const Default$2 = {
className: 'modal-backdrop',
isVisible: true, isVisible: true,
// if false, we use the backdrop helper without adding any element to the dom // if false, we use the backdrop helper without adding any element to the dom
isAnimated: false, isAnimated: false,
rootElement: document.body, rootElement: 'body',
// give the choice to place backdrop under different elements // give the choice to place backdrop under different elements
clickCallback: null, clickCallback: null,
}; };
const DefaultType$1 = { const DefaultType$2 = {
className: 'string',
isVisible: 'boolean', isVisible: 'boolean',
isAnimated: 'boolean', isAnimated: 'boolean',
rootElement: 'element', rootElement: '(element|string)',
clickCallback: '(function|null)', clickCallback: '(function|null)',
}; };
const NAME$1 = 'backdrop'; const NAME$2 = 'backdrop';
const CLASS_NAME_BACKDROP = 'modal-backdrop';
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW$1 = 'show'; const CLASS_NAME_SHOW$1 = 'show';
const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$1}`; const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$2}`;
class Backdrop { class Backdrop {
constructor(config) { constructor(config) {
@ -380,7 +446,7 @@
_getElement() { _getElement() {
if (!this._element) { if (!this._element) {
const backdrop = document.createElement('div'); const backdrop = document.createElement('div');
backdrop.className = CLASS_NAME_BACKDROP; backdrop.className = this._config.className;
if (this._config.isAnimated) { if (this._config.isAnimated) {
backdrop.classList.add(CLASS_NAME_FADE); backdrop.classList.add(CLASS_NAME_FADE);
@ -393,9 +459,10 @@
} }
_getConfig(config) { _getConfig(config) {
config = { ...Default$1, ...(typeof config === 'object' ? config : {}) }; config = { ...Default$2, ...(typeof config === 'object' ? config : {}) }; // use getElement() with the default "body" to get a fresh Element on each instantiation
config.rootElement = config.rootElement || document.body;
typeCheckConfig(NAME$1, config, DefaultType$1); config.rootElement = getElement(config.rootElement);
typeCheckConfig(NAME$2, config, DefaultType$2);
return config; return config;
} }
@ -404,9 +471,9 @@
return; return;
} }
this._config.rootElement.appendChild(this._getElement()); this._config.rootElement.append(this._getElement());
EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => { EventHandler__default.default.on(this._getElement(), EVENT_MOUSEDOWN, () => {
execute(this._config.clickCallback); execute(this._config.clickCallback);
}); });
this._isAppended = true; this._isAppended = true;
@ -417,31 +484,149 @@
return; return;
} }
EventHandler__default['default'].off(this._element, EVENT_MOUSEDOWN); EventHandler__default.default.off(this._element, EVENT_MOUSEDOWN);
this._getElement().parentNode.removeChild(this._element); this._element.remove();
this._isAppended = false; this._isAppended = false;
} }
_emulateAnimation(callback) { _emulateAnimation(callback) {
if (!this._config.isAnimated) { executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
execute(callback);
return;
}
const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement());
EventHandler__default['default'].one(this._getElement(), 'transitionend', () =>
execute(callback)
);
emulateTransitionEnd(this._getElement(), backdropTransitionDuration);
} }
} }
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): offcanvas.js * Bootstrap (v5.1.3): util/focustrap.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/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.3): 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.3): offcanvas.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
/** /**
@ -467,16 +652,14 @@
scroll: 'boolean', scroll: 'boolean',
}; };
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
const OPEN_SELECTOR = '.offcanvas.show'; const OPEN_SELECTOR = '.offcanvas.show';
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_HIDE = `hide${EVENT_KEY}`; const EVENT_HIDE = `hide${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]';
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]'; const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -484,12 +667,13 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Offcanvas extends BaseComponent__default['default'] { class Offcanvas extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._isShown = false; this._isShown = false;
this._backdrop = this._initializeBackDrop(); this._backdrop = this._initializeBackDrop();
this._focustrap = this._initializeFocusTrap();
this._addEventListeners(); this._addEventListeners();
} // Getters } // Getters
@ -511,7 +695,7 @@
return; return;
} }
const showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW, { const showEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW, {
relatedTarget, relatedTarget,
}); });
@ -525,9 +709,7 @@
this._backdrop.show(); this._backdrop.show();
if (!this._config.scroll) { if (!this._config.scroll) {
hide(); new ScrollBarHelper().hide();
this._enforceFocusOnElement(this._element);
} }
this._element.removeAttribute('aria-hidden'); this._element.removeAttribute('aria-hidden');
@ -539,7 +721,11 @@
this._element.classList.add(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
const completeCallBack = () => { const completeCallBack = () => {
EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, { if (!this._config.scroll) {
this._focustrap.activate();
}
EventHandler__default.default.trigger(this._element, EVENT_SHOWN, {
relatedTarget, relatedTarget,
}); });
}; };
@ -552,13 +738,13 @@
return; return;
} }
const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); const hideEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE);
if (hideEvent.defaultPrevented) { if (hideEvent.defaultPrevented) {
return; return;
} }
EventHandler__default['default'].off(document, EVENT_FOCUSIN); this._focustrap.deactivate();
this._element.blur(); this._element.blur();
@ -578,10 +764,10 @@
this._element.style.visibility = 'hidden'; this._element.style.visibility = 'hidden';
if (!this._config.scroll) { if (!this._config.scroll) {
reset(); new ScrollBarHelper().reset();
} }
EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN); EventHandler__default.default.trigger(this._element, EVENT_HIDDEN);
}; };
this._queueCallback(completeCallback, this._element, true); this._queueCallback(completeCallback, this._element, true);
@ -590,14 +776,15 @@
dispose() { dispose() {
this._backdrop.dispose(); this._backdrop.dispose();
this._focustrap.deactivate();
super.dispose(); super.dispose();
EventHandler__default['default'].off(document, EVENT_FOCUSIN);
} // Private } // Private
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator__default['default'].getDataAttributes(this._element), ...Manipulator__default.default.getDataAttributes(this._element),
...(typeof config === 'object' ? config : {}), ...(typeof config === 'object' ? config : {}),
}; };
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
@ -606,6 +793,7 @@
_initializeBackDrop() { _initializeBackDrop() {
return new Backdrop({ return new Backdrop({
className: CLASS_NAME_BACKDROP,
isVisible: this._config.backdrop, isVisible: this._config.backdrop,
isAnimated: true, isAnimated: true,
rootElement: this._element.parentNode, rootElement: this._element.parentNode,
@ -613,29 +801,14 @@
}); });
} }
_enforceFocusOnElement(element) { _initializeFocusTrap() {
EventHandler__default['default'].off(document, EVENT_FOCUSIN); // guard against infinite focus loop return new FocusTrap({
trapElement: this._element,
EventHandler__default['default'].on(document, EVENT_FOCUSIN, (event) => {
if (
document !== event.target &&
element !== event.target &&
!element.contains(event.target)
) {
element.focus();
}
}); });
element.focus();
} }
_addEventListeners() { _addEventListeners() {
EventHandler__default['default'].on( EventHandler__default.default.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => {
this._element,
EVENT_CLICK_DISMISS,
SELECTOR_DATA_DISMISS,
() => this.hide()
);
EventHandler__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, (event) => {
if (this._config.keyboard && event.key === ESCAPE_KEY) { if (this._config.keyboard && event.key === ESCAPE_KEY) {
this.hide(); this.hide();
} }
@ -644,9 +817,7 @@
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = const data = Offcanvas.getOrCreateInstance(this, config);
Data__default['default'].get(this, DATA_KEY) ||
new Offcanvas(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -666,7 +837,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_CLICK_DATA_API, EVENT_CLICK_DATA_API,
SELECTOR_DATA_TOGGLE, SELECTOR_DATA_TOGGLE,
@ -681,28 +852,29 @@
return; return;
} }
EventHandler__default['default'].one(target, EVENT_HIDDEN, () => { EventHandler__default.default.one(target, EVENT_HIDDEN, () => {
// focus on trigger when it is closed // focus on trigger when it is closed
if (isVisible(this)) { if (isVisible(this)) {
this.focus(); this.focus();
} }
}); // avoid conflict when clicking a toggler of an offcanvas, while another is open }); // avoid conflict when clicking a toggler of an offcanvas, while another is open
const allReadyOpen = SelectorEngine__default['default'].findOne(OPEN_SELECTOR); const allReadyOpen = SelectorEngine__default.default.findOne(OPEN_SELECTOR);
if (allReadyOpen && allReadyOpen !== target) { if (allReadyOpen && allReadyOpen !== target) {
Offcanvas.getInstance(allReadyOpen).hide(); Offcanvas.getInstance(allReadyOpen).hide();
} }
const data = Data__default['default'].get(target, DATA_KEY) || new Offcanvas(target); const data = Offcanvas.getOrCreateInstance(target);
data.toggle(this); data.toggle(this);
} }
); );
EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, () => { EventHandler__default.default.on(window, EVENT_LOAD_DATA_API, () =>
SelectorEngine__default['default'] SelectorEngine__default.default
.find(OPEN_SELECTOR) .find(OPEN_SELECTOR)
.forEach((el) => (Data__default['default'].get(el, DATA_KEY) || new Offcanvas(el)).show()); .forEach((el) => Offcanvas.getOrCreateInstance(el).show())
}); );
enableDismissTrigger(Offcanvas);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

File diff suppressed because one or more lines are too long

View File

@ -1,29 +1,29 @@
/*! /*!
* Bootstrap popover.js v5.0.1 (https://getbootstrap.com/) * Bootstrap popover.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(require('./tooltip.js')))
require('./dom/selector-engine.js'),
require('./dom/data.js'),
require('./tooltip.js')
))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define(['./dom/selector-engine', './dom/data', './tooltip'], factory) ? define(['./tooltip'], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Popover = factory(global.SelectorEngine, global.Data, global.Tooltip))); (global.Popover = factory(global.Tooltip)));
})(this, function (SelectorEngine, Data, Tooltip) { })(this, function (Tooltip) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const Tooltip__default = /*#__PURE__*/ _interopDefaultLegacy(Tooltip);
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data);
var Tooltip__default = /*#__PURE__*/ _interopDefaultLegacy(Tooltip); /**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -35,9 +35,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -64,7 +73,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): popover.js * Bootstrap (v5.1.3): popover.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -78,9 +87,8 @@
const DATA_KEY = 'bs.popover'; const DATA_KEY = 'bs.popover';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const CLASS_PREFIX = 'bs-popover'; const CLASS_PREFIX = 'bs-popover';
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g');
const Default = { const Default = {
...Tooltip__default['default'].Default, ...Tooltip__default.default.Default,
placement: 'right', placement: 'right',
offset: [0, 8], offset: [0, 8],
trigger: 'click', trigger: 'click',
@ -93,7 +101,7 @@
'</div>', '</div>',
}; };
const DefaultType = { const DefaultType = {
...Tooltip__default['default'].DefaultType, ...Tooltip__default.default.DefaultType,
content: '(string|element|function)', content: '(string|element|function)',
}; };
const Event = { const Event = {
@ -108,8 +116,6 @@
MOUSEENTER: `mouseenter${EVENT_KEY}`, MOUSEENTER: `mouseenter${EVENT_KEY}`,
MOUSELEAVE: `mouseleave${EVENT_KEY}`, MOUSELEAVE: `mouseleave${EVENT_KEY}`,
}; };
const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show';
const SELECTOR_TITLE = '.popover-header'; const SELECTOR_TITLE = '.popover-header';
const SELECTOR_CONTENT = '.popover-body'; const SELECTOR_CONTENT = '.popover-body';
/** /**
@ -118,7 +124,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Popover extends Tooltip__default['default'] { class Popover extends Tooltip__default.default {
// Getters // Getters
static get Default() { static get Default() {
return Default; return Default;
@ -140,58 +146,23 @@
return this.getTitle() || this._getContent(); return this.getTitle() || this._getContent();
} }
setContent() { setContent(tip) {
const tip = this.getTipElement(); // we use append for html objects to maintain js events this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TITLE);
this.setElementContent( this._sanitizeAndSetContent(tip, this._getContent(), SELECTOR_CONTENT);
SelectorEngine__default['default'].findOne(SELECTOR_TITLE, tip),
this.getTitle()
);
let content = this._getContent();
if (typeof content === 'function') {
content = content.call(this._element);
}
this.setElementContent(
SelectorEngine__default['default'].findOne(SELECTOR_CONTENT, tip),
content
);
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
} // Private } // Private
_addAttachmentClass(attachment) {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`);
}
_getContent() { _getContent() {
return this._element.getAttribute('data-bs-content') || this._config.content; return this._resolvePossibleFunction(this._config.content);
} }
_cleanTipClass() { _getBasicClassPrefix() {
const tip = this.getTipElement(); return CLASS_PREFIX;
const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX);
if (tabClass !== null && tabClass.length > 0) {
tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass));
}
} // Static } // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data__default['default'].get(this, DATA_KEY); const data = Popover.getOrCreateInstance(this, config);
const _config = typeof config === 'object' ? config : null;
if (!data && /dispose|hide/.test(config)) {
return;
}
if (!data) {
data = new Popover(this, _config);
Data__default['default'].set(this, DATA_KEY, data);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {

File diff suppressed because one or more lines are too long

View File

@ -1,51 +1,46 @@
/*! /*!
* Bootstrap scrollspy.js v5.0.1 (https://getbootstrap.com/) * Bootstrap scrollspy.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('./dom/selector-engine.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./dom/selector-engine.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(
'./dom/selector-engine', ['./dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'],
'./dom/event-handler', factory
'./dom/manipulator', )
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.ScrollSpy = factory( (global.ScrollSpy = factory(
global.SelectorEngine,
global.EventHandler, global.EventHandler,
global.Manipulator, global.Manipulator,
global.SelectorEngine,
global.Base global.Base
))); )));
})(this, function (SelectorEngine, EventHandler, Manipulator, BaseComponent) { })(this, function (EventHandler, Manipulator, SelectorEngine, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/index.js * Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const MAX_UID = 1000000;
const toType = (obj) => { const toType = (obj) => {
if (obj === null || obj === undefined) { if (obj === null || obj === undefined) {
return `${obj}`; return `${obj}`;
@ -56,19 +51,6 @@
.match(/\s([a-z]+)/i)[1] .match(/\s([a-z]+)/i)[1]
.toLowerCase(); .toLowerCase();
}; };
/**
* --------------------------------------------------------------------------
* Public Util Api
* --------------------------------------------------------------------------
*/
const getUID = (prefix) => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getSelector = (element) => { const getSelector = (element) => {
let selector = element.getAttribute('data-bs-target'); let selector = element.getAttribute('data-bs-target');
@ -115,6 +97,19 @@
return typeof obj.nodeType !== 'undefined'; return typeof obj.nodeType !== 'undefined';
}; };
const getElement = (obj) => {
if (isElement(obj)) {
// it's a jQuery object or a node element
return obj.jquery ? obj[0] : obj;
}
if (typeof obj === 'string' && obj.length > 0) {
return document.querySelector(obj);
}
return null;
};
const typeCheckConfig = (componentName, config, configTypes) => { const typeCheckConfig = (componentName, config, configTypes) => {
Object.keys(configTypes).forEach((property) => { Object.keys(configTypes).forEach((property) => {
const expectedTypes = configTypes[property]; const expectedTypes = configTypes[property];
@ -139,9 +134,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -168,7 +172,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): scrollspy.js * Bootstrap (v5.1.3): scrollspy.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -202,6 +206,7 @@
const SELECTOR_NAV_LINKS = '.nav-link'; const SELECTOR_NAV_LINKS = '.nav-link';
const SELECTOR_NAV_ITEMS = '.nav-item'; const SELECTOR_NAV_ITEMS = '.nav-item';
const SELECTOR_LIST_ITEMS = '.list-group-item'; const SELECTOR_LIST_ITEMS = '.list-group-item';
const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}, .${CLASS_NAME_DROPDOWN_ITEM}`;
const SELECTOR_DROPDOWN = '.dropdown'; const SELECTOR_DROPDOWN = '.dropdown';
const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'; const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
const METHOD_OFFSET = 'offset'; const METHOD_OFFSET = 'offset';
@ -212,17 +217,16 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class ScrollSpy extends BaseComponent__default['default'] { class ScrollSpy extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element; this._scrollElement = this._element.tagName === 'BODY' ? window : this._element;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`;
this._offsets = []; this._offsets = [];
this._targets = []; this._targets = [];
this._activeTarget = null; this._activeTarget = null;
this._scrollHeight = 0; this._scrollHeight = 0;
EventHandler__default['default'].on(this._scrollElement, EVENT_SCROLL, () => this._process()); EventHandler__default.default.on(this._scrollElement, EVENT_SCROLL, () => this._process());
this.refresh(); this.refresh();
this._process(); this._process();
@ -244,12 +248,15 @@
this._offsets = []; this._offsets = [];
this._targets = []; this._targets = [];
this._scrollHeight = this._getScrollHeight(); this._scrollHeight = this._getScrollHeight();
const targets = SelectorEngine__default['default'].find(this._selector); const targets = SelectorEngine__default.default.find(
SELECTOR_LINK_ITEMS,
this._config.target
);
targets targets
.map((element) => { .map((element) => {
const targetSelector = getSelectorFromElement(element); const targetSelector = getSelectorFromElement(element);
const target = targetSelector const target = targetSelector
? SelectorEngine__default['default'].findOne(targetSelector) ? SelectorEngine__default.default.findOne(targetSelector)
: null; : null;
if (target) { if (target) {
@ -257,7 +264,7 @@
if (targetBCR.width || targetBCR.height) { if (targetBCR.width || targetBCR.height) {
return [ return [
Manipulator__default['default'][offsetMethod](target).top + offsetBase, Manipulator__default.default[offsetMethod](target).top + offsetBase,
targetSelector, targetSelector,
]; ];
} }
@ -275,28 +282,17 @@
} }
dispose() { dispose() {
EventHandler__default['default'].off(this._scrollElement, EVENT_KEY); EventHandler__default.default.off(this._scrollElement, EVENT_KEY);
super.dispose(); super.dispose();
} // Private } // Private
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator__default['default'].getDataAttributes(this._element), ...Manipulator__default.default.getDataAttributes(this._element),
...(typeof config === 'object' && config ? config : {}), ...(typeof config === 'object' && config ? config : {}),
}; };
config.target = getElement(config.target) || document.documentElement;
if (typeof config.target !== 'string' && isElement(config.target)) {
let { id } = config.target;
if (!id) {
id = getUID(NAME);
config.target.id = id;
}
config.target = `#${id}`;
}
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
} }
@ -366,56 +362,51 @@
this._clear(); this._clear();
const queries = this._selector const queries = SELECTOR_LINK_ITEMS.split(',').map(
.split(',') (selector) => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`
.map((selector) => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`); );
const link = SelectorEngine__default.default.findOne(queries.join(','), this._config.target);
const link = SelectorEngine__default['default'].findOne(queries.join(',')); link.classList.add(CLASS_NAME_ACTIVE);
if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
SelectorEngine__default['default'] SelectorEngine__default.default
.findOne(SELECTOR_DROPDOWN_TOGGLE, link.closest(SELECTOR_DROPDOWN)) .findOne(SELECTOR_DROPDOWN_TOGGLE, link.closest(SELECTOR_DROPDOWN))
.classList.add(CLASS_NAME_ACTIVE); .classList.add(CLASS_NAME_ACTIVE);
link.classList.add(CLASS_NAME_ACTIVE);
} else { } else {
// Set triggered link as active SelectorEngine__default.default
link.classList.add(CLASS_NAME_ACTIVE);
SelectorEngine__default['default']
.parents(link, SELECTOR_NAV_LIST_GROUP) .parents(link, SELECTOR_NAV_LIST_GROUP)
.forEach((listGroup) => { .forEach((listGroup) => {
// Set triggered links parents as active // Set triggered links parents as active
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
SelectorEngine__default['default'] SelectorEngine__default.default
.prev(listGroup, `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`) .prev(listGroup, `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`)
.forEach((item) => item.classList.add(CLASS_NAME_ACTIVE)); // Handle special case when .nav-link is inside .nav-item .forEach((item) => item.classList.add(CLASS_NAME_ACTIVE)); // Handle special case when .nav-link is inside .nav-item
SelectorEngine__default['default'] SelectorEngine__default.default
.prev(listGroup, SELECTOR_NAV_ITEMS) .prev(listGroup, SELECTOR_NAV_ITEMS)
.forEach((navItem) => { .forEach((navItem) => {
SelectorEngine__default['default'] SelectorEngine__default.default
.children(navItem, SELECTOR_NAV_LINKS) .children(navItem, SELECTOR_NAV_LINKS)
.forEach((item) => item.classList.add(CLASS_NAME_ACTIVE)); .forEach((item) => item.classList.add(CLASS_NAME_ACTIVE));
}); });
}); });
} }
EventHandler__default['default'].trigger(this._scrollElement, EVENT_ACTIVATE, { EventHandler__default.default.trigger(this._scrollElement, EVENT_ACTIVATE, {
relatedTarget: target, relatedTarget: target,
}); });
} }
_clear() { _clear() {
SelectorEngine__default['default'] SelectorEngine__default.default
.find(this._selector) .find(SELECTOR_LINK_ITEMS, this._config.target)
.filter((node) => node.classList.contains(CLASS_NAME_ACTIVE)) .filter((node) => node.classList.contains(CLASS_NAME_ACTIVE))
.forEach((node) => node.classList.remove(CLASS_NAME_ACTIVE)); .forEach((node) => node.classList.remove(CLASS_NAME_ACTIVE));
} // Static } // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = const data = ScrollSpy.getOrCreateInstance(this, config);
ScrollSpy.getInstance(this) ||
new ScrollSpy(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -435,8 +426,8 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, () => { EventHandler__default.default.on(window, EVENT_LOAD_DATA_API, () => {
SelectorEngine__default['default'].find(SELECTOR_DATA_SPY).forEach((spy) => new ScrollSpy(spy)); SelectorEngine__default.default.find(SELECTOR_DATA_SPY).forEach((spy) => new ScrollSpy(spy));
}); });
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------

File diff suppressed because one or more lines are too long

View File

@ -1,36 +1,35 @@
/*! /*!
* Bootstrap tab.js v5.0.1 (https://getbootstrap.com/) * Bootstrap tab.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('./dom/selector-engine.js'),
require('./dom/data.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/selector-engine.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(['./dom/event-handler', './dom/selector-engine', './base-component'], factory)
'./dom/selector-engine',
'./dom/data',
'./dom/event-handler',
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Tab = factory(global.SelectorEngine, global.Data, global.EventHandler, global.Base))); (global.Tab = factory(global.EventHandler, global.SelectorEngine, global.Base)));
})(this, function (SelectorEngine, Data, EventHandler, BaseComponent) { })(this, function (EventHandler, SelectorEngine, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const getSelector = (element) => { const getSelector = (element) => {
let selector = element.getAttribute('data-bs-target'); let selector = element.getAttribute('data-bs-target');
@ -75,8 +74,19 @@
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; 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) => element.offsetHeight; const reflow = (element) => {
// eslint-disable-next-line no-unused-expressions
element.offsetHeight;
};
const getjQuery = () => { const getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -88,9 +98,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -117,7 +136,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): tab.js * Bootstrap (v5.1.3): tab.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -154,7 +173,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Tab extends BaseComponent__default['default'] { class Tab extends BaseComponent__default.default {
// Getters // Getters
static get NAME() { static get NAME() {
return NAME; return NAME;
@ -179,16 +198,16 @@
listElement.nodeName === 'UL' || listElement.nodeName === 'OL' listElement.nodeName === 'UL' || listElement.nodeName === 'OL'
? SELECTOR_ACTIVE_UL ? SELECTOR_ACTIVE_UL
: SELECTOR_ACTIVE; : SELECTOR_ACTIVE;
previous = SelectorEngine__default['default'].find(itemSelector, listElement); previous = SelectorEngine__default.default.find(itemSelector, listElement);
previous = previous[previous.length - 1]; previous = previous[previous.length - 1];
} }
const hideEvent = previous const hideEvent = previous
? EventHandler__default['default'].trigger(previous, EVENT_HIDE, { ? EventHandler__default.default.trigger(previous, EVENT_HIDE, {
relatedTarget: this._element, relatedTarget: this._element,
}) })
: null; : null;
const showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW, { const showEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW, {
relatedTarget: previous, relatedTarget: previous,
}); });
@ -199,10 +218,10 @@
this._activate(this._element, listElement); this._activate(this._element, listElement);
const complete = () => { const complete = () => {
EventHandler__default['default'].trigger(previous, EVENT_HIDDEN, { EventHandler__default.default.trigger(previous, EVENT_HIDDEN, {
relatedTarget: this._element, relatedTarget: this._element,
}); });
EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, { EventHandler__default.default.trigger(this._element, EVENT_SHOWN, {
relatedTarget: previous, relatedTarget: previous,
}); });
}; };
@ -217,8 +236,8 @@
_activate(element, container, callback) { _activate(element, container, callback) {
const activeElements = const activeElements =
container && (container.nodeName === 'UL' || container.nodeName === 'OL') container && (container.nodeName === 'UL' || container.nodeName === 'OL')
? SelectorEngine__default['default'].find(SELECTOR_ACTIVE_UL, container) ? SelectorEngine__default.default.find(SELECTOR_ACTIVE_UL, container)
: SelectorEngine__default['default'].children(container, SELECTOR_ACTIVE); : SelectorEngine__default.default.children(container, SELECTOR_ACTIVE);
const active = activeElements[0]; const active = activeElements[0];
const isTransitioning = callback && active && active.classList.contains(CLASS_NAME_FADE); const isTransitioning = callback && active && active.classList.contains(CLASS_NAME_FADE);
@ -236,7 +255,7 @@
_transitionComplete(element, active, callback) { _transitionComplete(element, active, callback) {
if (active) { if (active) {
active.classList.remove(CLASS_NAME_ACTIVE); active.classList.remove(CLASS_NAME_ACTIVE);
const dropdownChild = SelectorEngine__default['default'].findOne( const dropdownChild = SelectorEngine__default.default.findOne(
SELECTOR_DROPDOWN_ACTIVE_CHILD, SELECTOR_DROPDOWN_ACTIVE_CHILD,
active.parentNode active.parentNode
); );
@ -272,7 +291,7 @@
const dropdownElement = element.closest(SELECTOR_DROPDOWN); const dropdownElement = element.closest(SELECTOR_DROPDOWN);
if (dropdownElement) { if (dropdownElement) {
SelectorEngine__default['default'] SelectorEngine__default.default
.find(SELECTOR_DROPDOWN_TOGGLE, dropdownElement) .find(SELECTOR_DROPDOWN_TOGGLE, dropdownElement)
.forEach((dropdown) => dropdown.classList.add(CLASS_NAME_ACTIVE)); .forEach((dropdown) => dropdown.classList.add(CLASS_NAME_ACTIVE));
} }
@ -287,7 +306,7 @@
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = Data__default['default'].get(this, DATA_KEY) || new Tab(this); const data = Tab.getOrCreateInstance(this);
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -305,7 +324,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler__default['default'].on( EventHandler__default.default.on(
document, document,
EVENT_CLICK_DATA_API, EVENT_CLICK_DATA_API,
SELECTOR_DATA_TOGGLE, SELECTOR_DATA_TOGGLE,
@ -318,7 +337,7 @@
return; return;
} }
const data = Data__default['default'].get(this, DATA_KEY) || new Tab(this); const data = Tab.getOrCreateInstance(this);
data.show(); data.show();
} }
); );

File diff suppressed because one or more lines are too long

View File

@ -1,36 +1,35 @@
/*! /*!
* Bootstrap toast.js v5.0.1 (https://getbootstrap.com/) * Bootstrap toast.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('./dom/data.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(['./dom/event-handler', './dom/manipulator', './base-component'], factory)
'./dom/data',
'./dom/event-handler',
'./dom/manipulator',
'./base-component',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Toast = factory(global.Data, global.EventHandler, global.Manipulator, global.Base))); (global.Toast = factory(global.EventHandler, global.Manipulator, global.Base)));
})(this, function (Data, EventHandler, Manipulator, BaseComponent) { })(this, function (EventHandler, Manipulator, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const toType = (obj) => { const toType = (obj) => {
if (obj === null || obj === undefined) { if (obj === null || obj === undefined) {
@ -43,6 +42,34 @@
.toLowerCase(); .toLowerCase();
}; };
const getSelector = (element) => {
let selector = element.getAttribute('data-bs-target');
if (!selector || selector === '#') {
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
if (!hrefAttr || (!hrefAttr.includes('#') && !hrefAttr.startsWith('.'))) {
return null;
} // Just in case some CMS puts out a full URL with the anchor appended
if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
hrefAttr = `#${hrefAttr.split('#')[1]}`;
}
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
}
return selector;
};
const getElementFromSelector = (element) => {
const selector = getSelector(element);
return selector ? document.querySelector(selector) : null;
};
const isElement = (obj) => { const isElement = (obj) => {
if (!obj || typeof obj !== 'object') { if (!obj || typeof obj !== 'object') {
return false; return false;
@ -69,7 +96,34 @@
}); });
}; };
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 getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -81,9 +135,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -110,7 +173,38 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): toast.js * Bootstrap (v5.1.3): 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.3): toast.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -123,7 +217,6 @@
const NAME = 'toast'; const NAME = 'toast';
const DATA_KEY = 'bs.toast'; const DATA_KEY = 'bs.toast';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`; const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;
const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`; const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`; const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
@ -133,7 +226,8 @@
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_HIDE = 'hide'; const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_SHOWING = 'showing'; const CLASS_NAME_SHOWING = 'showing';
const DefaultType = { const DefaultType = {
@ -146,14 +240,13 @@
autohide: true, autohide: true,
delay: 5000, delay: 5000,
}; };
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="toast"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* Class Definition * Class Definition
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Toast extends BaseComponent__default['default'] { class Toast extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
this._config = this._getConfig(config); this._config = this._getConfig(config);
@ -177,7 +270,7 @@
} // Public } // Public
show() { show() {
const showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW); const showEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW);
if (showEvent.defaultPrevented) { if (showEvent.defaultPrevented) {
return; return;
@ -192,17 +285,17 @@
const complete = () => { const complete = () => {
this._element.classList.remove(CLASS_NAME_SHOWING); this._element.classList.remove(CLASS_NAME_SHOWING);
this._element.classList.add(CLASS_NAME_SHOW); EventHandler__default.default.trigger(this._element, EVENT_SHOWN);
EventHandler__default['default'].trigger(this._element, EVENT_SHOWN);
this._maybeScheduleHide(); this._maybeScheduleHide();
}; };
this._element.classList.remove(CLASS_NAME_HIDE); this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated
reflow(this._element); reflow(this._element);
this._element.classList.add(CLASS_NAME_SHOW);
this._element.classList.add(CLASS_NAME_SHOWING); this._element.classList.add(CLASS_NAME_SHOWING);
this._queueCallback(complete, this._element, this._config.animation); this._queueCallback(complete, this._element, this._config.animation);
@ -213,20 +306,24 @@
return; return;
} }
const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); const hideEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE);
if (hideEvent.defaultPrevented) { if (hideEvent.defaultPrevented) {
return; return;
} }
const complete = () => { const complete = () => {
this._element.classList.add(CLASS_NAME_HIDE); this._element.classList.add(CLASS_NAME_HIDE); // @deprecated
EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN); this._element.classList.remove(CLASS_NAME_SHOWING);
};
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_SHOW);
EventHandler__default.default.trigger(this._element, EVENT_HIDDEN);
};
this._element.classList.add(CLASS_NAME_SHOWING);
this._queueCallback(complete, this._element, this._config.animation); this._queueCallback(complete, this._element, this._config.animation);
} }
@ -243,7 +340,7 @@
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator__default['default'].getDataAttributes(this._element), ...Manipulator__default.default.getDataAttributes(this._element),
...(typeof config === 'object' && config ? config : {}), ...(typeof config === 'object' && config ? config : {}),
}; };
typeCheckConfig(NAME, config, this.constructor.DefaultType); typeCheckConfig(NAME, config, this.constructor.DefaultType);
@ -293,22 +390,16 @@
} }
_setListeners() { _setListeners() {
EventHandler__default['default'].on( EventHandler__default.default.on(this._element, EVENT_MOUSEOVER, (event) =>
this._element,
EVENT_CLICK_DISMISS,
SELECTOR_DATA_DISMISS,
() => this.hide()
);
EventHandler__default['default'].on(this._element, EVENT_MOUSEOVER, (event) =>
this._onInteraction(event, true) this._onInteraction(event, true)
); );
EventHandler__default['default'].on(this._element, EVENT_MOUSEOUT, (event) => EventHandler__default.default.on(this._element, EVENT_MOUSEOUT, (event) =>
this._onInteraction(event, false) this._onInteraction(event, false)
); );
EventHandler__default['default'].on(this._element, EVENT_FOCUSIN, (event) => EventHandler__default.default.on(this._element, EVENT_FOCUSIN, (event) =>
this._onInteraction(event, true) this._onInteraction(event, true)
); );
EventHandler__default['default'].on(this._element, EVENT_FOCUSOUT, (event) => EventHandler__default.default.on(this._element, EVENT_FOCUSOUT, (event) =>
this._onInteraction(event, false) this._onInteraction(event, false)
); );
} }
@ -320,13 +411,7 @@
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data__default['default'].get(this, DATA_KEY); const data = Toast.getOrCreateInstance(this, config);
const _config = typeof config === 'object' && config;
if (!data) {
data = new Toast(this, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -338,6 +423,8 @@
}); });
} }
} }
enableDismissTrigger(Toast);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
/*! /*!
* Bootstrap tooltip.js v5.0.1 (https://getbootstrap.com/) * Bootstrap tooltip.js v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/ */
@ -7,44 +7,46 @@
typeof exports === 'object' && typeof module !== 'undefined' typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory( ? (module.exports = factory(
require('@popperjs/core'), require('@popperjs/core'),
require('./dom/selector-engine.js'),
require('./dom/data.js'), require('./dom/data.js'),
require('./dom/event-handler.js'), require('./dom/event-handler.js'),
require('./dom/manipulator.js'), require('./dom/manipulator.js'),
require('./dom/selector-engine.js'),
require('./base-component.js') require('./base-component.js')
)) ))
: typeof define === 'function' && define.amd : typeof define === 'function' && define.amd
? define([ ? define(
[
'@popperjs/core', '@popperjs/core',
'./dom/selector-engine',
'./dom/data', './dom/data',
'./dom/event-handler', './dom/event-handler',
'./dom/manipulator', './dom/manipulator',
'./dom/selector-engine',
'./base-component', './base-component',
], factory) ],
factory
)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.Tooltip = factory( (global.Tooltip = factory(
global.Popper, global.Popper,
global.SelectorEngine,
global.Data, global.Data,
global.EventHandler, global.EventHandler,
global.Manipulator, global.Manipulator,
global.SelectorEngine,
global.Base global.Base
))); )));
})(this, function (Popper, SelectorEngine, Data, EventHandler, Manipulator, BaseComponent) { })(this, function (Popper, Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) {
'use strict'; 'use strict';
function _interopDefaultLegacy(e) { const _interopDefaultLegacy = (e) =>
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
function _interopNamespace(e) { function _interopNamespace(e) {
if (e && e.__esModule) return e; if (e && e.__esModule) return e;
var n = Object.create(null); const n = Object.create(null);
if (e) { if (e) {
Object.keys(e).forEach(function (k) { for (const k in e) {
if (k !== 'default') { if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k); const d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty( Object.defineProperty(
n, n,
k, k,
@ -52,32 +54,29 @@
? d ? d
: { : {
enumerable: true, enumerable: true,
get: function () { get: () => e[k],
return e[k];
},
} }
); );
} }
});
} }
n['default'] = e; }
n.default = e;
return Object.freeze(n); return Object.freeze(n);
} }
var Popper__namespace = /*#__PURE__*/ _interopNamespace(Popper); const Popper__namespace = /*#__PURE__*/ _interopNamespace(Popper);
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine); const Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data);
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data); const EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler); const Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator); const SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
var BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent); const BaseComponent__default = /*#__PURE__*/ _interopDefaultLegacy(BaseComponent);
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/index.js * Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const MAX_UID = 1000000; const MAX_UID = 1000000;
const toType = (obj) => { const toType = (obj) => {
@ -123,7 +122,7 @@
} }
if (typeof obj === 'string' && obj.length > 0) { if (typeof obj === 'string' && obj.length > 0) {
return SelectorEngine__default['default'].findOne(obj); return document.querySelector(obj);
} }
return null; return null;
@ -176,9 +175,18 @@
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -207,11 +215,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/sanitizer.js * Bootstrap (v5.1.3): util/sanitizer.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const uriAttrs = new Set([ const uriAttributes = new Set([
'background', 'background',
'cite', 'cite',
'href', 'href',
@ -225,35 +233,38 @@
/** /**
* A pattern that recognizes a commonly useful subset of URLs that are safe. * A pattern that recognizes a commonly useful subset of URLs that are safe.
* *
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
*/ */
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i; const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i;
/** /**
* A pattern that matches safe data URLs. Only matches image, video and audio types. * A pattern that matches safe data URLs. Only matches image, video and audio types.
* *
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
*/ */
const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; const DATA_URL_PATTERN =
/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;
const allowedAttribute = (attr, allowedAttributeList) => { const allowedAttribute = (attribute, allowedAttributeList) => {
const attrName = attr.nodeName.toLowerCase(); const attributeName = attribute.nodeName.toLowerCase();
if (allowedAttributeList.includes(attrName)) { if (allowedAttributeList.includes(attributeName)) {
if (uriAttrs.has(attrName)) { if (uriAttributes.has(attributeName)) {
return Boolean( return Boolean(
SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue) SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)
); );
} }
return true; return true;
} }
const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp); // Check if a regular expression validates the attribute. const regExp = allowedAttributeList.filter(
(attributeRegex) => attributeRegex instanceof RegExp
); // Check if a regular expression validates the attribute.
for (let i = 0, len = regExp.length; i < len; i++) { for (let i = 0, len = regExp.length; i < len; i++) {
if (regExp[i].test(attrName)) { if (regExp[i].test(attributeName)) {
return true; return true;
} }
} }
@ -305,23 +316,22 @@
const domParser = new window.DOMParser(); const domParser = new window.DOMParser();
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
const allowlistKeys = Object.keys(allowList);
const elements = [].concat(...createdDocument.body.querySelectorAll('*')); const elements = [].concat(...createdDocument.body.querySelectorAll('*'));
for (let i = 0, len = elements.length; i < len; i++) { for (let i = 0, len = elements.length; i < len; i++) {
const el = elements[i]; const element = elements[i];
const elName = el.nodeName.toLowerCase(); const elementName = element.nodeName.toLowerCase();
if (!allowlistKeys.includes(elName)) { if (!Object.keys(allowList).includes(elementName)) {
el.parentNode.removeChild(el); element.remove();
continue; continue;
} }
const attributeList = [].concat(...el.attributes); const attributeList = [].concat(...element.attributes);
const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []); const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);
attributeList.forEach((attr) => { attributeList.forEach((attribute) => {
if (!allowedAttribute(attr, allowedAttributes)) { if (!allowedAttribute(attribute, allowedAttributes)) {
el.removeAttribute(attr.nodeName); element.removeAttribute(attribute.nodeName);
} }
}); });
} }
@ -331,7 +341,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): tooltip.js * Bootstrap (v5.1.3): tooltip.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -345,7 +355,6 @@
const DATA_KEY = 'bs.tooltip'; const DATA_KEY = 'bs.tooltip';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const CLASS_PREFIX = 'bs-tooltip'; const CLASS_PREFIX = 'bs-tooltip';
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g');
const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
const DefaultType = { const DefaultType = {
animation: 'boolean', animation: 'boolean',
@ -414,6 +423,8 @@
const HOVER_STATE_SHOW = 'show'; const HOVER_STATE_SHOW = 'show';
const HOVER_STATE_OUT = 'out'; const HOVER_STATE_OUT = 'out';
const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
const EVENT_MODAL_HIDE = 'hide.bs.modal';
const TRIGGER_HOVER = 'hover'; const TRIGGER_HOVER = 'hover';
const TRIGGER_FOCUS = 'focus'; const TRIGGER_FOCUS = 'focus';
const TRIGGER_CLICK = 'click'; const TRIGGER_CLICK = 'click';
@ -424,7 +435,7 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
class Tooltip extends BaseComponent__default['default'] { class Tooltip extends BaseComponent__default.default {
constructor(element, config) { constructor(element, config) {
if (typeof Popper__namespace === 'undefined') { if (typeof Popper__namespace === 'undefined') {
throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)"); throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");
@ -500,19 +511,17 @@
dispose() { dispose() {
clearTimeout(this._timeout); clearTimeout(this._timeout);
EventHandler__default['default'].off( EventHandler__default.default.off(
this._element.closest(`.${CLASS_NAME_MODAL}`), this._element.closest(SELECTOR_MODAL),
'hide.bs.modal', EVENT_MODAL_HIDE,
this._hideModalHandler this._hideModalHandler
); );
if (this.tip && this.tip.parentNode) { if (this.tip) {
this.tip.parentNode.removeChild(this.tip); this.tip.remove();
} }
if (this._popper) { this._disposePopper();
this._popper.destroy();
}
super.dispose(); super.dispose();
} }
@ -526,7 +535,7 @@
return; return;
} }
const showEvent = EventHandler__default['default'].trigger( const showEvent = EventHandler__default.default.trigger(
this._element, this._element,
this.constructor.Event.SHOW this.constructor.Event.SHOW
); );
@ -538,6 +547,18 @@
if (showEvent.defaultPrevented || !isInTheDom) { if (showEvent.defaultPrevented || !isInTheDom) {
return; return;
} // A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title`
// This will be removed later in favor of a `setContent` method
if (
this.constructor.NAME === 'tooltip' &&
this.tip &&
this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML
) {
this._disposePopper();
this.tip.remove();
this.tip = null;
} }
const tip = this.getTipElement(); const tip = this.getTipElement();
@ -546,8 +567,6 @@
this._element.setAttribute('aria-describedby', tipId); this._element.setAttribute('aria-describedby', tipId);
this.setContent();
if (this._config.animation) { if (this._config.animation) {
tip.classList.add(CLASS_NAME_FADE); tip.classList.add(CLASS_NAME_FADE);
} }
@ -562,11 +581,11 @@
this._addAttachmentClass(attachment); this._addAttachmentClass(attachment);
const { container } = this._config; const { container } = this._config;
Data__default['default'].set(tip, this.constructor.DATA_KEY, this); Data__default.default.set(tip, this.constructor.DATA_KEY, this);
if (!this._element.ownerDocument.documentElement.contains(this.tip)) { if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip); container.append(tip);
EventHandler__default['default'].trigger(this._element, this.constructor.Event.INSERTED); EventHandler__default.default.trigger(this._element, this.constructor.Event.INSERTED);
} }
if (this._popper) { if (this._popper) {
@ -580,10 +599,8 @@
} }
tip.classList.add(CLASS_NAME_SHOW); tip.classList.add(CLASS_NAME_SHOW);
const customClass =
typeof this._config.customClass === 'function' const customClass = this._resolvePossibleFunction(this._config.customClass);
? this._config.customClass()
: this._config.customClass;
if (customClass) { if (customClass) {
tip.classList.add(...customClass.split(' ')); tip.classList.add(...customClass.split(' '));
@ -594,14 +611,14 @@
if ('ontouchstart' in document.documentElement) { if ('ontouchstart' in document.documentElement) {
[].concat(...document.body.children).forEach((element) => { [].concat(...document.body.children).forEach((element) => {
EventHandler__default['default'].on(element, 'mouseover', noop); EventHandler__default.default.on(element, 'mouseover', noop);
}); });
} }
const complete = () => { const complete = () => {
const prevHoverState = this._hoverState; const prevHoverState = this._hoverState;
this._hoverState = null; this._hoverState = null;
EventHandler__default['default'].trigger(this._element, this.constructor.Event.SHOWN); EventHandler__default.default.trigger(this._element, this.constructor.Event.SHOWN);
if (prevHoverState === HOVER_STATE_OUT) { if (prevHoverState === HOVER_STATE_OUT) {
this._leave(null, this); this._leave(null, this);
@ -625,24 +642,20 @@
return; return;
} }
if (this._hoverState !== HOVER_STATE_SHOW && tip.parentNode) { if (this._hoverState !== HOVER_STATE_SHOW) {
tip.parentNode.removeChild(tip); tip.remove();
} }
this._cleanTipClass(); this._cleanTipClass();
this._element.removeAttribute('aria-describedby'); this._element.removeAttribute('aria-describedby');
EventHandler__default['default'].trigger(this._element, this.constructor.Event.HIDDEN); EventHandler__default.default.trigger(this._element, this.constructor.Event.HIDDEN);
if (this._popper) { this._disposePopper();
this._popper.destroy();
this._popper = null;
}
}; };
const hideEvent = EventHandler__default['default'].trigger( const hideEvent = EventHandler__default.default.trigger(
this._element, this._element,
this.constructor.Event.HIDE this.constructor.Event.HIDE
); );
@ -657,7 +670,7 @@
if ('ontouchstart' in document.documentElement) { if ('ontouchstart' in document.documentElement) {
[] []
.concat(...document.body.children) .concat(...document.body.children)
.forEach((element) => EventHandler__default['default'].off(element, 'mouseover', noop)); .forEach((element) => EventHandler__default.default.off(element, 'mouseover', noop));
} }
this._activeTrigger[TRIGGER_CLICK] = false; this._activeTrigger[TRIGGER_CLICK] = false;
@ -687,17 +700,26 @@
const element = document.createElement('div'); const element = document.createElement('div');
element.innerHTML = this._config.template; element.innerHTML = this._config.template;
this.tip = element.children[0]; const tip = element.children[0];
this.setContent(tip);
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
this.tip = tip;
return this.tip; return this.tip;
} }
setContent() { setContent(tip) {
const tip = this.getTipElement(); this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER);
this.setElementContent( }
SelectorEngine__default['default'].findOne(SELECTOR_TOOLTIP_INNER, tip),
this.getTitle() _sanitizeAndSetContent(template, content, selector) {
); const templateElement = SelectorEngine__default.default.findOne(selector, template);
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
if (!content && templateElement) {
templateElement.remove();
return;
} // we use append for html objects to maintain js events
this.setElementContent(templateElement, content);
} }
setElementContent(element, content) { setElementContent(element, content) {
@ -711,7 +733,7 @@
if (this._config.html) { if (this._config.html) {
if (content.parentNode !== element) { if (content.parentNode !== element) {
element.innerHTML = ''; element.innerHTML = '';
element.appendChild(content); element.append(content);
} }
} else { } else {
element.textContent = content.textContent; element.textContent = content.textContent;
@ -732,16 +754,9 @@
} }
getTitle() { getTitle() {
let title = this._element.getAttribute('data-bs-original-title'); const title = this._element.getAttribute('data-bs-original-title') || this._config.title;
if (!title) { return this._resolvePossibleFunction(title);
title =
typeof this._config.title === 'function'
? this._config.title.call(this._element)
: this._config.title;
}
return title;
} }
updateAttachment(attachment) { updateAttachment(attachment) {
@ -757,15 +772,10 @@
} // Private } // Private
_initializeOnDelegatedTarget(event, context) { _initializeOnDelegatedTarget(event, context) {
const dataKey = this.constructor.DATA_KEY; return (
context = context || Data__default['default'].get(event.delegateTarget, dataKey); context ||
this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig())
if (!context) { );
context = new this.constructor(event.delegateTarget, this._getDelegateConfig());
Data__default['default'].set(event.delegateTarget, dataKey, context);
}
return context;
} }
_getOffset() { _getOffset() {
@ -782,6 +792,10 @@
return offset; return offset;
} }
_resolvePossibleFunction(content) {
return typeof content === 'function' ? content.call(this._element) : content;
}
_getPopperConfig(attachment) { _getPopperConfig(attachment) {
const defaultBsPopperConfig = { const defaultBsPopperConfig = {
placement: attachment, placement: attachment,
@ -832,7 +846,9 @@
} }
_addAttachmentClass(attachment) { _addAttachmentClass(attachment) {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`); this.getTipElement().classList.add(
`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`
);
} }
_getAttachment(placement) { _getAttachment(placement) {
@ -844,7 +860,7 @@
triggers.forEach((trigger) => { triggers.forEach((trigger) => {
if (trigger === 'click') { if (trigger === 'click') {
EventHandler__default['default'].on( EventHandler__default.default.on(
this._element, this._element,
this.constructor.Event.CLICK, this.constructor.Event.CLICK,
this._config.selector, this._config.selector,
@ -859,13 +875,10 @@
trigger === TRIGGER_HOVER trigger === TRIGGER_HOVER
? this.constructor.Event.MOUSELEAVE ? this.constructor.Event.MOUSELEAVE
: this.constructor.Event.FOCUSOUT; : this.constructor.Event.FOCUSOUT;
EventHandler__default['default'].on( EventHandler__default.default.on(this._element, eventIn, this._config.selector, (event) =>
this._element, this._enter(event)
eventIn,
this._config.selector,
(event) => this._enter(event)
); );
EventHandler__default['default'].on( EventHandler__default.default.on(
this._element, this._element,
eventOut, eventOut,
this._config.selector, this._config.selector,
@ -880,9 +893,9 @@
} }
}; };
EventHandler__default['default'].on( EventHandler__default.default.on(
this._element.closest(`.${CLASS_NAME_MODAL}`), this._element.closest(SELECTOR_MODAL),
'hide.bs.modal', EVENT_MODAL_HIDE,
this._hideModalHandler this._hideModalHandler
); );
@ -943,9 +956,8 @@
context = this._initializeOnDelegatedTarget(event, context); context = this._initializeOnDelegatedTarget(event, context);
if (event) { if (event) {
context._activeTrigger[ context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] =
event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER context._element.contains(event.relatedTarget);
] = context._element.contains(event.relatedTarget);
} }
if (context._isWithActiveTrigger()) { if (context._isWithActiveTrigger()) {
@ -978,7 +990,7 @@
} }
_getConfig(config) { _getConfig(config) {
const dataAttributes = Manipulator__default['default'].getDataAttributes(this._element); const dataAttributes = Manipulator__default.default.getDataAttributes(this._element);
Object.keys(dataAttributes).forEach((dataAttr) => { Object.keys(dataAttributes).forEach((dataAttr) => {
if (DISALLOWED_ATTRIBUTES.has(dataAttr)) { if (DISALLOWED_ATTRIBUTES.has(dataAttr)) {
delete dataAttributes[dataAttr]; delete dataAttributes[dataAttr];
@ -1018,26 +1030,31 @@
_getDelegateConfig() { _getDelegateConfig() {
const config = {}; const config = {};
if (this._config) {
for (const key in this._config) { for (const key in this._config) {
if (this.constructor.Default[key] !== this._config[key]) { if (this.constructor.Default[key] !== this._config[key]) {
config[key] = this._config[key]; config[key] = this._config[key];
} }
} } // In the future can be replaced with:
} // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
// `Object.fromEntries(keysWithDifferentValues)`
return config; return config;
} }
_cleanTipClass() { _cleanTipClass() {
const tip = this.getTipElement(); const tip = this.getTipElement();
const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX); const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g');
const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex);
if (tabClass !== null && tabClass.length > 0) { if (tabClass !== null && tabClass.length > 0) {
tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass)); tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass));
} }
} }
_getBasicClassPrefix() {
return CLASS_PREFIX;
}
_handlePopperPlacementChange(popperData) { _handlePopperPlacementChange(popperData) {
const { state } = popperData; const { state } = popperData;
@ -1050,21 +1067,19 @@
this._cleanTipClass(); this._cleanTipClass();
this._addAttachmentClass(this._getAttachment(state.placement)); this._addAttachmentClass(this._getAttachment(state.placement));
}
_disposePopper() {
if (this._popper) {
this._popper.destroy();
this._popper = null;
}
} // Static } // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data__default['default'].get(this, DATA_KEY); const data = Tooltip.getOrCreateInstance(this, config);
const _config = typeof config === 'object' && config;
if (!data && /dispose|hide/.test(config)) {
return;
}
if (!data) {
data = new Tooltip(this, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,14 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): alert.js * Bootstrap (v5.1.3): alert.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin, getElementFromSelector } from './util/index'; import { defineJQueryPlugin } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -19,15 +19,9 @@ import BaseComponent from './base-component';
const NAME = 'alert'; const NAME = 'alert';
const DATA_KEY = 'bs.alert'; const DATA_KEY = 'bs.alert';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const DATA_API_KEY = '.data-api';
const SELECTOR_DISMISS = '[data-mdb-dismiss="alert"]';
const EVENT_CLOSE = `close${EVENT_KEY}`; const EVENT_CLOSE = `close${EVENT_KEY}`;
const EVENT_CLOSED = `closed${EVENT_KEY}`; const EVENT_CLOSED = `closed${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const CLASS_NAME_ALERT = 'alert';
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
@ -46,67 +40,43 @@ class Alert extends BaseComponent {
// Public // Public
close(element) { close() {
const rootElement = element ? this._getRootElement(element) : this._element; const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE);
const customEvent = this._triggerCloseEvent(rootElement);
if (customEvent === null || customEvent.defaultPrevented) { if (closeEvent.defaultPrevented) {
return; return;
} }
this._removeElement(rootElement); this._element.classList.remove(CLASS_NAME_SHOW);
const isAnimated = this._element.classList.contains(CLASS_NAME_FADE);
this._queueCallback(() => this._destroyElement(), this._element, isAnimated);
} }
// Private // Private
_destroyElement() {
_getRootElement(element) { this._element.remove();
return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`); EventHandler.trigger(this._element, EVENT_CLOSED);
} this.dispose();
_triggerCloseEvent(element) {
return EventHandler.trigger(element, EVENT_CLOSE);
}
_removeElement(element) {
element.classList.remove(CLASS_NAME_SHOW);
const isAnimated = element.classList.contains(CLASS_NAME_FADE);
this._queueCallback(() => this._destroyElement(element), element, isAnimated);
}
_destroyElement(element) {
if (element.parentNode) {
element.parentNode.removeChild(element);
}
EventHandler.trigger(element, EVENT_CLOSED);
} }
// Static // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Alert.getOrCreateInstance(this);
if (!data) { if (typeof config !== 'string') {
data = new Alert(this); return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
} }
if (config === 'close') {
data[config](this); data[config](this);
}
}); });
} }
static handleDismiss(alertInstance) {
return function (event) {
if (event) {
event.preventDefault();
}
alertInstance.close(this);
};
}
} }
/** /**
@ -115,7 +85,7 @@ class Alert extends BaseComponent {
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert.handleDismiss(new Alert())); enableDismissTrigger(Alert, 'close');
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------

View File

@ -1,17 +1,12 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): base-component.js * Bootstrap (v5.1.3): base-component.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import Data from './dom/data'; import Data from './dom/data';
import { import { executeAfterTransition, getElement } from './util/index';
emulateTransitionEnd,
execute,
getElement,
getTransitionDurationFromElement,
} from './util/index';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
/** /**
@ -20,7 +15,7 @@ import EventHandler from './dom/event-handler';
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
const VERSION = '5.0.1'; const VERSION = '5.1.3';
class BaseComponent { class BaseComponent {
constructor(element) { constructor(element) {
@ -44,21 +39,19 @@ class BaseComponent {
} }
_queueCallback(callback, element, isAnimated = true) { _queueCallback(callback, element, isAnimated = true) {
if (!isAnimated) { executeAfterTransition(callback, element, isAnimated);
execute(callback);
return;
}
const transitionDuration = getTransitionDurationFromElement(element);
EventHandler.one(element, 'transitionend', () => execute(callback));
emulateTransitionEnd(element, transitionDuration);
} }
/** Static */ /** Static */
static getInstance(element) { static getInstance(element) {
return Data.get(element, this.DATA_KEY); return Data.get(getElement(element), this.DATA_KEY);
}
static getOrCreateInstance(element, config = {}) {
return (
this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
);
} }
static get VERSION() { static get VERSION() {

View File

@ -1,12 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): button.js * Bootstrap (v5.1.3): button.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin } from './util/index'; import { defineJQueryPlugin } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
@ -51,11 +50,7 @@ class Button extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Button.getOrCreateInstance(this);
if (!data) {
data = new Button(this);
}
if (config === 'toggle') { if (config === 'toggle') {
data[config](); data[config]();
@ -74,11 +69,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, (event) =>
event.preventDefault(); event.preventDefault();
const button = event.target.closest(SELECTOR_DATA_TOGGLE); const button = event.target.closest(SELECTOR_DATA_TOGGLE);
const data = Button.getOrCreateInstance(button);
let data = Data.get(button, DATA_KEY);
if (!data) {
data = new Button(button);
}
data.toggle(); data.toggle();
}); });

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): carousel.js * Bootstrap (v5.1.3): carousel.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -10,11 +10,11 @@ import {
getElementFromSelector, getElementFromSelector,
isRTL, isRTL,
isVisible, isVisible,
getNextActiveElement,
reflow, reflow,
triggerTransitionEnd, triggerTransitionEnd,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
@ -59,6 +59,11 @@ const ORDER_PREV = 'prev';
const DIRECTION_LEFT = 'left'; const DIRECTION_LEFT = 'left';
const DIRECTION_RIGHT = 'right'; const DIRECTION_RIGHT = 'right';
const KEY_TO_DIRECTION = {
[ARROW_LEFT_KEY]: DIRECTION_RIGHT,
[ARROW_RIGHT_KEY]: DIRECTION_LEFT,
};
const EVENT_SLIDE = `slide${EVENT_KEY}`; const EVENT_SLIDE = `slide${EVENT_KEY}`;
const EVENT_SLID = `slid${EVENT_KEY}`; const EVENT_SLID = `slid${EVENT_KEY}`;
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
@ -135,10 +140,8 @@ class Carousel extends BaseComponent {
// Public // Public
next() { next() {
if (!this._isSliding) {
this._slide(ORDER_NEXT); this._slide(ORDER_NEXT);
} }
}
nextWhenVisible() { nextWhenVisible() {
// Don't call next when the page isn't visible // Don't call next when the page isn't visible
@ -149,10 +152,8 @@ class Carousel extends BaseComponent {
} }
prev() { prev() {
if (!this._isSliding) {
this._slide(ORDER_PREV); this._slide(ORDER_PREV);
} }
}
pause(event) { pause(event) {
if (!event) { if (!event) {
@ -217,7 +218,8 @@ class Carousel extends BaseComponent {
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...config, ...Manipulator.getDataAttributes(this._element),
...(typeof config === 'object' ? config : {}),
}; };
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
@ -257,11 +259,15 @@ class Carousel extends BaseComponent {
} }
_addTouchEventListeners() { _addTouchEventListeners() {
const start = (event) => { const hasPointerPenTouch = (event) => {
if ( return (
this._pointerEvent && this._pointerEvent &&
(event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH) (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
) { );
};
const start = (event) => {
if (hasPointerPenTouch(event)) {
this.touchStartX = event.clientX; this.touchStartX = event.clientX;
} else if (!this._pointerEvent) { } else if (!this._pointerEvent) {
this.touchStartX = event.touches[0].clientX; this.touchStartX = event.touches[0].clientX;
@ -275,10 +281,7 @@ class Carousel extends BaseComponent {
}; };
const end = (event) => { const end = (event) => {
if ( if (hasPointerPenTouch(event)) {
this._pointerEvent &&
(event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
) {
this.touchDeltaX = event.clientX - this.touchStartX; this.touchDeltaX = event.clientX - this.touchStartX;
} }
@ -305,7 +308,7 @@ class Carousel extends BaseComponent {
}; };
SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach((itemImg) => { SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach((itemImg) => {
EventHandler.on(itemImg, EVENT_DRAG_START, (e) => e.preventDefault()); EventHandler.on(itemImg, EVENT_DRAG_START, (event) => event.preventDefault());
}); });
if (this._pointerEvent) { if (this._pointerEvent) {
@ -325,12 +328,10 @@ class Carousel extends BaseComponent {
return; return;
} }
if (event.key === ARROW_LEFT_KEY) { const direction = KEY_TO_DIRECTION[event.key];
if (direction) {
event.preventDefault(); event.preventDefault();
this._slide(DIRECTION_RIGHT); this._slide(direction);
} else if (event.key === ARROW_RIGHT_KEY) {
event.preventDefault();
this._slide(DIRECTION_LEFT);
} }
} }
@ -343,20 +344,7 @@ class Carousel extends BaseComponent {
_getItemByOrder(order, activeElement) { _getItemByOrder(order, activeElement) {
const isNext = order === ORDER_NEXT; const isNext = order === ORDER_NEXT;
const isPrev = order === ORDER_PREV; return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);
const activeIndex = this._getItemIndex(activeElement);
const lastItemIndex = this._items.length - 1;
const isGoingToWrap =
(isPrev && activeIndex === 0) || (isNext && activeIndex === lastItemIndex);
if (isGoingToWrap && !this._config.wrap) {
return activeElement;
}
const delta = isPrev ? -1 : 1;
const itemIndex = (activeIndex + delta) % this._items.length;
return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
} }
_triggerSlideEvent(relatedTarget, eventDirectionName) { _triggerSlideEvent(relatedTarget, eventDirectionName) {
@ -432,6 +420,10 @@ class Carousel extends BaseComponent {
return; return;
} }
if (this._isSliding) {
return;
}
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
if (slideEvent.defaultPrevented) { if (slideEvent.defaultPrevented) {
return; return;
@ -520,12 +512,9 @@ class Carousel extends BaseComponent {
// Static // Static
static carouselInterface(element, config) { static carouselInterface(element, config) {
let data = Data.get(element, DATA_KEY); const data = Carousel.getOrCreateInstance(element, config);
let _config = {
...Default,
...Manipulator.getDataAttributes(element),
};
let { _config } = data;
if (typeof config === 'object') { if (typeof config === 'object') {
_config = { _config = {
..._config, ..._config,
@ -535,10 +524,6 @@ class Carousel extends BaseComponent {
const action = typeof config === 'string' ? config : _config.slide; const action = typeof config === 'string' ? config : _config.slide;
if (!data) {
data = new Carousel(element, _config);
}
if (typeof config === 'number') { if (typeof config === 'number') {
data.to(config); data.to(config);
} else if (typeof action === 'string') { } else if (typeof action === 'string') {
@ -579,7 +564,7 @@ class Carousel extends BaseComponent {
Carousel.carouselInterface(target, config); Carousel.carouselInterface(target, config);
if (slideIndex) { if (slideIndex) {
Data.get(target, DATA_KEY).to(slideIndex); Carousel.getInstance(target).to(slideIndex);
} }
event.preventDefault(); event.preventDefault();
@ -598,7 +583,7 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE); const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);
for (let i = 0, len = carousels.length; i < len; i++) { for (let i = 0, len = carousels.length; i < len; i++) {
Carousel.carouselInterface(carousels[i], Data.get(carousels[i], DATA_KEY)); Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));
} }
}); });

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): collapse.js * Bootstrap (v5.1.3): collapse.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -32,12 +32,12 @@ const DATA_API_KEY = '.data-api';
const Default = { const Default = {
toggle: true, toggle: true,
parent: '', parent: null,
}; };
const DefaultType = { const DefaultType = {
toggle: 'boolean', toggle: 'boolean',
parent: '(string|element)', parent: '(null|element)',
}; };
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
@ -50,11 +50,13 @@ const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_COLLAPSE = 'collapse'; const CLASS_NAME_COLLAPSE = 'collapse';
const CLASS_NAME_COLLAPSING = 'collapsing'; const CLASS_NAME_COLLAPSING = 'collapsing';
const CLASS_NAME_COLLAPSED = 'collapsed'; const CLASS_NAME_COLLAPSED = 'collapsed';
const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;
const CLASS_NAME_HORIZONTAL = 'collapse-horizontal';
const WIDTH = 'width'; const WIDTH = 'width';
const HEIGHT = 'height'; const HEIGHT = 'height';
const SELECTOR_ACTIVES = '.show, .collapsing'; const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';
const SELECTOR_DATA_TOGGLE = '[data-mdb-toggle="collapse"]'; const SELECTOR_DATA_TOGGLE = '[data-mdb-toggle="collapse"]';
/** /**
@ -69,10 +71,7 @@ class Collapse extends BaseComponent {
this._isTransitioning = false; this._isTransitioning = false;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._triggerArray = SelectorEngine.find( this._triggerArray = [];
`${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` +
`${SELECTOR_DATA_TOGGLE}[data-mdb-target="#${this._element.id}"]`
);
const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE); const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE);
@ -89,10 +88,10 @@ class Collapse extends BaseComponent {
} }
} }
this._parent = this._config.parent ? this._getParent() : null; this._initializeChildren();
if (!this._config.parent) { if (!this._config.parent) {
this._addAriaAndCollapsedClass(this._element, this._triggerArray); this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());
} }
if (this._config.toggle) { if (this._config.toggle) {
@ -113,7 +112,7 @@ class Collapse extends BaseComponent {
// Public // Public
toggle() { toggle() {
if (this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isShown()) {
this.hide(); this.hide();
} else { } else {
this.show(); this.show();
@ -121,31 +120,24 @@ class Collapse extends BaseComponent {
} }
show() { show() {
if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isTransitioning || this._isShown()) {
return; return;
} }
let actives; let actives = [];
let activesData; let activesData;
if (this._parent) { if (this._config.parent) {
actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent).filter((elem) => { const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);
if (typeof this._config.parent === 'string') { actives = SelectorEngine.find(SELECTOR_ACTIVES, this._config.parent).filter(
return elem.getAttribute('data-mdb-parent') === this._config.parent; (elem) => !children.includes(elem)
} ); // remove children if greater depth
return elem.classList.contains(CLASS_NAME_COLLAPSE);
});
if (actives.length === 0) {
actives = null;
}
} }
const container = SelectorEngine.findOne(this._selector); const container = SelectorEngine.findOne(this._selector);
if (actives) { if (actives.length) {
const tempActiveData = actives.find((elem) => container !== elem); const tempActiveData = actives.find((elem) => container !== elem);
activesData = tempActiveData ? Data.get(tempActiveData, DATA_KEY) : null; activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null;
if (activesData && activesData._isTransitioning) { if (activesData && activesData._isTransitioning) {
return; return;
@ -157,17 +149,15 @@ class Collapse extends BaseComponent {
return; return;
} }
if (actives) {
actives.forEach((elemActive) => { actives.forEach((elemActive) => {
if (container !== elemActive) { if (container !== elemActive) {
Collapse.collapseInterface(elemActive, 'hide'); Collapse.getOrCreateInstance(elemActive, { toggle: false }).hide();
} }
if (!activesData) { if (!activesData) {
Data.set(elemActive, DATA_KEY, null); Data.set(elemActive, DATA_KEY, null);
} }
}); });
}
const dimension = this._getDimension(); const dimension = this._getDimension();
@ -176,22 +166,17 @@ class Collapse extends BaseComponent {
this._element.style[dimension] = 0; this._element.style[dimension] = 0;
if (this._triggerArray.length) { this._addAriaAndCollapsedClass(this._triggerArray, true);
this._triggerArray.forEach((element) => { this._isTransitioning = true;
element.classList.remove(CLASS_NAME_COLLAPSED);
element.setAttribute('aria-expanded', true);
});
}
this.setTransitioning(true);
const complete = () => { const complete = () => {
this._isTransitioning = false;
this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSING);
this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);
this._element.style[dimension] = ''; this._element.style[dimension] = '';
this.setTransitioning(false);
EventHandler.trigger(this._element, EVENT_SHOWN); EventHandler.trigger(this._element, EVENT_SHOWN);
}; };
@ -203,7 +188,7 @@ class Collapse extends BaseComponent {
} }
hide() { hide() {
if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isTransitioning || !this._isShown()) {
return; return;
} }
@ -222,22 +207,19 @@ class Collapse extends BaseComponent {
this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);
const triggerArrayLength = this._triggerArray.length; const triggerArrayLength = this._triggerArray.length;
if (triggerArrayLength > 0) {
for (let i = 0; i < triggerArrayLength; i++) { for (let i = 0; i < triggerArrayLength; i++) {
const trigger = this._triggerArray[i]; const trigger = this._triggerArray[i];
const elem = getElementFromSelector(trigger); const elem = getElementFromSelector(trigger);
if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { if (elem && !this._isShown(elem)) {
trigger.classList.add(CLASS_NAME_COLLAPSED); this._addAriaAndCollapsedClass([trigger], false);
trigger.setAttribute('aria-expanded', false);
}
} }
} }
this.setTransitioning(true); this._isTransitioning = true;
const complete = () => { const complete = () => {
this.setTransitioning(false); this._isTransitioning = false;
this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSING);
this._element.classList.add(CLASS_NAME_COLLAPSE); this._element.classList.add(CLASS_NAME_COLLAPSE);
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
@ -248,8 +230,8 @@ class Collapse extends BaseComponent {
this._queueCallback(complete, this._element, true); this._queueCallback(complete, this._element, true);
} }
setTransitioning(isTransitioning) { _isShown(element = this._element) {
this._isTransitioning = isTransitioning; return element.classList.contains(CLASS_NAME_SHOW);
} }
// Private // Private
@ -257,39 +239,40 @@ class Collapse extends BaseComponent {
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator.getDataAttributes(this._element),
...config, ...config,
}; };
config.toggle = Boolean(config.toggle); // Coerce string values config.toggle = Boolean(config.toggle); // Coerce string values
config.parent = getElement(config.parent);
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
} }
_getDimension() { _getDimension() {
return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT; return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;
} }
_getParent() { _initializeChildren() {
let { parent } = this._config; if (!this._config.parent) {
parent = getElement(parent);
const selector = `${SELECTOR_DATA_TOGGLE}[data-mdb-parent="${parent}"]`;
SelectorEngine.find(selector, parent).forEach((element) => {
const selected = getElementFromSelector(element);
this._addAriaAndCollapsedClass(selected, [element]);
});
return parent;
}
_addAriaAndCollapsedClass(element, triggerArray) {
if (!element || !triggerArray.length) {
return; return;
} }
const isOpen = element.classList.contains(CLASS_NAME_SHOW); const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);
SelectorEngine.find(SELECTOR_DATA_TOGGLE, this._config.parent)
.filter((elem) => !children.includes(elem))
.forEach((element) => {
const selected = getElementFromSelector(element);
if (selected) {
this._addAriaAndCollapsedClass([element], this._isShown(selected));
}
});
}
_addAriaAndCollapsedClass(triggerArray, isOpen) {
if (!triggerArray.length) {
return;
}
triggerArray.forEach((elem) => { triggerArray.forEach((elem) => {
if (isOpen) { if (isOpen) {
@ -304,21 +287,14 @@ class Collapse extends BaseComponent {
// Static // Static
static collapseInterface(element, config) { static jQueryInterface(config) {
let data = Data.get(element, DATA_KEY); return this.each(function () {
const _config = { const _config = {};
...Default, if (typeof config === 'string' && /show|hide/.test(config)) {
...Manipulator.getDataAttributes(element),
...(typeof config === 'object' && config ? config : {}),
};
if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false; _config.toggle = false;
} }
if (!data) { const data = Collapse.getOrCreateInstance(this, _config);
data = new Collapse(element, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -327,11 +303,6 @@ class Collapse extends BaseComponent {
data[config](); data[config]();
} }
}
static jQueryInterface(config) {
return this.each(function () {
Collapse.collapseInterface(this, config);
}); });
} }
} }
@ -351,26 +322,11 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
event.preventDefault(); event.preventDefault();
} }
const triggerData = Manipulator.getDataAttributes(this);
const selector = getSelectorFromElement(this); const selector = getSelectorFromElement(this);
const selectorElements = SelectorEngine.find(selector); const selectorElements = SelectorEngine.find(selector);
selectorElements.forEach((element) => { selectorElements.forEach((element) => {
const data = Data.get(element, DATA_KEY); Collapse.getOrCreateInstance(element, { toggle: false }).toggle();
let config;
if (data) {
// update parent attribute
if (data._parent === null && typeof triggerData.parent === 'string') {
data._config.parent = triggerData.parent;
data._parent = data._getParent();
}
config = 'toggle';
} else {
config = triggerData;
}
Collapse.collapseInterface(element, config);
}); });
}); });

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/data.js * Bootstrap (v5.1.3): dom/data.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/event-handler.js * Bootstrap (v5.1.3): dom/event-handler.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -113,7 +113,6 @@ function bootstrapDelegationHandler(element, selector, fn) {
event.delegateTarget = target; event.delegateTarget = target;
if (handler.oneOff) { if (handler.oneOff) {
// eslint-disable-next-line unicorn/consistent-destructuring
EventHandler.off(element, event.type, selector, fn); EventHandler.off(element, event.type, selector, fn);
} }

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/manipulator.js * Bootstrap (v5.1.3): dom/manipulator.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -64,8 +64,8 @@ const Manipulator = {
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
return { return {
top: rect.top + document.body.scrollTop, top: rect.top + window.pageYOffset,
left: rect.left + document.body.scrollLeft, left: rect.left + window.pageXOffset,
}; };
}, },

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/selector-engine.js * Bootstrap (v5.1.3): dom/selector-engine.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -11,6 +11,8 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
import { isDisabled, isVisible } from '../util/index';
const NODE_TEXT = 3; const NODE_TEXT = 3;
const SelectorEngine = { const SelectorEngine = {
@ -69,6 +71,23 @@ const SelectorEngine = {
return []; return [];
}, },
focusableChildren(element) {
const focusables = [
'a',
'button',
'input',
'textarea',
'select',
'details',
'[tabindex]',
'[contenteditable="true"]',
]
.map((selector) => `${selector}:not([tabindex^="-"])`)
.join(', ');
return this.find(focusables, element).filter((el) => !isDisabled(el) && isVisible(el));
},
}; };
export default SelectorEngine; export default SelectorEngine;

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dropdown.js * Bootstrap (v5.1.3): dropdown.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -11,14 +11,14 @@ import {
defineJQueryPlugin, defineJQueryPlugin,
getElement, getElement,
getElementFromSelector, getElementFromSelector,
getNextActiveElement,
isDisabled, isDisabled,
isElement, isElement,
isVisible,
isRTL, isRTL,
isVisible,
noop, noop,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
@ -48,7 +48,6 @@ const EVENT_HIDE = `hide${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_CLICK = `click${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`;
@ -103,8 +102,6 @@ class Dropdown extends BaseComponent {
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._menu = this._getMenuElement(); this._menu = this._getMenuElement();
this._inNavbar = this._detectNavbar(); this._inNavbar = this._detectNavbar();
this._addEventListeners();
} }
// Getters // Getters
@ -124,26 +121,14 @@ class Dropdown extends BaseComponent {
// Public // Public
toggle() { toggle() {
if (isDisabled(this._element)) { return this._isShown() ? this.hide() : this.show();
return;
}
const isActive = this._element.classList.contains(CLASS_NAME_SHOW);
if (isActive) {
this.hide();
return;
}
this.show();
} }
show() { show() {
if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW)) { if (isDisabled(this._element) || this._isShown(this._menu)) {
return; return;
} }
const parent = Dropdown.getParentFromElement(this._element);
const relatedTarget = { const relatedTarget = {
relatedTarget: this._element, relatedTarget: this._element,
}; };
@ -154,34 +139,12 @@ class Dropdown extends BaseComponent {
return; return;
} }
const parent = Dropdown.getParentFromElement(this._element);
// Totally disable Popper for Dropdowns in Navbar // Totally disable Popper for Dropdowns in Navbar
if (this._inNavbar) { if (this._inNavbar) {
Manipulator.setDataAttribute(this._menu, 'popper', 'none'); Manipulator.setDataAttribute(this._menu, 'popper', 'none');
} else { } else {
if (typeof Popper === 'undefined') { this._createPopper(parent);
throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");
}
let referenceElement = this._element;
if (this._config.reference === 'parent') {
referenceElement = parent;
} else if (isElement(this._config.reference)) {
referenceElement = getElement(this._config.reference);
} else if (typeof this._config.reference === 'object') {
referenceElement = this._config.reference;
}
const popperConfig = this._getPopperConfig();
const isDisplayStatic = popperConfig.modifiers.find(
(modifier) => modifier.name === 'applyStyles' && modifier.enabled === false
);
this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig);
if (isDisplayStatic) {
Manipulator.setDataAttribute(this._menu, 'popper', 'static');
}
} }
// If this is a touch-enabled device we add extra // If this is a touch-enabled device we add extra
@ -197,13 +160,13 @@ class Dropdown extends BaseComponent {
this._element.focus(); this._element.focus();
this._element.setAttribute('aria-expanded', true); this._element.setAttribute('aria-expanded', true);
this._menu.classList.toggle(CLASS_NAME_SHOW); this._menu.classList.add(CLASS_NAME_SHOW);
this._element.classList.toggle(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget); EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget);
} }
hide() { hide() {
if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW)) { if (isDisabled(this._element) || !this._isShown(this._menu)) {
return; return;
} }
@ -231,13 +194,6 @@ class Dropdown extends BaseComponent {
// Private // Private
_addEventListeners() {
EventHandler.on(this._element, EVENT_CLICK, (event) => {
event.preventDefault();
this.toggle();
});
}
_completeHide(relatedTarget) { _completeHide(relatedTarget) {
const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget); const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget);
if (hideEvent.defaultPrevented) { if (hideEvent.defaultPrevented) {
@ -286,6 +242,37 @@ class Dropdown extends BaseComponent {
return config; return config;
} }
_createPopper(parent) {
if (typeof Popper === 'undefined') {
throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");
}
let referenceElement = this._element;
if (this._config.reference === 'parent') {
referenceElement = parent;
} else if (isElement(this._config.reference)) {
referenceElement = getElement(this._config.reference);
} else if (typeof this._config.reference === 'object') {
referenceElement = this._config.reference;
}
const popperConfig = this._getPopperConfig();
const isDisplayStatic = popperConfig.modifiers.find(
(modifier) => modifier.name === 'applyStyles' && modifier.enabled === false
);
this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig);
if (isDisplayStatic) {
Manipulator.setDataAttribute(this._menu, 'popper', 'static');
}
}
_isShown(element = this._element) {
return element.classList.contains(CLASS_NAME_SHOW);
}
_getMenuElement() { _getMenuElement() {
return SelectorEngine.next(this._element, SELECTOR_MENU)[0]; return SelectorEngine.next(this._element, SELECTOR_MENU)[0];
} }
@ -366,53 +353,33 @@ class Dropdown extends BaseComponent {
}; };
} }
_selectMenuItem(event) { _selectMenuItem({ key, target }) {
const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible); const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible);
if (!items.length) { if (!items.length) {
return; return;
} }
let index = items.indexOf(event.target); // if target isn't included in items (e.g. when expanding the dropdown)
// allow cycling to get the last item in case key equals ARROW_UP_KEY
// Up getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
if (event.key === ARROW_UP_KEY && index > 0) {
index--;
}
// Down
if (event.key === ARROW_DOWN_KEY && index < items.length - 1) {
index++;
}
// index is -1 if the first keydown is an ArrowUp
index = index === -1 ? 0 : index;
items[index].focus();
} }
// Static // Static
static dropdownInterface(element, config) { static jQueryInterface(config) {
let data = Data.get(element, DATA_KEY); return this.each(function () {
const _config = typeof config === 'object' ? config : null; const data = Dropdown.getOrCreateInstance(this, config);
if (!data) { if (typeof config !== 'string') {
data = new Dropdown(element, _config); return;
} }
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`); throw new TypeError(`No method named "${config}"`);
} }
data[config](); data[config]();
}
}
static jQueryInterface(config) {
return this.each(function () {
Dropdown.dropdownInterface(this, config);
}); });
} }
@ -427,12 +394,12 @@ class Dropdown extends BaseComponent {
const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE); const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE);
for (let i = 0, len = toggles.length; i < len; i++) { for (let i = 0, len = toggles.length; i < len; i++) {
const context = Data.get(toggles[i], DATA_KEY); const context = Dropdown.getInstance(toggles[i]);
if (!context || context._config.autoClose === false) { if (!context || context._config.autoClose === false) {
continue; continue;
} }
if (!context._element.classList.contains(CLASS_NAME_SHOW)) { if (!context._isShown()) {
continue; continue;
} }
@ -505,28 +472,28 @@ class Dropdown extends BaseComponent {
return; return;
} }
const getToggleButton = () => const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE)
this.matches(SELECTOR_DATA_TOGGLE)
? this ? this
: SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0]; : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0];
const instance = Dropdown.getOrCreateInstance(getToggleButton);
if (event.key === ESCAPE_KEY) { if (event.key === ESCAPE_KEY) {
getToggleButton().focus(); instance.hide();
Dropdown.clearMenus();
return; return;
} }
if (!isActive && (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY)) { if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {
getToggleButton().click(); if (!isActive) {
instance.show();
}
instance._selectMenuItem(event);
return; return;
} }
if (!isActive || event.key === SPACE_KEY) { if (!isActive || event.key === SPACE_KEY) {
Dropdown.clearMenus(); Dropdown.clearMenus();
return;
} }
Dropdown.getInstance(getToggleButton())._selectMenuItem(event);
} }
} }
@ -547,7 +514,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus);
EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
event.preventDefault(); event.preventDefault();
Dropdown.dropdownInterface(this); Dropdown.getOrCreateInstance(this).toggle();
}); });
/** /**

View File

@ -1,15 +1,13 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): modal.js * Bootstrap (v5.1.3): modal.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { import {
defineJQueryPlugin, defineJQueryPlugin,
emulateTransitionEnd,
getElementFromSelector, getElementFromSelector,
getTransitionDurationFromElement,
isRTL, isRTL,
isVisible, isVisible,
reflow, reflow,
@ -18,13 +16,11 @@ import {
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
import { import ScrollBarHelper from './util/scrollbar';
getWidth as getScrollBarWidth,
hide as scrollBarHide,
reset as scrollBarReset,
} from './util/scrollbar';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import Backdrop from './util/backdrop'; import Backdrop from './util/backdrop';
import FocusTrap from './util/focustrap';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -55,7 +51,6 @@ const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_RESIZE = `resize${EVENT_KEY}`; const EVENT_RESIZE = `resize${EVENT_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`; const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
@ -68,10 +63,10 @@ const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_STATIC = 'modal-static'; const CLASS_NAME_STATIC = 'modal-static';
const OPEN_SELECTOR = '.modal.show';
const SELECTOR_DIALOG = '.modal-dialog'; const SELECTOR_DIALOG = '.modal-dialog';
const SELECTOR_MODAL_BODY = '.modal-body'; const SELECTOR_MODAL_BODY = '.modal-body';
const SELECTOR_DATA_TOGGLE = '[data-mdb-toggle="modal"]'; const SELECTOR_DATA_TOGGLE = '[data-mdb-toggle="modal"]';
const SELECTOR_DATA_DISMISS = '[data-mdb-dismiss="modal"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -86,9 +81,11 @@ class Modal extends BaseComponent {
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element);
this._backdrop = this._initializeBackDrop(); this._backdrop = this._initializeBackDrop();
this._focustrap = this._initializeFocusTrap();
this._isShown = false; this._isShown = false;
this._ignoreBackdropClick = false; this._ignoreBackdropClick = false;
this._isTransitioning = false; this._isTransitioning = false;
this._scrollBar = new ScrollBarHelper();
} }
// Getters // Getters
@ -112,21 +109,21 @@ class Modal extends BaseComponent {
return; return;
} }
if (this._isAnimated()) {
this._isTransitioning = true;
}
const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, {
relatedTarget, relatedTarget,
}); });
if (this._isShown || showEvent.defaultPrevented) { if (showEvent.defaultPrevented) {
return; return;
} }
this._isShown = true; this._isShown = true;
scrollBarHide(); if (this._isAnimated()) {
this._isTransitioning = true;
}
this._scrollBar.hide();
document.body.classList.add(CLASS_NAME_OPEN); document.body.classList.add(CLASS_NAME_OPEN);
@ -135,10 +132,6 @@ class Modal extends BaseComponent {
this._setEscapeEvent(); this._setEscapeEvent();
this._setResizeEvent(); this._setResizeEvent();
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, (event) =>
this.hide(event)
);
EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => {
EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, (event) => { EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, (event) => {
if (event.target === this._element) { if (event.target === this._element) {
@ -150,11 +143,7 @@ class Modal extends BaseComponent {
this._showBackdrop(() => this._showElement(relatedTarget)); this._showBackdrop(() => this._showElement(relatedTarget));
} }
hide(event) { hide() {
if (event) {
event.preventDefault();
}
if (!this._isShown || this._isTransitioning) { if (!this._isShown || this._isTransitioning) {
return; return;
} }
@ -175,7 +164,7 @@ class Modal extends BaseComponent {
this._setEscapeEvent(); this._setEscapeEvent();
this._setResizeEvent(); this._setResizeEvent();
EventHandler.off(document, EVENT_FOCUSIN); this._focustrap.deactivate();
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_SHOW);
@ -189,14 +178,8 @@ class Modal extends BaseComponent {
[window, this._dialog].forEach((htmlElement) => EventHandler.off(htmlElement, EVENT_KEY)); [window, this._dialog].forEach((htmlElement) => EventHandler.off(htmlElement, EVENT_KEY));
this._backdrop.dispose(); this._backdrop.dispose();
this._focustrap.deactivate();
super.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
*/
EventHandler.off(document, EVENT_FOCUSIN);
} }
handleUpdate() { handleUpdate() {
@ -212,11 +195,17 @@ class Modal extends BaseComponent {
}); });
} }
_initializeFocusTrap() {
return new FocusTrap({
trapElement: this._element,
});
}
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator.getDataAttributes(this._element), ...Manipulator.getDataAttributes(this._element),
...config, ...(typeof config === 'object' ? config : {}),
}; };
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
@ -228,7 +217,7 @@ class Modal extends BaseComponent {
if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
// Don't move modal's DOM position // Don't move modal's DOM position
document.body.appendChild(this._element); document.body.append(this._element);
} }
this._element.style.display = 'block'; this._element.style.display = 'block';
@ -247,13 +236,9 @@ class Modal extends BaseComponent {
this._element.classList.add(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
if (this._config.focus) {
this._enforceFocus();
}
const transitionComplete = () => { const transitionComplete = () => {
if (this._config.focus) { if (this._config.focus) {
this._element.focus(); this._focustrap.activate();
} }
this._isTransitioning = false; this._isTransitioning = false;
@ -265,19 +250,6 @@ class Modal extends BaseComponent {
this._queueCallback(transitionComplete, this._dialog, isAnimated); 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() { _setEscapeEvent() {
if (this._isShown) { if (this._isShown) {
EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => {
@ -310,7 +282,7 @@ class Modal extends BaseComponent {
this._backdrop.hide(() => { this._backdrop.hide(() => {
document.body.classList.remove(CLASS_NAME_OPEN); document.body.classList.remove(CLASS_NAME_OPEN);
this._resetAdjustments(); this._resetAdjustments();
scrollBarReset(); this._scrollBar.reset();
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
}); });
} }
@ -346,25 +318,31 @@ class Modal extends BaseComponent {
return; return;
} }
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const { classList, scrollHeight, style } = this._element;
const isModalOverflowing = scrollHeight > document.documentElement.clientHeight;
if (!isModalOverflowing) { // return if the following background transition hasn't yet completed
this._element.style.overflowY = 'hidden'; if (
(!isModalOverflowing && style.overflowY === 'hidden') ||
classList.contains(CLASS_NAME_STATIC)
) {
return;
} }
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);
if (!isModalOverflowing) { if (!isModalOverflowing) {
EventHandler.one(this._element, 'transitionend', () => { style.overflowY = 'hidden';
this._element.style.overflowY = '';
});
emulateTransitionEnd(this._element, modalTransitionDuration);
} }
});
emulateTransitionEnd(this._element, modalTransitionDuration); classList.add(CLASS_NAME_STATIC);
this._queueCallback(() => {
classList.remove(CLASS_NAME_STATIC);
if (!isModalOverflowing) {
this._queueCallback(() => {
style.overflowY = '';
}, this._dialog);
}
}, this._dialog);
this._element.focus(); this._element.focus();
} }
@ -374,7 +352,7 @@ class Modal extends BaseComponent {
_adjustDialog() { _adjustDialog() {
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
const scrollbarWidth = getScrollBarWidth(); const scrollbarWidth = this._scrollBar.getWidth();
const isBodyOverflowing = scrollbarWidth > 0; const isBodyOverflowing = scrollbarWidth > 0;
if ( if (
@ -401,8 +379,7 @@ class Modal extends BaseComponent {
static jQueryInterface(config, relatedTarget) { static jQueryInterface(config, relatedTarget) {
return this.each(function () { return this.each(function () {
const data = const data = Modal.getOrCreateInstance(this, config);
Modal.getInstance(this) || new Modal(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -443,11 +420,19 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
}); });
}); });
const data = Modal.getInstance(target) || new Modal(target); // 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); data.toggle(this);
}); });
enableDismissTrigger(Modal);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

View File

@ -1,7 +1,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): offcanvas.js * Bootstrap (v5.1.3): offcanvas.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -12,13 +12,14 @@ import {
isVisible, isVisible,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import { hide as scrollBarHide, reset as scrollBarReset } from './util/scrollbar'; import ScrollBarHelper from './util/scrollbar';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import Backdrop from './util/backdrop'; import Backdrop from './util/backdrop';
import FocusTrap from './util/focustrap';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -46,18 +47,16 @@ const DefaultType = {
}; };
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
const OPEN_SELECTOR = '.offcanvas.show'; const OPEN_SELECTOR = '.offcanvas.show';
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_HIDE = `hide${EVENT_KEY}`; const EVENT_HIDE = `hide${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
const SELECTOR_DATA_DISMISS = '[data-mdb-dismiss="offcanvas"]';
const SELECTOR_DATA_TOGGLE = '[data-mdb-toggle="offcanvas"]'; const SELECTOR_DATA_TOGGLE = '[data-mdb-toggle="offcanvas"]';
/** /**
@ -73,6 +72,7 @@ class Offcanvas extends BaseComponent {
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._isShown = false; this._isShown = false;
this._backdrop = this._initializeBackDrop(); this._backdrop = this._initializeBackDrop();
this._focustrap = this._initializeFocusTrap();
this._addEventListeners(); this._addEventListeners();
} }
@ -109,8 +109,7 @@ class Offcanvas extends BaseComponent {
this._backdrop.show(); this._backdrop.show();
if (!this._config.scroll) { if (!this._config.scroll) {
scrollBarHide(); new ScrollBarHelper().hide();
this._enforceFocusOnElement(this._element);
} }
this._element.removeAttribute('aria-hidden'); this._element.removeAttribute('aria-hidden');
@ -119,6 +118,10 @@ class Offcanvas extends BaseComponent {
this._element.classList.add(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
const completeCallBack = () => { const completeCallBack = () => {
if (!this._config.scroll) {
this._focustrap.activate();
}
EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget }); EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget });
}; };
@ -136,7 +139,7 @@ class Offcanvas extends BaseComponent {
return; return;
} }
EventHandler.off(document, EVENT_FOCUSIN); this._focustrap.deactivate();
this._element.blur(); this._element.blur();
this._isShown = false; this._isShown = false;
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_SHOW);
@ -149,7 +152,7 @@ class Offcanvas extends BaseComponent {
this._element.style.visibility = 'hidden'; this._element.style.visibility = 'hidden';
if (!this._config.scroll) { if (!this._config.scroll) {
scrollBarReset(); new ScrollBarHelper().reset();
} }
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
@ -160,8 +163,8 @@ class Offcanvas extends BaseComponent {
dispose() { dispose() {
this._backdrop.dispose(); this._backdrop.dispose();
this._focustrap.deactivate();
super.dispose(); super.dispose();
EventHandler.off(document, EVENT_FOCUSIN);
} }
// Private // Private
@ -178,6 +181,7 @@ class Offcanvas extends BaseComponent {
_initializeBackDrop() { _initializeBackDrop() {
return new Backdrop({ return new Backdrop({
className: CLASS_NAME_BACKDROP,
isVisible: this._config.backdrop, isVisible: this._config.backdrop,
isAnimated: true, isAnimated: true,
rootElement: this._element.parentNode, rootElement: this._element.parentNode,
@ -185,23 +189,13 @@ class Offcanvas extends BaseComponent {
}); });
} }
_enforceFocusOnElement(element) { _initializeFocusTrap() {
EventHandler.off(document, EVENT_FOCUSIN); // guard against infinite focus loop return new FocusTrap({
EventHandler.on(document, EVENT_FOCUSIN, (event) => { trapElement: this._element,
if (
document !== event.target &&
element !== event.target &&
!element.contains(event.target)
) {
element.focus();
}
}); });
element.focus();
} }
_addEventListeners() { _addEventListeners() {
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => {
if (this._config.keyboard && event.key === ESCAPE_KEY) { if (this._config.keyboard && event.key === ESCAPE_KEY) {
this.hide(); this.hide();
@ -213,8 +207,7 @@ class Offcanvas extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = const data = Offcanvas.getOrCreateInstance(this, config);
Data.get(this, DATA_KEY) || new Offcanvas(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -259,17 +252,15 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
Offcanvas.getInstance(allReadyOpen).hide(); Offcanvas.getInstance(allReadyOpen).hide();
} }
const data = Data.get(target, DATA_KEY) || new Offcanvas(target); const data = Offcanvas.getOrCreateInstance(target);
data.toggle(this); data.toggle(this);
}); });
EventHandler.on(window, EVENT_LOAD_DATA_API, () => { EventHandler.on(window, EVENT_LOAD_DATA_API, () =>
SelectorEngine.find(OPEN_SELECTOR).forEach((el) => SelectorEngine.find(OPEN_SELECTOR).forEach((el) => Offcanvas.getOrCreateInstance(el).show())
(Data.get(el, DATA_KEY) || new Offcanvas(el)).show()
); );
});
enableDismissTrigger(Offcanvas);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

View File

@ -1,13 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): popover.js * Bootstrap (v5.1.3): popover.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin } from './util/index'; import { defineJQueryPlugin } from './util/index';
import Data from './dom/data';
import SelectorEngine from './dom/selector-engine';
import Tooltip from './tooltip'; import Tooltip from './tooltip';
/** /**
@ -20,7 +18,6 @@ const NAME = 'popover';
const DATA_KEY = 'bs.popover'; const DATA_KEY = 'bs.popover';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const CLASS_PREFIX = 'bs-popover'; const CLASS_PREFIX = 'bs-popover';
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g');
const Default = { const Default = {
...Tooltip.Default, ...Tooltip.Default,
@ -54,9 +51,6 @@ const Event = {
MOUSELEAVE: `mouseleave${EVENT_KEY}`, MOUSELEAVE: `mouseleave${EVENT_KEY}`,
}; };
const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show';
const SELECTOR_TITLE = '.popover-header'; const SELECTOR_TITLE = '.popover-header';
const SELECTOR_CONTENT = '.popover-body'; const SELECTOR_CONTENT = '.popover-body';
@ -91,54 +85,26 @@ class Popover extends Tooltip {
return this.getTitle() || this._getContent(); return this.getTitle() || this._getContent();
} }
setContent() { setContent(tip) {
const tip = this.getTipElement(); this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TITLE);
this._sanitizeAndSetContent(tip, this._getContent(), SELECTOR_CONTENT);
// we use append for html objects to maintain js events
this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle());
let content = this._getContent();
if (typeof content === 'function') {
content = content.call(this._element);
}
this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content);
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
} }
// Private // Private
_addAttachmentClass(attachment) {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`);
}
_getContent() { _getContent() {
return this._element.getAttribute('data-mdb-content') || this._config.content; return this._resolvePossibleFunction(this._config.content);
} }
_cleanTipClass() { _getBasicClassPrefix() {
const tip = this.getTipElement(); return CLASS_PREFIX;
const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX);
if (tabClass !== null && tabClass.length > 0) {
tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass));
}
} }
// Static // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Popover.getOrCreateInstance(this, config);
const _config = typeof config === 'object' ? config : null;
if (!data && /dispose|hide/.test(config)) {
return;
}
if (!data) {
data = new Popover(this, _config);
Data.set(this, DATA_KEY, data);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {

View File

@ -1,15 +1,14 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): scrollspy.js * Bootstrap (v5.1.3): scrollspy.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { import {
defineJQueryPlugin, defineJQueryPlugin,
getElement,
getSelectorFromElement, getSelectorFromElement,
getUID,
isElement,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
@ -52,6 +51,7 @@ const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
const SELECTOR_NAV_LINKS = '.nav-link'; const SELECTOR_NAV_LINKS = '.nav-link';
const SELECTOR_NAV_ITEMS = '.nav-item'; const SELECTOR_NAV_ITEMS = '.nav-item';
const SELECTOR_LIST_ITEMS = '.list-group-item'; const SELECTOR_LIST_ITEMS = '.list-group-item';
const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}, .${CLASS_NAME_DROPDOWN_ITEM}`;
const SELECTOR_DROPDOWN = '.dropdown'; const SELECTOR_DROPDOWN = '.dropdown';
const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'; const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
@ -67,14 +67,11 @@ const METHOD_POSITION = 'position';
class ScrollSpy extends BaseComponent { class ScrollSpy extends BaseComponent {
constructor(element, config) { constructor(element, config) {
super(element); super(element);
if (!getSelectorFromElement(element)) { if (!getSelectorFromElement(element)) {
return; return;
} }
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element; this._scrollElement = this._element.tagName === 'BODY' ? window : this._element;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`;
this._offsets = []; this._offsets = [];
this._targets = []; this._targets = [];
this._activeTarget = null; this._activeTarget = null;
@ -110,7 +107,7 @@ class ScrollSpy extends BaseComponent {
this._targets = []; this._targets = [];
this._scrollHeight = this._getScrollHeight(); this._scrollHeight = this._getScrollHeight();
const targets = SelectorEngine.find(this._selector); const targets = SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target);
targets targets
.map((element) => { .map((element) => {
@ -148,15 +145,7 @@ class ScrollSpy extends BaseComponent {
...(typeof config === 'object' && config ? config : {}), ...(typeof config === 'object' && config ? config : {}),
}; };
if (typeof config.target !== 'string' && isElement(config.target)) { config.target = getElement(config.target) || document.documentElement;
let { id } = config.target;
if (!id) {
id = getUID(NAME);
config.target.id = id;
}
config.target = `#${id}`;
}
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
@ -224,23 +213,19 @@ class ScrollSpy extends BaseComponent {
this._clear(); this._clear();
const queries = this._selector const queries = SELECTOR_LINK_ITEMS.split(',').map(
.split(',') (selector) => `${selector}[data-mdb-target="${target}"],${selector}[href="${target}"]`
.map((selector) => `${selector}[data-mdb-target="${target}"],${selector}[href="${target}"]`); );
const link = SelectorEngine.findOne(queries.join(',')); const link = SelectorEngine.findOne(queries.join(','), this._config.target);
link.classList.add(CLASS_NAME_ACTIVE);
if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
SelectorEngine.findOne( SelectorEngine.findOne(
SELECTOR_DROPDOWN_TOGGLE, SELECTOR_DROPDOWN_TOGGLE,
link.closest(SELECTOR_DROPDOWN) link.closest(SELECTOR_DROPDOWN)
).classList.add(CLASS_NAME_ACTIVE); ).classList.add(CLASS_NAME_ACTIVE);
link.classList.add(CLASS_NAME_ACTIVE);
} else { } else {
// Set triggered link as active
link.classList.add(CLASS_NAME_ACTIVE);
SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP).forEach((listGroup) => { SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP).forEach((listGroup) => {
// Set triggered links parents as active // Set triggered links parents as active
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
@ -263,7 +248,7 @@ class ScrollSpy extends BaseComponent {
} }
_clear() { _clear() {
SelectorEngine.find(this._selector) SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target)
.filter((node) => node.classList.contains(CLASS_NAME_ACTIVE)) .filter((node) => node.classList.contains(CLASS_NAME_ACTIVE))
.forEach((node) => node.classList.remove(CLASS_NAME_ACTIVE)); .forEach((node) => node.classList.remove(CLASS_NAME_ACTIVE));
} }
@ -272,9 +257,7 @@ class ScrollSpy extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = const data = ScrollSpy.getOrCreateInstance(this, config);
ScrollSpy.getInstance(this) ||
new ScrollSpy(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -296,8 +279,9 @@ class ScrollSpy extends BaseComponent {
*/ */
// EventHandler.on(window, EVENT_LOAD_DATA_API, () => { // EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
// SelectorEngine.find(SELECTOR_DATA_SPY).forEach((spy) => new ScrollSpy(spy)); // SelectorEngine.find(SELECTOR_DATA_SPY)
// }); // .forEach(spy => new ScrollSpy(spy))
// })
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------

View File

@ -1,12 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): tab.js * Bootstrap (v5.1.3): tab.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin, getElementFromSelector, isDisabled, reflow } from './util/index'; import { defineJQueryPlugin, getElementFromSelector, isDisabled, reflow } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
@ -187,7 +186,7 @@ class Tab extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = Data.get(this, DATA_KEY) || new Tab(this); const data = Tab.getOrCreateInstance(this);
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -215,7 +214,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
return; return;
} }
const data = Data.get(this, DATA_KEY) || new Tab(this); const data = Tab.getOrCreateInstance(this);
data.show(); data.show();
}); });

View File

@ -1,15 +1,15 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): toast.js * Bootstrap (v5.1.3): toast.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin, reflow, typeCheckConfig } from './util/index'; import { defineJQueryPlugin, reflow, typeCheckConfig } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -21,7 +21,6 @@ const NAME = 'toast';
const DATA_KEY = 'bs.toast'; const DATA_KEY = 'bs.toast';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`; const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;
const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`; const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`; const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
@ -32,7 +31,7 @@ const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_HIDE = 'hide'; const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_SHOWING = 'showing'; const CLASS_NAME_SHOWING = 'showing';
@ -48,8 +47,6 @@ const Default = {
delay: 5000, delay: 5000,
}; };
const SELECTOR_DATA_DISMISS = '[data-mdb-dismiss="toast"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* Class Definition * Class Definition
@ -98,15 +95,14 @@ class Toast extends BaseComponent {
const complete = () => { const complete = () => {
this._element.classList.remove(CLASS_NAME_SHOWING); this._element.classList.remove(CLASS_NAME_SHOWING);
this._element.classList.add(CLASS_NAME_SHOW);
EventHandler.trigger(this._element, EVENT_SHOWN); EventHandler.trigger(this._element, EVENT_SHOWN);
this._maybeScheduleHide(); this._maybeScheduleHide();
}; };
this._element.classList.remove(CLASS_NAME_HIDE); this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated
reflow(this._element); reflow(this._element);
this._element.classList.add(CLASS_NAME_SHOW);
this._element.classList.add(CLASS_NAME_SHOWING); this._element.classList.add(CLASS_NAME_SHOWING);
this._queueCallback(complete, this._element, this._config.animation); this._queueCallback(complete, this._element, this._config.animation);
@ -124,11 +120,13 @@ class Toast extends BaseComponent {
} }
const complete = () => { const complete = () => {
this._element.classList.add(CLASS_NAME_HIDE); this._element.classList.add(CLASS_NAME_HIDE); // @deprecated
this._element.classList.remove(CLASS_NAME_SHOWING);
this._element.classList.remove(CLASS_NAME_SHOW);
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
}; };
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOWING);
this._queueCallback(complete, this._element, this._config.animation); this._queueCallback(complete, this._element, this._config.animation);
} }
@ -198,7 +196,6 @@ class Toast extends BaseComponent {
} }
_setListeners() { _setListeners() {
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
EventHandler.on(this._element, EVENT_MOUSEOVER, (event) => this._onInteraction(event, true)); EventHandler.on(this._element, EVENT_MOUSEOVER, (event) => this._onInteraction(event, true));
EventHandler.on(this._element, EVENT_MOUSEOUT, (event) => this._onInteraction(event, false)); EventHandler.on(this._element, EVENT_MOUSEOUT, (event) => this._onInteraction(event, false));
EventHandler.on(this._element, EVENT_FOCUSIN, (event) => this._onInteraction(event, true)); EventHandler.on(this._element, EVENT_FOCUSIN, (event) => this._onInteraction(event, true));
@ -214,12 +211,7 @@ class Toast extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Toast.getOrCreateInstance(this, config);
const _config = typeof config === 'object' && config;
if (!data) {
data = new Toast(this, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -232,6 +224,8 @@ class Toast extends BaseComponent {
} }
} }
enableDismissTrigger(Toast);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): tooltip.js * Bootstrap (v5.1.3): tooltip.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -34,7 +34,6 @@ const NAME = 'tooltip';
const DATA_KEY = 'bs.tooltip'; const DATA_KEY = 'bs.tooltip';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const CLASS_PREFIX = 'bs-tooltip'; const CLASS_PREFIX = 'bs-tooltip';
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g');
const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
const DefaultType = { const DefaultType = {
@ -110,6 +109,9 @@ const HOVER_STATE_SHOW = 'show';
const HOVER_STATE_OUT = 'out'; const HOVER_STATE_OUT = 'out';
const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
const EVENT_MODAL_HIDE = 'hide.bs.modal';
const TRIGGER_HOVER = 'hover'; const TRIGGER_HOVER = 'hover';
const TRIGGER_FOCUS = 'focus'; const TRIGGER_FOCUS = 'focus';
@ -205,19 +207,16 @@ class Tooltip extends BaseComponent {
clearTimeout(this._timeout); clearTimeout(this._timeout);
EventHandler.off( EventHandler.off(
this._element.closest(`.${CLASS_NAME_MODAL}`), this._element.closest(SELECTOR_MODAL),
'hide.bs.modal', EVENT_MODAL_HIDE,
this._hideModalHandler this._hideModalHandler
); );
if (this.tip && this.tip.parentNode) { if (this.tip) {
this.tip.parentNode.removeChild(this.tip); this.tip.remove();
}
if (this._popper) {
this._popper.destroy();
} }
this._disposePopper();
super.dispose(); super.dispose();
} }
@ -241,14 +240,24 @@ class Tooltip extends BaseComponent {
return; return;
} }
// A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-mdb-original-title`
// This will be removed later in favor of a `setContent` method
if (
this.constructor.NAME === 'tooltip' &&
this.tip &&
this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML
) {
this._disposePopper();
this.tip.remove();
this.tip = null;
}
const tip = this.getTipElement(); const tip = this.getTipElement();
const tipId = getUID(this.constructor.NAME); const tipId = getUID(this.constructor.NAME);
tip.setAttribute('id', tipId); tip.setAttribute('id', tipId);
this._element.setAttribute('aria-describedby', tipId); this._element.setAttribute('aria-describedby', tipId);
this.setContent();
if (this._config.animation) { if (this._config.animation) {
tip.classList.add(CLASS_NAME_FADE); tip.classList.add(CLASS_NAME_FADE);
} }
@ -265,7 +274,7 @@ class Tooltip extends BaseComponent {
Data.set(tip, this.constructor.DATA_KEY, this); Data.set(tip, this.constructor.DATA_KEY, this);
if (!this._element.ownerDocument.documentElement.contains(this.tip)) { if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip); container.append(tip);
EventHandler.trigger(this._element, this.constructor.Event.INSERTED); EventHandler.trigger(this._element, this.constructor.Event.INSERTED);
} }
@ -277,10 +286,7 @@ class Tooltip extends BaseComponent {
tip.classList.add(CLASS_NAME_SHOW); tip.classList.add(CLASS_NAME_SHOW);
const customClass = const customClass = this._resolvePossibleFunction(this._config.customClass);
typeof this._config.customClass === 'function'
? this._config.customClass()
: this._config.customClass;
if (customClass) { if (customClass) {
tip.classList.add(...customClass.split(' ')); tip.classList.add(...customClass.split(' '));
} }
@ -321,18 +327,15 @@ class Tooltip extends BaseComponent {
return; return;
} }
if (this._hoverState !== HOVER_STATE_SHOW && tip.parentNode) { if (this._hoverState !== HOVER_STATE_SHOW) {
tip.parentNode.removeChild(tip); tip.remove();
} }
this._cleanTipClass(); this._cleanTipClass();
this._element.removeAttribute('aria-describedby'); this._element.removeAttribute('aria-describedby');
EventHandler.trigger(this._element, this.constructor.Event.HIDDEN); EventHandler.trigger(this._element, this.constructor.Event.HIDDEN);
if (this._popper) { this._disposePopper();
this._popper.destroy();
this._popper = null;
}
}; };
const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE); const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE);
@ -379,14 +382,28 @@ class Tooltip extends BaseComponent {
const element = document.createElement('div'); const element = document.createElement('div');
element.innerHTML = this._config.template; element.innerHTML = this._config.template;
this.tip = element.children[0]; const tip = element.children[0];
this.setContent(tip);
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
this.tip = tip;
return this.tip; return this.tip;
} }
setContent() { setContent(tip) {
const tip = this.getTipElement(); this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER);
this.setElementContent(SelectorEngine.findOne(SELECTOR_TOOLTIP_INNER, tip), this.getTitle()); }
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
_sanitizeAndSetContent(template, content, selector) {
const templateElement = SelectorEngine.findOne(selector, template);
if (!content && templateElement) {
templateElement.remove();
return;
}
// we use append for html objects to maintain js events
this.setElementContent(templateElement, content);
} }
setElementContent(element, content) { setElementContent(element, content) {
@ -401,7 +418,7 @@ class Tooltip extends BaseComponent {
if (this._config.html) { if (this._config.html) {
if (content.parentNode !== element) { if (content.parentNode !== element) {
element.innerHTML = ''; element.innerHTML = '';
element.appendChild(content); element.append(content);
} }
} else { } else {
element.textContent = content.textContent; element.textContent = content.textContent;
@ -422,16 +439,9 @@ class Tooltip extends BaseComponent {
} }
getTitle() { getTitle() {
let title = this._element.getAttribute('data-mdb-original-title'); const title = this._element.getAttribute('data-mdb-original-title') || this._config.title;
if (!title) { return this._resolvePossibleFunction(title);
title =
typeof this._config.title === 'function'
? this._config.title.call(this._element)
: this._config.title;
}
return title;
} }
updateAttachment(attachment) { updateAttachment(attachment) {
@ -449,15 +459,10 @@ class Tooltip extends BaseComponent {
// Private // Private
_initializeOnDelegatedTarget(event, context) { _initializeOnDelegatedTarget(event, context) {
const dataKey = this.constructor.DATA_KEY; return (
context = context || Data.get(event.delegateTarget, dataKey); context ||
this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig())
if (!context) { );
context = new this.constructor(event.delegateTarget, this._getDelegateConfig());
Data.set(event.delegateTarget, dataKey, context);
}
return context;
} }
_getOffset() { _getOffset() {
@ -474,6 +479,10 @@ class Tooltip extends BaseComponent {
return offset; return offset;
} }
_resolvePossibleFunction(content) {
return typeof content === 'function' ? content.call(this._element) : content;
}
_getPopperConfig(attachment) { _getPopperConfig(attachment) {
const defaultBsPopperConfig = { const defaultBsPopperConfig = {
placement: attachment, placement: attachment,
@ -525,7 +534,9 @@ class Tooltip extends BaseComponent {
} }
_addAttachmentClass(attachment) { _addAttachmentClass(attachment) {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`); this.getTipElement().classList.add(
`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`
);
} }
_getAttachment(placement) { _getAttachment(placement) {
@ -569,8 +580,8 @@ class Tooltip extends BaseComponent {
}; };
EventHandler.on( EventHandler.on(
this._element.closest(`.${CLASS_NAME_MODAL}`), this._element.closest(SELECTOR_MODAL),
'hide.bs.modal', EVENT_MODAL_HIDE,
this._hideModalHandler this._hideModalHandler
); );
@ -634,9 +645,8 @@ class Tooltip extends BaseComponent {
context = this._initializeOnDelegatedTarget(event, context); context = this._initializeOnDelegatedTarget(event, context);
if (event) { if (event) {
context._activeTrigger[ context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] =
event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER context._element.contains(event.relatedTarget);
] = context._element.contains(event.relatedTarget);
} }
if (context._isWithActiveTrigger()) { if (context._isWithActiveTrigger()) {
@ -713,25 +723,31 @@ class Tooltip extends BaseComponent {
_getDelegateConfig() { _getDelegateConfig() {
const config = {}; const config = {};
if (this._config) {
for (const key in this._config) { for (const key in this._config) {
if (this.constructor.Default[key] !== this._config[key]) { if (this.constructor.Default[key] !== this._config[key]) {
config[key] = this._config[key]; config[key] = this._config[key];
} }
} }
}
// In the future can be replaced with:
// const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
// `Object.fromEntries(keysWithDifferentValues)`
return config; return config;
} }
_cleanTipClass() { _cleanTipClass() {
const tip = this.getTipElement(); const tip = this.getTipElement();
const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX); const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g');
const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex);
if (tabClass !== null && tabClass.length > 0) { if (tabClass !== null && tabClass.length > 0) {
tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass)); tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass));
} }
} }
_getBasicClassPrefix() {
return CLASS_PREFIX;
}
_handlePopperPlacementChange(popperData) { _handlePopperPlacementChange(popperData) {
const { state } = popperData; const { state } = popperData;
@ -744,20 +760,18 @@ class Tooltip extends BaseComponent {
this._addAttachmentClass(this._getAttachment(state.placement)); this._addAttachmentClass(this._getAttachment(state.placement));
} }
_disposePopper() {
if (this._popper) {
this._popper.destroy();
this._popper = null;
}
}
// Static // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Tooltip.getOrCreateInstance(this, config);
const _config = typeof config === 'object' && config;
if (!data && /dispose|hide/.test(config)) {
return;
}
if (!data) {
data = new Tooltip(this, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {

View File

@ -1,34 +1,29 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/backdrop.js * Bootstrap (v5.1.3): util/backdrop.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import EventHandler from '../dom/event-handler'; import EventHandler from '../dom/event-handler';
import { import { execute, executeAfterTransition, getElement, reflow, typeCheckConfig } from './index';
emulateTransitionEnd,
execute,
getTransitionDurationFromElement,
reflow,
typeCheckConfig,
} from './index';
const Default = { const Default = {
className: 'modal-backdrop',
isVisible: true, // if false, we use the backdrop helper without adding any element to the dom isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
isAnimated: false, isAnimated: false,
rootElement: document.body, // give the choice to place backdrop under different elements rootElement: 'body', // give the choice to place backdrop under different elements
clickCallback: null, clickCallback: null,
}; };
const DefaultType = { const DefaultType = {
className: 'string',
isVisible: 'boolean', isVisible: 'boolean',
isAnimated: 'boolean', isAnimated: 'boolean',
rootElement: 'element', rootElement: '(element|string)',
clickCallback: '(function|null)', clickCallback: '(function|null)',
}; };
const NAME = 'backdrop'; const NAME = 'backdrop';
const CLASS_NAME_BACKDROP = 'modal-backdrop';
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
@ -79,7 +74,7 @@ class Backdrop {
_getElement() { _getElement() {
if (!this._element) { if (!this._element) {
const backdrop = document.createElement('div'); const backdrop = document.createElement('div');
backdrop.className = CLASS_NAME_BACKDROP; backdrop.className = this._config.className;
if (this._config.isAnimated) { if (this._config.isAnimated) {
backdrop.classList.add(CLASS_NAME_FADE); backdrop.classList.add(CLASS_NAME_FADE);
} }
@ -96,7 +91,8 @@ class Backdrop {
...(typeof config === 'object' ? config : {}), ...(typeof config === 'object' ? config : {}),
}; };
config.rootElement = config.rootElement || document.body; // use getElement() with the default "body" to get a fresh Element on each instantiation
config.rootElement = getElement(config.rootElement);
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
} }
@ -106,7 +102,7 @@ class Backdrop {
return; return;
} }
this._config.rootElement.appendChild(this._getElement()); this._config.rootElement.append(this._getElement());
EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => { EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => {
execute(this._config.clickCallback); execute(this._config.clickCallback);
@ -122,19 +118,12 @@ class Backdrop {
EventHandler.off(this._element, EVENT_MOUSEDOWN); EventHandler.off(this._element, EVENT_MOUSEDOWN);
this._getElement().parentNode.removeChild(this._element); this._element.remove();
this._isAppended = false; this._isAppended = false;
} }
_emulateAnimation(callback) { _emulateAnimation(callback) {
if (!this._config.isAnimated) { executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
execute(callback);
return;
}
const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement());
EventHandler.one(this._getElement(), 'transitionend', () => execute(callback));
emulateTransitionEnd(this._getElement(), backdropTransitionDuration);
} }
} }

View File

@ -0,0 +1,32 @@
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/component-functions.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
import EventHandler from '../dom/event-handler';
import { getElementFromSelector, isDisabled } from './index';
const enableDismissTrigger = (component, method = 'hide') => {
const clickEvent = `click.dismiss${component.EVENT_KEY}`;
const name = component.NAME;
EventHandler.on(document, clickEvent, `[data-mdb-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]();
});
};
export { enableDismissTrigger };

View File

@ -0,0 +1,105 @@
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/focustrap.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
import EventHandler from '../dom/event-handler';
import SelectorEngine from '../dom/selector-engine';
import { typeCheckConfig } from './index';
const Default = {
trapElement: null, // The element to trap focus inside of
autofocus: true,
};
const DefaultType = {
trapElement: 'element',
autofocus: 'boolean',
};
const NAME = 'focustrap';
const DATA_KEY = 'bs.focustrap';
const EVENT_KEY = `.${DATA_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY}`;
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.off(document, EVENT_KEY); // guard against infinite focus loop
EventHandler.on(document, EVENT_FOCUSIN, (event) => this._handleFocusin(event));
EventHandler.on(document, EVENT_KEYDOWN_TAB, (event) => this._handleKeydown(event));
this._isActive = true;
}
deactivate() {
if (!this._isActive) {
return;
}
this._isActive = false;
EventHandler.off(document, EVENT_KEY);
}
// Private
_handleFocusin(event) {
const { target } = event;
const { trapElement } = this._config;
if (target === document || target === trapElement || trapElement.contains(target)) {
return;
}
const elements = SelectorEngine.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,
...(typeof config === 'object' ? config : {}),
};
typeCheckConfig(NAME, config, DefaultType);
return config;
}
}
export default FocusTrap;

View File

@ -1,8 +1,6 @@
import SelectorEngine from '../dom/selector-engine';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/index.js * Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -127,30 +125,12 @@ const getElement = (obj) => {
} }
if (typeof obj === 'string' && obj.length > 0) { if (typeof obj === 'string' && obj.length > 0) {
return SelectorEngine.findOne(obj); return document.querySelector(obj);
} }
return null; return null;
}; };
const emulateTransitionEnd = (element, duration) => {
let called = false;
const durationPadding = 5;
const emulatedDuration = duration + durationPadding;
function listener() {
called = true;
element.removeEventListener(TRANSITION_END, listener);
}
element.addEventListener(TRANSITION_END, listener);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(element);
}
}, emulatedDuration);
};
const typeCheckConfig = (componentName, config, configTypes) => { const typeCheckConfig = (componentName, config, configTypes) => {
Object.keys(configTypes).forEach((property) => { Object.keys(configTypes).forEach((property) => {
const expectedTypes = configTypes[property]; const expectedTypes = configTypes[property];
@ -166,22 +146,11 @@ const typeCheckConfig = (componentName, config, configTypes) => {
}; };
const isVisible = (element) => { const isVisible = (element) => {
if (!element) { if (!isElement(element) || element.getClientRects().length === 0) {
return false; return false;
} }
if (element.style && element.parentNode && element.parentNode.style) { return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
const elementStyle = getComputedStyle(element);
const parentNodeStyle = getComputedStyle(element.parentNode);
return (
elementStyle.display !== 'none' &&
parentNodeStyle.display !== 'none' &&
elementStyle.visibility !== 'hidden'
);
}
return false;
}; };
const isDisabled = (element) => { const isDisabled = (element) => {
@ -225,7 +194,18 @@ const findShadowRoot = (element) => {
const noop = () => {}; const noop = () => {};
const reflow = (element) => element.offsetHeight; /**
* 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 getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -237,9 +217,18 @@ const getjQuery = () => {
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -270,6 +259,63 @@ const execute = (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);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element depending on the direction and if cycle is allowed
if (index === -1) {
return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];
}
const listLength = list.length;
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
export { export {
getElement, getElement,
getUID, getUID,
@ -278,16 +324,17 @@ export {
getTransitionDurationFromElement, getTransitionDurationFromElement,
triggerTransitionEnd, triggerTransitionEnd,
isElement, isElement,
emulateTransitionEnd,
typeCheckConfig, typeCheckConfig,
isVisible, isVisible,
isDisabled, isDisabled,
findShadowRoot, findShadowRoot,
noop, noop,
getNextActiveElement,
reflow, reflow,
getjQuery, getjQuery,
onDOMContentLoaded, onDOMContentLoaded,
isRTL, isRTL,
defineJQueryPlugin, defineJQueryPlugin,
execute, execute,
executeAfterTransition,
}; };

View File

@ -1,11 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/sanitizer.js * Bootstrap (v5.1.3): util/sanitizer.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const uriAttrs = new Set([ const uriAttributes = new Set([
'background', 'background',
'cite', 'cite',
'href', 'href',
@ -21,35 +21,36 @@ const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
/** /**
* A pattern that recognizes a commonly useful subset of URLs that are safe. * A pattern that recognizes a commonly useful subset of URLs that are safe.
* *
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
*/ */
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i; const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i;
/** /**
* A pattern that matches safe data URLs. Only matches image, video and audio types. * A pattern that matches safe data URLs. Only matches image, video and audio types.
* *
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
*/ */
const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; const DATA_URL_PATTERN =
/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;
const allowedAttribute = (attr, allowedAttributeList) => { const allowedAttribute = (attribute, allowedAttributeList) => {
const attrName = attr.nodeName.toLowerCase(); const attributeName = attribute.nodeName.toLowerCase();
if (allowedAttributeList.includes(attrName)) { if (allowedAttributeList.includes(attributeName)) {
if (uriAttrs.has(attrName)) { if (uriAttributes.has(attributeName)) {
return Boolean( return Boolean(
SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue) SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)
); );
} }
return true; return true;
} }
const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp); const regExp = allowedAttributeList.filter((attributeRegex) => attributeRegex instanceof RegExp);
// Check if a regular expression validates the attribute. // Check if a regular expression validates the attribute.
for (let i = 0, len = regExp.length; i < len; i++) { for (let i = 0, len = regExp.length; i < len; i++) {
if (regExp[i].test(attrName)) { if (regExp[i].test(attributeName)) {
return true; return true;
} }
} }
@ -102,25 +103,24 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
const domParser = new window.DOMParser(); const domParser = new window.DOMParser();
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
const allowlistKeys = Object.keys(allowList);
const elements = [].concat(...createdDocument.body.querySelectorAll('*')); const elements = [].concat(...createdDocument.body.querySelectorAll('*'));
for (let i = 0, len = elements.length; i < len; i++) { for (let i = 0, len = elements.length; i < len; i++) {
const el = elements[i]; const element = elements[i];
const elName = el.nodeName.toLowerCase(); const elementName = element.nodeName.toLowerCase();
if (!allowlistKeys.includes(elName)) { if (!Object.keys(allowList).includes(elementName)) {
el.parentNode.removeChild(el); element.remove();
continue; continue;
} }
const attributeList = [].concat(...el.attributes); const attributeList = [].concat(...element.attributes);
const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []); const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);
attributeList.forEach((attr) => { attributeList.forEach((attribute) => {
if (!allowedAttribute(attr, allowedAttributes)) { if (!allowedAttribute(attribute, allowedAttributes)) {
el.removeAttribute(attr.nodeName); element.removeAttribute(attribute.nodeName);
} }
}); });
} }

View File

@ -1,71 +1,86 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/scrollBar.js * Bootstrap (v5.1.3): util/scrollBar.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import SelectorEngine from '../dom/selector-engine'; import SelectorEngine from '../dom/selector-engine';
import Manipulator from '../dom/manipulator'; import Manipulator from '../dom/manipulator';
import { isElement } from './index';
const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
const SELECTOR_STICKY_CONTENT = '.sticky-top'; const SELECTOR_STICKY_CONTENT = '.sticky-top';
const getWidth = () => { class ScrollBarHelper {
constructor() {
this._element = document.body;
}
getWidth() {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
const documentWidth = document.documentElement.clientWidth; const documentWidth = document.documentElement.clientWidth;
return Math.abs(window.innerWidth - documentWidth); return Math.abs(window.innerWidth - documentWidth);
}; }
const hide = (width = getWidth()) => { hide() {
_disableOverFlow(); const width = this.getWidth();
// give padding to element to balances the hidden scrollbar width this._disableOverFlow();
_setElementAttributes('body', 'paddingRight', (calculatedValue) => calculatedValue + width); // give padding to element to balance the hidden scrollbar width
// trick: We adjust positive paddingRight and negative marginRight to sticky-top elements, to keep shown fullwidth this._setElementAttributes(
_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, SELECTOR_FIXED_CONTENT,
'paddingRight', 'paddingRight',
(calculatedValue) => calculatedValue + width (calculatedValue) => calculatedValue + width
); );
_setElementAttributes( this._setElementAttributes(
SELECTOR_STICKY_CONTENT, SELECTOR_STICKY_CONTENT,
'marginRight', 'marginRight',
(calculatedValue) => calculatedValue - width (calculatedValue) => calculatedValue - width
); );
};
const _disableOverFlow = () => {
const actualValue = document.body.style.overflow;
if (actualValue) {
Manipulator.setDataAttribute(document.body, 'overflow', actualValue);
} }
document.body.style.overflow = 'hidden'; _disableOverFlow() {
}; this._saveInitialAttribute(this._element, 'overflow');
this._element.style.overflow = 'hidden';
}
const _setElementAttributes = (selector, styleProp, callback) => { _setElementAttributes(selector, styleProp, callback) {
const scrollbarWidth = getWidth(); const scrollbarWidth = this.getWidth();
SelectorEngine.find(selector).forEach((element) => { const manipulationCallBack = (element) => {
if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) { if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
return; return;
} }
const actualValue = element.style[styleProp]; this._saveInitialAttribute(element, styleProp);
const calculatedValue = window.getComputedStyle(element)[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`;
});
}; };
const reset = () => { this._applyManipulationCallback(selector, manipulationCallBack);
_resetElementAttributes('body', 'overflow'); }
_resetElementAttributes('body', 'paddingRight');
_resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
_resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
};
const _resetElementAttributes = (selector, styleProp) => { reset() {
SelectorEngine.find(selector).forEach((element) => { 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.setDataAttribute(element, styleProp, actualValue);
}
}
_resetElementAttributes(selector, styleProp) {
const manipulationCallBack = (element) => {
const value = Manipulator.getDataAttribute(element, styleProp); const value = Manipulator.getDataAttribute(element, styleProp);
if (typeof value === 'undefined') { if (typeof value === 'undefined') {
element.style.removeProperty(styleProp); element.style.removeProperty(styleProp);
@ -73,11 +88,22 @@ const _resetElementAttributes = (selector, styleProp) => {
Manipulator.removeDataAttribute(element, styleProp); Manipulator.removeDataAttribute(element, styleProp);
element.style[styleProp] = value; element.style[styleProp] = value;
} }
});
}; };
const isBodyOverflowing = () => { this._applyManipulationCallback(selector, manipulationCallBack);
return getWidth() > 0; }
};
export { getWidth, hide, isBodyOverflowing, reset }; _applyManipulationCallback(selector, callBack) {
if (isElement(selector)) {
callBack(selector);
} else {
SelectorEngine.find(selector, this._element).forEach(callBack);
}
}
isOverflowing() {
return this.getWidth() > 0;
}
}
export default ScrollBarHelper;

View File

@ -1,14 +1,14 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): alert.js * Bootstrap (v5.1.3): alert.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin, getElementFromSelector } from './util/index'; import { defineJQueryPlugin } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -19,15 +19,9 @@ import BaseComponent from './base-component';
const NAME = 'alert'; const NAME = 'alert';
const DATA_KEY = 'bs.alert'; const DATA_KEY = 'bs.alert';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const DATA_API_KEY = '.data-api';
const SELECTOR_DISMISS = '[data-bs-dismiss="alert"]';
const EVENT_CLOSE = `close${EVENT_KEY}`; const EVENT_CLOSE = `close${EVENT_KEY}`;
const EVENT_CLOSED = `closed${EVENT_KEY}`; const EVENT_CLOSED = `closed${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const CLASS_NAME_ALERT = 'alert';
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
@ -46,67 +40,43 @@ class Alert extends BaseComponent {
// Public // Public
close(element) { close() {
const rootElement = element ? this._getRootElement(element) : this._element; const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE);
const customEvent = this._triggerCloseEvent(rootElement);
if (customEvent === null || customEvent.defaultPrevented) { if (closeEvent.defaultPrevented) {
return; return;
} }
this._removeElement(rootElement); this._element.classList.remove(CLASS_NAME_SHOW);
const isAnimated = this._element.classList.contains(CLASS_NAME_FADE);
this._queueCallback(() => this._destroyElement(), this._element, isAnimated);
} }
// Private // Private
_destroyElement() {
_getRootElement(element) { this._element.remove();
return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`); EventHandler.trigger(this._element, EVENT_CLOSED);
} this.dispose();
_triggerCloseEvent(element) {
return EventHandler.trigger(element, EVENT_CLOSE);
}
_removeElement(element) {
element.classList.remove(CLASS_NAME_SHOW);
const isAnimated = element.classList.contains(CLASS_NAME_FADE);
this._queueCallback(() => this._destroyElement(element), element, isAnimated);
}
_destroyElement(element) {
if (element.parentNode) {
element.parentNode.removeChild(element);
}
EventHandler.trigger(element, EVENT_CLOSED);
} }
// Static // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Alert.getOrCreateInstance(this);
if (!data) { if (typeof config !== 'string') {
data = new Alert(this); return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
} }
if (config === 'close') {
data[config](this); data[config](this);
}
}); });
} }
static handleDismiss(alertInstance) {
return function (event) {
if (event) {
event.preventDefault();
}
alertInstance.close(this);
};
}
} }
/** /**
@ -115,7 +85,7 @@ class Alert extends BaseComponent {
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert.handleDismiss(new Alert())); enableDismissTrigger(Alert, 'close');
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------

View File

@ -1,17 +1,12 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): base-component.js * Bootstrap (v5.1.3): base-component.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import Data from './dom/data'; import Data from './dom/data';
import { import { executeAfterTransition, getElement } from './util/index';
emulateTransitionEnd,
execute,
getElement,
getTransitionDurationFromElement,
} from './util/index';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
/** /**
@ -20,7 +15,7 @@ import EventHandler from './dom/event-handler';
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
const VERSION = '5.0.1'; const VERSION = '5.1.3';
class BaseComponent { class BaseComponent {
constructor(element) { constructor(element) {
@ -44,21 +39,19 @@ class BaseComponent {
} }
_queueCallback(callback, element, isAnimated = true) { _queueCallback(callback, element, isAnimated = true) {
if (!isAnimated) { executeAfterTransition(callback, element, isAnimated);
execute(callback);
return;
}
const transitionDuration = getTransitionDurationFromElement(element);
EventHandler.one(element, 'transitionend', () => execute(callback));
emulateTransitionEnd(element, transitionDuration);
} }
/** Static */ /** Static */
static getInstance(element) { static getInstance(element) {
return Data.get(element, this.DATA_KEY); return Data.get(getElement(element), this.DATA_KEY);
}
static getOrCreateInstance(element, config = {}) {
return (
this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
);
} }
static get VERSION() { static get VERSION() {

View File

@ -1,12 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): button.js * Bootstrap (v5.1.3): button.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin } from './util/index'; import { defineJQueryPlugin } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
@ -51,11 +50,7 @@ class Button extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Button.getOrCreateInstance(this);
if (!data) {
data = new Button(this);
}
if (config === 'toggle') { if (config === 'toggle') {
data[config](); data[config]();
@ -74,11 +69,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, (event) =>
event.preventDefault(); event.preventDefault();
const button = event.target.closest(SELECTOR_DATA_TOGGLE); const button = event.target.closest(SELECTOR_DATA_TOGGLE);
const data = Button.getOrCreateInstance(button);
let data = Data.get(button, DATA_KEY);
if (!data) {
data = new Button(button);
}
data.toggle(); data.toggle();
}); });

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): carousel.js * Bootstrap (v5.1.3): carousel.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -10,11 +10,11 @@ import {
getElementFromSelector, getElementFromSelector,
isRTL, isRTL,
isVisible, isVisible,
getNextActiveElement,
reflow, reflow,
triggerTransitionEnd, triggerTransitionEnd,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
@ -59,6 +59,11 @@ const ORDER_PREV = 'prev';
const DIRECTION_LEFT = 'left'; const DIRECTION_LEFT = 'left';
const DIRECTION_RIGHT = 'right'; const DIRECTION_RIGHT = 'right';
const KEY_TO_DIRECTION = {
[ARROW_LEFT_KEY]: DIRECTION_RIGHT,
[ARROW_RIGHT_KEY]: DIRECTION_LEFT,
};
const EVENT_SLIDE = `slide${EVENT_KEY}`; const EVENT_SLIDE = `slide${EVENT_KEY}`;
const EVENT_SLID = `slid${EVENT_KEY}`; const EVENT_SLID = `slid${EVENT_KEY}`;
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`; const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
@ -135,10 +140,8 @@ class Carousel extends BaseComponent {
// Public // Public
next() { next() {
if (!this._isSliding) {
this._slide(ORDER_NEXT); this._slide(ORDER_NEXT);
} }
}
nextWhenVisible() { nextWhenVisible() {
// Don't call next when the page isn't visible // Don't call next when the page isn't visible
@ -149,10 +152,8 @@ class Carousel extends BaseComponent {
} }
prev() { prev() {
if (!this._isSliding) {
this._slide(ORDER_PREV); this._slide(ORDER_PREV);
} }
}
pause(event) { pause(event) {
if (!event) { if (!event) {
@ -217,7 +218,8 @@ class Carousel extends BaseComponent {
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...config, ...Manipulator.getDataAttributes(this._element),
...(typeof config === 'object' ? config : {}),
}; };
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
@ -257,11 +259,15 @@ class Carousel extends BaseComponent {
} }
_addTouchEventListeners() { _addTouchEventListeners() {
const start = (event) => { const hasPointerPenTouch = (event) => {
if ( return (
this._pointerEvent && this._pointerEvent &&
(event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH) (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
) { );
};
const start = (event) => {
if (hasPointerPenTouch(event)) {
this.touchStartX = event.clientX; this.touchStartX = event.clientX;
} else if (!this._pointerEvent) { } else if (!this._pointerEvent) {
this.touchStartX = event.touches[0].clientX; this.touchStartX = event.touches[0].clientX;
@ -275,10 +281,7 @@ class Carousel extends BaseComponent {
}; };
const end = (event) => { const end = (event) => {
if ( if (hasPointerPenTouch(event)) {
this._pointerEvent &&
(event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
) {
this.touchDeltaX = event.clientX - this.touchStartX; this.touchDeltaX = event.clientX - this.touchStartX;
} }
@ -305,7 +308,7 @@ class Carousel extends BaseComponent {
}; };
SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach((itemImg) => { SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach((itemImg) => {
EventHandler.on(itemImg, EVENT_DRAG_START, (e) => e.preventDefault()); EventHandler.on(itemImg, EVENT_DRAG_START, (event) => event.preventDefault());
}); });
if (this._pointerEvent) { if (this._pointerEvent) {
@ -325,12 +328,10 @@ class Carousel extends BaseComponent {
return; return;
} }
if (event.key === ARROW_LEFT_KEY) { const direction = KEY_TO_DIRECTION[event.key];
if (direction) {
event.preventDefault(); event.preventDefault();
this._slide(DIRECTION_RIGHT); this._slide(direction);
} else if (event.key === ARROW_RIGHT_KEY) {
event.preventDefault();
this._slide(DIRECTION_LEFT);
} }
} }
@ -343,20 +344,7 @@ class Carousel extends BaseComponent {
_getItemByOrder(order, activeElement) { _getItemByOrder(order, activeElement) {
const isNext = order === ORDER_NEXT; const isNext = order === ORDER_NEXT;
const isPrev = order === ORDER_PREV; return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);
const activeIndex = this._getItemIndex(activeElement);
const lastItemIndex = this._items.length - 1;
const isGoingToWrap =
(isPrev && activeIndex === 0) || (isNext && activeIndex === lastItemIndex);
if (isGoingToWrap && !this._config.wrap) {
return activeElement;
}
const delta = isPrev ? -1 : 1;
const itemIndex = (activeIndex + delta) % this._items.length;
return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
} }
_triggerSlideEvent(relatedTarget, eventDirectionName) { _triggerSlideEvent(relatedTarget, eventDirectionName) {
@ -432,6 +420,10 @@ class Carousel extends BaseComponent {
return; return;
} }
if (this._isSliding) {
return;
}
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
if (slideEvent.defaultPrevented) { if (slideEvent.defaultPrevented) {
return; return;
@ -520,12 +512,9 @@ class Carousel extends BaseComponent {
// Static // Static
static carouselInterface(element, config) { static carouselInterface(element, config) {
let data = Data.get(element, DATA_KEY); const data = Carousel.getOrCreateInstance(element, config);
let _config = {
...Default,
...Manipulator.getDataAttributes(element),
};
let { _config } = data;
if (typeof config === 'object') { if (typeof config === 'object') {
_config = { _config = {
..._config, ..._config,
@ -535,10 +524,6 @@ class Carousel extends BaseComponent {
const action = typeof config === 'string' ? config : _config.slide; const action = typeof config === 'string' ? config : _config.slide;
if (!data) {
data = new Carousel(element, _config);
}
if (typeof config === 'number') { if (typeof config === 'number') {
data.to(config); data.to(config);
} else if (typeof action === 'string') { } else if (typeof action === 'string') {
@ -579,7 +564,7 @@ class Carousel extends BaseComponent {
Carousel.carouselInterface(target, config); Carousel.carouselInterface(target, config);
if (slideIndex) { if (slideIndex) {
Data.get(target, DATA_KEY).to(slideIndex); Carousel.getInstance(target).to(slideIndex);
} }
event.preventDefault(); event.preventDefault();
@ -598,7 +583,7 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE); const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);
for (let i = 0, len = carousels.length; i < len; i++) { for (let i = 0, len = carousels.length; i < len; i++) {
Carousel.carouselInterface(carousels[i], Data.get(carousels[i], DATA_KEY)); Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));
} }
}); });

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): collapse.js * Bootstrap (v5.1.3): collapse.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -32,12 +32,12 @@ const DATA_API_KEY = '.data-api';
const Default = { const Default = {
toggle: true, toggle: true,
parent: '', parent: null,
}; };
const DefaultType = { const DefaultType = {
toggle: 'boolean', toggle: 'boolean',
parent: '(string|element)', parent: '(null|element)',
}; };
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
@ -50,11 +50,13 @@ const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_COLLAPSE = 'collapse'; const CLASS_NAME_COLLAPSE = 'collapse';
const CLASS_NAME_COLLAPSING = 'collapsing'; const CLASS_NAME_COLLAPSING = 'collapsing';
const CLASS_NAME_COLLAPSED = 'collapsed'; const CLASS_NAME_COLLAPSED = 'collapsed';
const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;
const CLASS_NAME_HORIZONTAL = 'collapse-horizontal';
const WIDTH = 'width'; const WIDTH = 'width';
const HEIGHT = 'height'; const HEIGHT = 'height';
const SELECTOR_ACTIVES = '.show, .collapsing'; const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]'; const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]';
/** /**
@ -69,10 +71,7 @@ class Collapse extends BaseComponent {
this._isTransitioning = false; this._isTransitioning = false;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._triggerArray = SelectorEngine.find( this._triggerArray = [];
`${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` +
`${SELECTOR_DATA_TOGGLE}[data-bs-target="#${this._element.id}"]`
);
const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE); const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE);
@ -89,10 +88,10 @@ class Collapse extends BaseComponent {
} }
} }
this._parent = this._config.parent ? this._getParent() : null; this._initializeChildren();
if (!this._config.parent) { if (!this._config.parent) {
this._addAriaAndCollapsedClass(this._element, this._triggerArray); this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());
} }
if (this._config.toggle) { if (this._config.toggle) {
@ -113,7 +112,7 @@ class Collapse extends BaseComponent {
// Public // Public
toggle() { toggle() {
if (this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isShown()) {
this.hide(); this.hide();
} else { } else {
this.show(); this.show();
@ -121,31 +120,24 @@ class Collapse extends BaseComponent {
} }
show() { show() {
if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isTransitioning || this._isShown()) {
return; return;
} }
let actives; let actives = [];
let activesData; let activesData;
if (this._parent) { if (this._config.parent) {
actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent).filter((elem) => { const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);
if (typeof this._config.parent === 'string') { actives = SelectorEngine.find(SELECTOR_ACTIVES, this._config.parent).filter(
return elem.getAttribute('data-bs-parent') === this._config.parent; (elem) => !children.includes(elem)
} ); // remove children if greater depth
return elem.classList.contains(CLASS_NAME_COLLAPSE);
});
if (actives.length === 0) {
actives = null;
}
} }
const container = SelectorEngine.findOne(this._selector); const container = SelectorEngine.findOne(this._selector);
if (actives) { if (actives.length) {
const tempActiveData = actives.find((elem) => container !== elem); const tempActiveData = actives.find((elem) => container !== elem);
activesData = tempActiveData ? Data.get(tempActiveData, DATA_KEY) : null; activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null;
if (activesData && activesData._isTransitioning) { if (activesData && activesData._isTransitioning) {
return; return;
@ -157,17 +149,15 @@ class Collapse extends BaseComponent {
return; return;
} }
if (actives) {
actives.forEach((elemActive) => { actives.forEach((elemActive) => {
if (container !== elemActive) { if (container !== elemActive) {
Collapse.collapseInterface(elemActive, 'hide'); Collapse.getOrCreateInstance(elemActive, { toggle: false }).hide();
} }
if (!activesData) { if (!activesData) {
Data.set(elemActive, DATA_KEY, null); Data.set(elemActive, DATA_KEY, null);
} }
}); });
}
const dimension = this._getDimension(); const dimension = this._getDimension();
@ -176,23 +166,17 @@ class Collapse extends BaseComponent {
this._element.style[dimension] = 0; this._element.style[dimension] = 0;
if (this._triggerArray.length) { this._addAriaAndCollapsedClass(this._triggerArray, true);
this._triggerArray.forEach((element) => { this._isTransitioning = true;
element.classList.remove(CLASS_NAME_COLLAPSED);
element.setAttribute('aria-expanded', true);
});
}
this.setTransitioning(true);
const complete = () => { const complete = () => {
this._isTransitioning = false;
this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSING);
this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);
this._element.style[dimension] = ''; this._element.style[dimension] = '';
this.setTransitioning(false);
EventHandler.trigger(this._element, EVENT_SHOWN); EventHandler.trigger(this._element, EVENT_SHOWN);
}; };
@ -204,7 +188,7 @@ class Collapse extends BaseComponent {
} }
hide() { hide() {
if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) { if (this._isTransitioning || !this._isShown()) {
return; return;
} }
@ -223,22 +207,19 @@ class Collapse extends BaseComponent {
this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);
const triggerArrayLength = this._triggerArray.length; const triggerArrayLength = this._triggerArray.length;
if (triggerArrayLength > 0) {
for (let i = 0; i < triggerArrayLength; i++) { for (let i = 0; i < triggerArrayLength; i++) {
const trigger = this._triggerArray[i]; const trigger = this._triggerArray[i];
const elem = getElementFromSelector(trigger); const elem = getElementFromSelector(trigger);
if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { if (elem && !this._isShown(elem)) {
trigger.classList.add(CLASS_NAME_COLLAPSED); this._addAriaAndCollapsedClass([trigger], false);
trigger.setAttribute('aria-expanded', false);
}
} }
} }
this.setTransitioning(true); this._isTransitioning = true;
const complete = () => { const complete = () => {
this.setTransitioning(false); this._isTransitioning = false;
this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSING);
this._element.classList.add(CLASS_NAME_COLLAPSE); this._element.classList.add(CLASS_NAME_COLLAPSE);
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
@ -249,8 +230,8 @@ class Collapse extends BaseComponent {
this._queueCallback(complete, this._element, true); this._queueCallback(complete, this._element, true);
} }
setTransitioning(isTransitioning) { _isShown(element = this._element) {
this._isTransitioning = isTransitioning; return element.classList.contains(CLASS_NAME_SHOW);
} }
// Private // Private
@ -258,39 +239,40 @@ class Collapse extends BaseComponent {
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator.getDataAttributes(this._element),
...config, ...config,
}; };
config.toggle = Boolean(config.toggle); // Coerce string values config.toggle = Boolean(config.toggle); // Coerce string values
config.parent = getElement(config.parent);
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
} }
_getDimension() { _getDimension() {
return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT; return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;
} }
_getParent() { _initializeChildren() {
let { parent } = this._config; if (!this._config.parent) {
parent = getElement(parent);
const selector = `${SELECTOR_DATA_TOGGLE}[data-bs-parent="${parent}"]`;
SelectorEngine.find(selector, parent).forEach((element) => {
const selected = getElementFromSelector(element);
this._addAriaAndCollapsedClass(selected, [element]);
});
return parent;
}
_addAriaAndCollapsedClass(element, triggerArray) {
if (!element || !triggerArray.length) {
return; return;
} }
const isOpen = element.classList.contains(CLASS_NAME_SHOW); const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);
SelectorEngine.find(SELECTOR_DATA_TOGGLE, this._config.parent)
.filter((elem) => !children.includes(elem))
.forEach((element) => {
const selected = getElementFromSelector(element);
if (selected) {
this._addAriaAndCollapsedClass([element], this._isShown(selected));
}
});
}
_addAriaAndCollapsedClass(triggerArray, isOpen) {
if (!triggerArray.length) {
return;
}
triggerArray.forEach((elem) => { triggerArray.forEach((elem) => {
if (isOpen) { if (isOpen) {
@ -305,21 +287,14 @@ class Collapse extends BaseComponent {
// Static // Static
static collapseInterface(element, config) { static jQueryInterface(config) {
let data = Data.get(element, DATA_KEY); return this.each(function () {
const _config = { const _config = {};
...Default, if (typeof config === 'string' && /show|hide/.test(config)) {
...Manipulator.getDataAttributes(element),
...(typeof config === 'object' && config ? config : {}),
};
if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false; _config.toggle = false;
} }
if (!data) { const data = Collapse.getOrCreateInstance(this, _config);
data = new Collapse(element, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -328,11 +303,6 @@ class Collapse extends BaseComponent {
data[config](); data[config]();
} }
}
static jQueryInterface(config) {
return this.each(function () {
Collapse.collapseInterface(this, config);
}); });
} }
} }
@ -352,26 +322,11 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
event.preventDefault(); event.preventDefault();
} }
const triggerData = Manipulator.getDataAttributes(this);
const selector = getSelectorFromElement(this); const selector = getSelectorFromElement(this);
const selectorElements = SelectorEngine.find(selector); const selectorElements = SelectorEngine.find(selector);
selectorElements.forEach((element) => { selectorElements.forEach((element) => {
const data = Data.get(element, DATA_KEY); Collapse.getOrCreateInstance(element, { toggle: false }).toggle();
let config;
if (data) {
// update parent attribute
if (data._parent === null && typeof triggerData.parent === 'string') {
data._config.parent = triggerData.parent;
data._parent = data._getParent();
}
config = 'toggle';
} else {
config = triggerData;
}
Collapse.collapseInterface(element, config);
}); });
}); });

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/data.js * Bootstrap (v5.1.3): dom/data.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/event-handler.js * Bootstrap (v5.1.3): dom/event-handler.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -113,7 +113,6 @@ function bootstrapDelegationHandler(element, selector, fn) {
event.delegateTarget = target; event.delegateTarget = target;
if (handler.oneOff) { if (handler.oneOff) {
// eslint-disable-next-line unicorn/consistent-destructuring
EventHandler.off(element, event.type, selector, fn); EventHandler.off(element, event.type, selector, fn);
} }

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/manipulator.js * Bootstrap (v5.1.3): dom/manipulator.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -64,8 +64,8 @@ const Manipulator = {
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
return { return {
top: rect.top + document.body.scrollTop, top: rect.top + window.pageYOffset,
left: rect.left + document.body.scrollLeft, left: rect.left + window.pageXOffset,
}; };
}, },

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dom/selector-engine.js * Bootstrap (v5.1.3): dom/selector-engine.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -11,6 +11,8 @@
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
import { isDisabled, isVisible } from '../util/index';
const NODE_TEXT = 3; const NODE_TEXT = 3;
const SelectorEngine = { const SelectorEngine = {
@ -69,6 +71,23 @@ const SelectorEngine = {
return []; return [];
}, },
focusableChildren(element) {
const focusables = [
'a',
'button',
'input',
'textarea',
'select',
'details',
'[tabindex]',
'[contenteditable="true"]',
]
.map((selector) => `${selector}:not([tabindex^="-"])`)
.join(', ');
return this.find(focusables, element).filter((el) => !isDisabled(el) && isVisible(el));
},
}; };
export default SelectorEngine; export default SelectorEngine;

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): dropdown.js * Bootstrap (v5.1.3): dropdown.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -11,14 +11,14 @@ import {
defineJQueryPlugin, defineJQueryPlugin,
getElement, getElement,
getElementFromSelector, getElementFromSelector,
getNextActiveElement,
isDisabled, isDisabled,
isElement, isElement,
isVisible,
isRTL, isRTL,
isVisible,
noop, noop,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
@ -48,7 +48,6 @@ const EVENT_HIDE = `hide${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_CLICK = `click${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`;
@ -103,8 +102,6 @@ class Dropdown extends BaseComponent {
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._menu = this._getMenuElement(); this._menu = this._getMenuElement();
this._inNavbar = this._detectNavbar(); this._inNavbar = this._detectNavbar();
this._addEventListeners();
} }
// Getters // Getters
@ -124,26 +121,14 @@ class Dropdown extends BaseComponent {
// Public // Public
toggle() { toggle() {
if (isDisabled(this._element)) { return this._isShown() ? this.hide() : this.show();
return;
}
const isActive = this._element.classList.contains(CLASS_NAME_SHOW);
if (isActive) {
this.hide();
return;
}
this.show();
} }
show() { show() {
if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW)) { if (isDisabled(this._element) || this._isShown(this._menu)) {
return; return;
} }
const parent = Dropdown.getParentFromElement(this._element);
const relatedTarget = { const relatedTarget = {
relatedTarget: this._element, relatedTarget: this._element,
}; };
@ -154,34 +139,12 @@ class Dropdown extends BaseComponent {
return; return;
} }
const parent = Dropdown.getParentFromElement(this._element);
// Totally disable Popper for Dropdowns in Navbar // Totally disable Popper for Dropdowns in Navbar
if (this._inNavbar) { if (this._inNavbar) {
Manipulator.setDataAttribute(this._menu, 'popper', 'none'); Manipulator.setDataAttribute(this._menu, 'popper', 'none');
} else { } else {
if (typeof Popper === 'undefined') { this._createPopper(parent);
throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");
}
let referenceElement = this._element;
if (this._config.reference === 'parent') {
referenceElement = parent;
} else if (isElement(this._config.reference)) {
referenceElement = getElement(this._config.reference);
} else if (typeof this._config.reference === 'object') {
referenceElement = this._config.reference;
}
const popperConfig = this._getPopperConfig();
const isDisplayStatic = popperConfig.modifiers.find(
(modifier) => modifier.name === 'applyStyles' && modifier.enabled === false
);
this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig);
if (isDisplayStatic) {
Manipulator.setDataAttribute(this._menu, 'popper', 'static');
}
} }
// If this is a touch-enabled device we add extra // If this is a touch-enabled device we add extra
@ -197,13 +160,13 @@ class Dropdown extends BaseComponent {
this._element.focus(); this._element.focus();
this._element.setAttribute('aria-expanded', true); this._element.setAttribute('aria-expanded', true);
this._menu.classList.toggle(CLASS_NAME_SHOW); this._menu.classList.add(CLASS_NAME_SHOW);
this._element.classList.toggle(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget); EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget);
} }
hide() { hide() {
if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW)) { if (isDisabled(this._element) || !this._isShown(this._menu)) {
return; return;
} }
@ -231,13 +194,6 @@ class Dropdown extends BaseComponent {
// Private // Private
_addEventListeners() {
EventHandler.on(this._element, EVENT_CLICK, (event) => {
event.preventDefault();
this.toggle();
});
}
_completeHide(relatedTarget) { _completeHide(relatedTarget) {
const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget); const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget);
if (hideEvent.defaultPrevented) { if (hideEvent.defaultPrevented) {
@ -286,6 +242,37 @@ class Dropdown extends BaseComponent {
return config; return config;
} }
_createPopper(parent) {
if (typeof Popper === 'undefined') {
throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");
}
let referenceElement = this._element;
if (this._config.reference === 'parent') {
referenceElement = parent;
} else if (isElement(this._config.reference)) {
referenceElement = getElement(this._config.reference);
} else if (typeof this._config.reference === 'object') {
referenceElement = this._config.reference;
}
const popperConfig = this._getPopperConfig();
const isDisplayStatic = popperConfig.modifiers.find(
(modifier) => modifier.name === 'applyStyles' && modifier.enabled === false
);
this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig);
if (isDisplayStatic) {
Manipulator.setDataAttribute(this._menu, 'popper', 'static');
}
}
_isShown(element = this._element) {
return element.classList.contains(CLASS_NAME_SHOW);
}
_getMenuElement() { _getMenuElement() {
return SelectorEngine.next(this._element, SELECTOR_MENU)[0]; return SelectorEngine.next(this._element, SELECTOR_MENU)[0];
} }
@ -366,53 +353,33 @@ class Dropdown extends BaseComponent {
}; };
} }
_selectMenuItem(event) { _selectMenuItem({ key, target }) {
const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible); const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible);
if (!items.length) { if (!items.length) {
return; return;
} }
let index = items.indexOf(event.target); // if target isn't included in items (e.g. when expanding the dropdown)
// allow cycling to get the last item in case key equals ARROW_UP_KEY
// Up getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
if (event.key === ARROW_UP_KEY && index > 0) {
index--;
}
// Down
if (event.key === ARROW_DOWN_KEY && index < items.length - 1) {
index++;
}
// index is -1 if the first keydown is an ArrowUp
index = index === -1 ? 0 : index;
items[index].focus();
} }
// Static // Static
static dropdownInterface(element, config) { static jQueryInterface(config) {
let data = Data.get(element, DATA_KEY); return this.each(function () {
const _config = typeof config === 'object' ? config : null; const data = Dropdown.getOrCreateInstance(this, config);
if (!data) { if (typeof config !== 'string') {
data = new Dropdown(element, _config); return;
} }
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`); throw new TypeError(`No method named "${config}"`);
} }
data[config](); data[config]();
}
}
static jQueryInterface(config) {
return this.each(function () {
Dropdown.dropdownInterface(this, config);
}); });
} }
@ -427,12 +394,12 @@ class Dropdown extends BaseComponent {
const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE); const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE);
for (let i = 0, len = toggles.length; i < len; i++) { for (let i = 0, len = toggles.length; i < len; i++) {
const context = Data.get(toggles[i], DATA_KEY); const context = Dropdown.getInstance(toggles[i]);
if (!context || context._config.autoClose === false) { if (!context || context._config.autoClose === false) {
continue; continue;
} }
if (!context._element.classList.contains(CLASS_NAME_SHOW)) { if (!context._isShown()) {
continue; continue;
} }
@ -505,28 +472,28 @@ class Dropdown extends BaseComponent {
return; return;
} }
const getToggleButton = () => const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE)
this.matches(SELECTOR_DATA_TOGGLE)
? this ? this
: SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0]; : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0];
const instance = Dropdown.getOrCreateInstance(getToggleButton);
if (event.key === ESCAPE_KEY) { if (event.key === ESCAPE_KEY) {
getToggleButton().focus(); instance.hide();
Dropdown.clearMenus();
return; return;
} }
if (!isActive && (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY)) { if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {
getToggleButton().click(); if (!isActive) {
instance.show();
}
instance._selectMenuItem(event);
return; return;
} }
if (!isActive || event.key === SPACE_KEY) { if (!isActive || event.key === SPACE_KEY) {
Dropdown.clearMenus(); Dropdown.clearMenus();
return;
} }
Dropdown.getInstance(getToggleButton())._selectMenuItem(event);
} }
} }
@ -547,7 +514,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus);
EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
event.preventDefault(); event.preventDefault();
Dropdown.dropdownInterface(this); Dropdown.getOrCreateInstance(this).toggle();
}); });
/** /**

View File

@ -1,15 +1,13 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): modal.js * Bootstrap (v5.1.3): modal.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { import {
defineJQueryPlugin, defineJQueryPlugin,
emulateTransitionEnd,
getElementFromSelector, getElementFromSelector,
getTransitionDurationFromElement,
isRTL, isRTL,
isVisible, isVisible,
reflow, reflow,
@ -18,13 +16,11 @@ import {
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
import { import ScrollBarHelper from './util/scrollbar';
getWidth as getScrollBarWidth,
hide as scrollBarHide,
reset as scrollBarReset,
} from './util/scrollbar';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import Backdrop from './util/backdrop'; import Backdrop from './util/backdrop';
import FocusTrap from './util/focustrap';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -55,7 +51,6 @@ const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_RESIZE = `resize${EVENT_KEY}`; const EVENT_RESIZE = `resize${EVENT_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`; const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
@ -68,10 +63,10 @@ const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_STATIC = 'modal-static'; const CLASS_NAME_STATIC = 'modal-static';
const OPEN_SELECTOR = '.modal.show';
const SELECTOR_DIALOG = '.modal-dialog'; const SELECTOR_DIALOG = '.modal-dialog';
const SELECTOR_MODAL_BODY = '.modal-body'; const SELECTOR_MODAL_BODY = '.modal-body';
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]'; const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]';
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -86,9 +81,11 @@ class Modal extends BaseComponent {
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element);
this._backdrop = this._initializeBackDrop(); this._backdrop = this._initializeBackDrop();
this._focustrap = this._initializeFocusTrap();
this._isShown = false; this._isShown = false;
this._ignoreBackdropClick = false; this._ignoreBackdropClick = false;
this._isTransitioning = false; this._isTransitioning = false;
this._scrollBar = new ScrollBarHelper();
} }
// Getters // Getters
@ -112,21 +109,21 @@ class Modal extends BaseComponent {
return; return;
} }
if (this._isAnimated()) {
this._isTransitioning = true;
}
const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, {
relatedTarget, relatedTarget,
}); });
if (this._isShown || showEvent.defaultPrevented) { if (showEvent.defaultPrevented) {
return; return;
} }
this._isShown = true; this._isShown = true;
scrollBarHide(); if (this._isAnimated()) {
this._isTransitioning = true;
}
this._scrollBar.hide();
document.body.classList.add(CLASS_NAME_OPEN); document.body.classList.add(CLASS_NAME_OPEN);
@ -135,10 +132,6 @@ class Modal extends BaseComponent {
this._setEscapeEvent(); this._setEscapeEvent();
this._setResizeEvent(); this._setResizeEvent();
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, (event) =>
this.hide(event)
);
EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => {
EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, (event) => { EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, (event) => {
if (event.target === this._element) { if (event.target === this._element) {
@ -150,11 +143,7 @@ class Modal extends BaseComponent {
this._showBackdrop(() => this._showElement(relatedTarget)); this._showBackdrop(() => this._showElement(relatedTarget));
} }
hide(event) { hide() {
if (event) {
event.preventDefault();
}
if (!this._isShown || this._isTransitioning) { if (!this._isShown || this._isTransitioning) {
return; return;
} }
@ -175,7 +164,7 @@ class Modal extends BaseComponent {
this._setEscapeEvent(); this._setEscapeEvent();
this._setResizeEvent(); this._setResizeEvent();
EventHandler.off(document, EVENT_FOCUSIN); this._focustrap.deactivate();
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_SHOW);
@ -189,14 +178,8 @@ class Modal extends BaseComponent {
[window, this._dialog].forEach((htmlElement) => EventHandler.off(htmlElement, EVENT_KEY)); [window, this._dialog].forEach((htmlElement) => EventHandler.off(htmlElement, EVENT_KEY));
this._backdrop.dispose(); this._backdrop.dispose();
this._focustrap.deactivate();
super.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
*/
EventHandler.off(document, EVENT_FOCUSIN);
} }
handleUpdate() { handleUpdate() {
@ -212,11 +195,17 @@ class Modal extends BaseComponent {
}); });
} }
_initializeFocusTrap() {
return new FocusTrap({
trapElement: this._element,
});
}
_getConfig(config) { _getConfig(config) {
config = { config = {
...Default, ...Default,
...Manipulator.getDataAttributes(this._element), ...Manipulator.getDataAttributes(this._element),
...config, ...(typeof config === 'object' ? config : {}),
}; };
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
@ -228,7 +217,7 @@ class Modal extends BaseComponent {
if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
// Don't move modal's DOM position // Don't move modal's DOM position
document.body.appendChild(this._element); document.body.append(this._element);
} }
this._element.style.display = 'block'; this._element.style.display = 'block';
@ -247,13 +236,9 @@ class Modal extends BaseComponent {
this._element.classList.add(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
if (this._config.focus) {
this._enforceFocus();
}
const transitionComplete = () => { const transitionComplete = () => {
if (this._config.focus) { if (this._config.focus) {
this._element.focus(); this._focustrap.activate();
} }
this._isTransitioning = false; this._isTransitioning = false;
@ -265,19 +250,6 @@ class Modal extends BaseComponent {
this._queueCallback(transitionComplete, this._dialog, isAnimated); 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() { _setEscapeEvent() {
if (this._isShown) { if (this._isShown) {
EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => {
@ -310,7 +282,7 @@ class Modal extends BaseComponent {
this._backdrop.hide(() => { this._backdrop.hide(() => {
document.body.classList.remove(CLASS_NAME_OPEN); document.body.classList.remove(CLASS_NAME_OPEN);
this._resetAdjustments(); this._resetAdjustments();
scrollBarReset(); this._scrollBar.reset();
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
}); });
} }
@ -346,25 +318,31 @@ class Modal extends BaseComponent {
return; return;
} }
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const { classList, scrollHeight, style } = this._element;
const isModalOverflowing = scrollHeight > document.documentElement.clientHeight;
if (!isModalOverflowing) { // return if the following background transition hasn't yet completed
this._element.style.overflowY = 'hidden'; if (
(!isModalOverflowing && style.overflowY === 'hidden') ||
classList.contains(CLASS_NAME_STATIC)
) {
return;
} }
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);
if (!isModalOverflowing) { if (!isModalOverflowing) {
EventHandler.one(this._element, 'transitionend', () => { style.overflowY = 'hidden';
this._element.style.overflowY = '';
});
emulateTransitionEnd(this._element, modalTransitionDuration);
} }
});
emulateTransitionEnd(this._element, modalTransitionDuration); classList.add(CLASS_NAME_STATIC);
this._queueCallback(() => {
classList.remove(CLASS_NAME_STATIC);
if (!isModalOverflowing) {
this._queueCallback(() => {
style.overflowY = '';
}, this._dialog);
}
}, this._dialog);
this._element.focus(); this._element.focus();
} }
@ -374,7 +352,7 @@ class Modal extends BaseComponent {
_adjustDialog() { _adjustDialog() {
const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
const scrollbarWidth = getScrollBarWidth(); const scrollbarWidth = this._scrollBar.getWidth();
const isBodyOverflowing = scrollbarWidth > 0; const isBodyOverflowing = scrollbarWidth > 0;
if ( if (
@ -401,8 +379,7 @@ class Modal extends BaseComponent {
static jQueryInterface(config, relatedTarget) { static jQueryInterface(config, relatedTarget) {
return this.each(function () { return this.each(function () {
const data = const data = Modal.getOrCreateInstance(this, config);
Modal.getInstance(this) || new Modal(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -443,11 +420,19 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
}); });
}); });
const data = Modal.getInstance(target) || new Modal(target); // 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); data.toggle(this);
}); });
enableDismissTrigger(Modal);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

View File

@ -1,7 +1,7 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): offcanvas.js * Bootstrap (v5.1.3): offcanvas.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -12,13 +12,14 @@ import {
isVisible, isVisible,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import { hide as scrollBarHide, reset as scrollBarReset } from './util/scrollbar'; import ScrollBarHelper from './util/scrollbar';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import Backdrop from './util/backdrop'; import Backdrop from './util/backdrop';
import FocusTrap from './util/focustrap';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -46,18 +47,16 @@ const DefaultType = {
}; };
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
const OPEN_SELECTOR = '.offcanvas.show'; const OPEN_SELECTOR = '.offcanvas.show';
const EVENT_SHOW = `show${EVENT_KEY}`; const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const EVENT_HIDE = `hide${EVENT_KEY}`; const EVENT_HIDE = `hide${EVENT_KEY}`;
const EVENT_HIDDEN = `hidden${EVENT_KEY}`; const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]';
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]'; const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]';
/** /**
@ -73,6 +72,7 @@ class Offcanvas extends BaseComponent {
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._isShown = false; this._isShown = false;
this._backdrop = this._initializeBackDrop(); this._backdrop = this._initializeBackDrop();
this._focustrap = this._initializeFocusTrap();
this._addEventListeners(); this._addEventListeners();
} }
@ -109,8 +109,7 @@ class Offcanvas extends BaseComponent {
this._backdrop.show(); this._backdrop.show();
if (!this._config.scroll) { if (!this._config.scroll) {
scrollBarHide(); new ScrollBarHelper().hide();
this._enforceFocusOnElement(this._element);
} }
this._element.removeAttribute('aria-hidden'); this._element.removeAttribute('aria-hidden');
@ -119,6 +118,10 @@ class Offcanvas extends BaseComponent {
this._element.classList.add(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOW);
const completeCallBack = () => { const completeCallBack = () => {
if (!this._config.scroll) {
this._focustrap.activate();
}
EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget }); EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget });
}; };
@ -136,7 +139,7 @@ class Offcanvas extends BaseComponent {
return; return;
} }
EventHandler.off(document, EVENT_FOCUSIN); this._focustrap.deactivate();
this._element.blur(); this._element.blur();
this._isShown = false; this._isShown = false;
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.remove(CLASS_NAME_SHOW);
@ -149,7 +152,7 @@ class Offcanvas extends BaseComponent {
this._element.style.visibility = 'hidden'; this._element.style.visibility = 'hidden';
if (!this._config.scroll) { if (!this._config.scroll) {
scrollBarReset(); new ScrollBarHelper().reset();
} }
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
@ -160,8 +163,8 @@ class Offcanvas extends BaseComponent {
dispose() { dispose() {
this._backdrop.dispose(); this._backdrop.dispose();
this._focustrap.deactivate();
super.dispose(); super.dispose();
EventHandler.off(document, EVENT_FOCUSIN);
} }
// Private // Private
@ -178,6 +181,7 @@ class Offcanvas extends BaseComponent {
_initializeBackDrop() { _initializeBackDrop() {
return new Backdrop({ return new Backdrop({
className: CLASS_NAME_BACKDROP,
isVisible: this._config.backdrop, isVisible: this._config.backdrop,
isAnimated: true, isAnimated: true,
rootElement: this._element.parentNode, rootElement: this._element.parentNode,
@ -185,23 +189,13 @@ class Offcanvas extends BaseComponent {
}); });
} }
_enforceFocusOnElement(element) { _initializeFocusTrap() {
EventHandler.off(document, EVENT_FOCUSIN); // guard against infinite focus loop return new FocusTrap({
EventHandler.on(document, EVENT_FOCUSIN, (event) => { trapElement: this._element,
if (
document !== event.target &&
element !== event.target &&
!element.contains(event.target)
) {
element.focus();
}
}); });
element.focus();
} }
_addEventListeners() { _addEventListeners() {
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, (event) => {
if (this._config.keyboard && event.key === ESCAPE_KEY) { if (this._config.keyboard && event.key === ESCAPE_KEY) {
this.hide(); this.hide();
@ -213,8 +207,7 @@ class Offcanvas extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = const data = Offcanvas.getOrCreateInstance(this, config);
Data.get(this, DATA_KEY) || new Offcanvas(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;
@ -259,17 +252,15 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
Offcanvas.getInstance(allReadyOpen).hide(); Offcanvas.getInstance(allReadyOpen).hide();
} }
const data = Data.get(target, DATA_KEY) || new Offcanvas(target); const data = Offcanvas.getOrCreateInstance(target);
data.toggle(this); data.toggle(this);
}); });
EventHandler.on(window, EVENT_LOAD_DATA_API, () => { EventHandler.on(window, EVENT_LOAD_DATA_API, () =>
SelectorEngine.find(OPEN_SELECTOR).forEach((el) => SelectorEngine.find(OPEN_SELECTOR).forEach((el) => Offcanvas.getOrCreateInstance(el).show())
(Data.get(el, DATA_KEY) || new Offcanvas(el)).show()
); );
});
enableDismissTrigger(Offcanvas);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

View File

@ -1,13 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): popover.js * Bootstrap (v5.1.3): popover.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin } from './util/index'; import { defineJQueryPlugin } from './util/index';
import Data from './dom/data';
import SelectorEngine from './dom/selector-engine';
import Tooltip from './tooltip'; import Tooltip from './tooltip';
/** /**
@ -20,7 +18,6 @@ const NAME = 'popover';
const DATA_KEY = 'bs.popover'; const DATA_KEY = 'bs.popover';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const CLASS_PREFIX = 'bs-popover'; const CLASS_PREFIX = 'bs-popover';
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g');
const Default = { const Default = {
...Tooltip.Default, ...Tooltip.Default,
@ -54,9 +51,6 @@ const Event = {
MOUSELEAVE: `mouseleave${EVENT_KEY}`, MOUSELEAVE: `mouseleave${EVENT_KEY}`,
}; };
const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show';
const SELECTOR_TITLE = '.popover-header'; const SELECTOR_TITLE = '.popover-header';
const SELECTOR_CONTENT = '.popover-body'; const SELECTOR_CONTENT = '.popover-body';
@ -91,54 +85,26 @@ class Popover extends Tooltip {
return this.getTitle() || this._getContent(); return this.getTitle() || this._getContent();
} }
setContent() { setContent(tip) {
const tip = this.getTipElement(); this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TITLE);
this._sanitizeAndSetContent(tip, this._getContent(), SELECTOR_CONTENT);
// we use append for html objects to maintain js events
this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle());
let content = this._getContent();
if (typeof content === 'function') {
content = content.call(this._element);
}
this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content);
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
} }
// Private // Private
_addAttachmentClass(attachment) {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`);
}
_getContent() { _getContent() {
return this._element.getAttribute('data-bs-content') || this._config.content; return this._resolvePossibleFunction(this._config.content);
} }
_cleanTipClass() { _getBasicClassPrefix() {
const tip = this.getTipElement(); return CLASS_PREFIX;
const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX);
if (tabClass !== null && tabClass.length > 0) {
tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass));
}
} }
// Static // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Popover.getOrCreateInstance(this, config);
const _config = typeof config === 'object' ? config : null;
if (!data && /dispose|hide/.test(config)) {
return;
}
if (!data) {
data = new Popover(this, _config);
Data.set(this, DATA_KEY, data);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {

View File

@ -1,15 +1,14 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): scrollspy.js * Bootstrap (v5.1.3): scrollspy.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { import {
defineJQueryPlugin, defineJQueryPlugin,
getElement,
getSelectorFromElement, getSelectorFromElement,
getUID,
isElement,
typeCheckConfig, typeCheckConfig,
} from './util/index'; } from './util/index';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
@ -52,6 +51,7 @@ const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
const SELECTOR_NAV_LINKS = '.nav-link'; const SELECTOR_NAV_LINKS = '.nav-link';
const SELECTOR_NAV_ITEMS = '.nav-item'; const SELECTOR_NAV_ITEMS = '.nav-item';
const SELECTOR_LIST_ITEMS = '.list-group-item'; const SELECTOR_LIST_ITEMS = '.list-group-item';
const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}, .${CLASS_NAME_DROPDOWN_ITEM}`;
const SELECTOR_DROPDOWN = '.dropdown'; const SELECTOR_DROPDOWN = '.dropdown';
const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'; const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
@ -69,7 +69,6 @@ class ScrollSpy extends BaseComponent {
super(element); super(element);
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element; this._scrollElement = this._element.tagName === 'BODY' ? window : this._element;
this._config = this._getConfig(config); this._config = this._getConfig(config);
this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`;
this._offsets = []; this._offsets = [];
this._targets = []; this._targets = [];
this._activeTarget = null; this._activeTarget = null;
@ -105,7 +104,7 @@ class ScrollSpy extends BaseComponent {
this._targets = []; this._targets = [];
this._scrollHeight = this._getScrollHeight(); this._scrollHeight = this._getScrollHeight();
const targets = SelectorEngine.find(this._selector); const targets = SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target);
targets targets
.map((element) => { .map((element) => {
@ -143,15 +142,7 @@ class ScrollSpy extends BaseComponent {
...(typeof config === 'object' && config ? config : {}), ...(typeof config === 'object' && config ? config : {}),
}; };
if (typeof config.target !== 'string' && isElement(config.target)) { config.target = getElement(config.target) || document.documentElement;
let { id } = config.target;
if (!id) {
id = getUID(NAME);
config.target.id = id;
}
config.target = `#${id}`;
}
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
@ -219,30 +210,25 @@ class ScrollSpy extends BaseComponent {
this._clear(); this._clear();
const queries = this._selector const queries = SELECTOR_LINK_ITEMS.split(',').map(
.split(',') (selector) => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`
.map((selector) => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`); );
const link = SelectorEngine.findOne(queries.join(',')); const link = SelectorEngine.findOne(queries.join(','), this._config.target);
link.classList.add(CLASS_NAME_ACTIVE);
if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
SelectorEngine.findOne( SelectorEngine.findOne(
SELECTOR_DROPDOWN_TOGGLE, SELECTOR_DROPDOWN_TOGGLE,
link.closest(SELECTOR_DROPDOWN) link.closest(SELECTOR_DROPDOWN)
).classList.add(CLASS_NAME_ACTIVE); ).classList.add(CLASS_NAME_ACTIVE);
link.classList.add(CLASS_NAME_ACTIVE);
} else { } else {
// Set triggered link as active
link.classList.add(CLASS_NAME_ACTIVE);
SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP).forEach((listGroup) => { SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP).forEach((listGroup) => {
// Set triggered links parents as active // Set triggered links parents as active
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
SelectorEngine.prev( SelectorEngine.prev(listGroup, `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`).forEach(
listGroup, (item) => item.classList.add(CLASS_NAME_ACTIVE)
`${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}` );
).forEach((item) => item.classList.add(CLASS_NAME_ACTIVE));
// Handle special case when .nav-link is inside .nav-item // Handle special case when .nav-link is inside .nav-item
SelectorEngine.prev(listGroup, SELECTOR_NAV_ITEMS).forEach((navItem) => { SelectorEngine.prev(listGroup, SELECTOR_NAV_ITEMS).forEach((navItem) => {
@ -259,7 +245,7 @@ class ScrollSpy extends BaseComponent {
} }
_clear() { _clear() {
SelectorEngine.find(this._selector) SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target)
.filter((node) => node.classList.contains(CLASS_NAME_ACTIVE)) .filter((node) => node.classList.contains(CLASS_NAME_ACTIVE))
.forEach((node) => node.classList.remove(CLASS_NAME_ACTIVE)); .forEach((node) => node.classList.remove(CLASS_NAME_ACTIVE));
} }
@ -268,9 +254,7 @@ class ScrollSpy extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = const data = ScrollSpy.getOrCreateInstance(this, config);
ScrollSpy.getInstance(this) ||
new ScrollSpy(this, typeof config === 'object' ? config : {});
if (typeof config !== 'string') { if (typeof config !== 'string') {
return; return;

View File

@ -1,12 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): tab.js * Bootstrap (v5.1.3): tab.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin, getElementFromSelector, isDisabled, reflow } from './util/index'; import { defineJQueryPlugin, getElementFromSelector, isDisabled, reflow } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import SelectorEngine from './dom/selector-engine'; import SelectorEngine from './dom/selector-engine';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
@ -187,7 +186,7 @@ class Tab extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
const data = Data.get(this, DATA_KEY) || new Tab(this); const data = Tab.getOrCreateInstance(this);
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -215,7 +214,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
return; return;
} }
const data = Data.get(this, DATA_KEY) || new Tab(this); const data = Tab.getOrCreateInstance(this);
data.show(); data.show();
}); });

View File

@ -1,15 +1,15 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): toast.js * Bootstrap (v5.1.3): toast.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import { defineJQueryPlugin, reflow, typeCheckConfig } from './util/index'; import { defineJQueryPlugin, reflow, typeCheckConfig } from './util/index';
import Data from './dom/data';
import EventHandler from './dom/event-handler'; import EventHandler from './dom/event-handler';
import Manipulator from './dom/manipulator'; import Manipulator from './dom/manipulator';
import BaseComponent from './base-component'; import BaseComponent from './base-component';
import { enableDismissTrigger } from './util/component-functions';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
@ -21,7 +21,6 @@ const NAME = 'toast';
const DATA_KEY = 'bs.toast'; const DATA_KEY = 'bs.toast';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`; const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;
const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`; const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`; const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
@ -32,7 +31,7 @@ const EVENT_SHOW = `show${EVENT_KEY}`;
const EVENT_SHOWN = `shown${EVENT_KEY}`; const EVENT_SHOWN = `shown${EVENT_KEY}`;
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_HIDE = 'hide'; const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
const CLASS_NAME_SHOWING = 'showing'; const CLASS_NAME_SHOWING = 'showing';
@ -48,8 +47,6 @@ const Default = {
delay: 5000, delay: 5000,
}; };
const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="toast"]';
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* Class Definition * Class Definition
@ -98,15 +95,14 @@ class Toast extends BaseComponent {
const complete = () => { const complete = () => {
this._element.classList.remove(CLASS_NAME_SHOWING); this._element.classList.remove(CLASS_NAME_SHOWING);
this._element.classList.add(CLASS_NAME_SHOW);
EventHandler.trigger(this._element, EVENT_SHOWN); EventHandler.trigger(this._element, EVENT_SHOWN);
this._maybeScheduleHide(); this._maybeScheduleHide();
}; };
this._element.classList.remove(CLASS_NAME_HIDE); this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated
reflow(this._element); reflow(this._element);
this._element.classList.add(CLASS_NAME_SHOW);
this._element.classList.add(CLASS_NAME_SHOWING); this._element.classList.add(CLASS_NAME_SHOWING);
this._queueCallback(complete, this._element, this._config.animation); this._queueCallback(complete, this._element, this._config.animation);
@ -124,11 +120,13 @@ class Toast extends BaseComponent {
} }
const complete = () => { const complete = () => {
this._element.classList.add(CLASS_NAME_HIDE); this._element.classList.add(CLASS_NAME_HIDE); // @deprecated
this._element.classList.remove(CLASS_NAME_SHOWING);
this._element.classList.remove(CLASS_NAME_SHOW);
EventHandler.trigger(this._element, EVENT_HIDDEN); EventHandler.trigger(this._element, EVENT_HIDDEN);
}; };
this._element.classList.remove(CLASS_NAME_SHOW); this._element.classList.add(CLASS_NAME_SHOWING);
this._queueCallback(complete, this._element, this._config.animation); this._queueCallback(complete, this._element, this._config.animation);
} }
@ -198,7 +196,6 @@ class Toast extends BaseComponent {
} }
_setListeners() { _setListeners() {
EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
EventHandler.on(this._element, EVENT_MOUSEOVER, (event) => this._onInteraction(event, true)); EventHandler.on(this._element, EVENT_MOUSEOVER, (event) => this._onInteraction(event, true));
EventHandler.on(this._element, EVENT_MOUSEOUT, (event) => this._onInteraction(event, false)); EventHandler.on(this._element, EVENT_MOUSEOUT, (event) => this._onInteraction(event, false));
EventHandler.on(this._element, EVENT_FOCUSIN, (event) => this._onInteraction(event, true)); EventHandler.on(this._element, EVENT_FOCUSIN, (event) => this._onInteraction(event, true));
@ -214,12 +211,7 @@ class Toast extends BaseComponent {
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Toast.getOrCreateInstance(this, config);
const _config = typeof config === 'object' && config;
if (!data) {
data = new Toast(this, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {
@ -232,6 +224,8 @@ class Toast extends BaseComponent {
} }
} }
enableDismissTrigger(Toast);
/** /**
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
* jQuery * jQuery

View File

@ -1,6 +1,6 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): tooltip.js * Bootstrap (v5.1.3): tooltip.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -34,7 +34,6 @@ const NAME = 'tooltip';
const DATA_KEY = 'bs.tooltip'; const DATA_KEY = 'bs.tooltip';
const EVENT_KEY = `.${DATA_KEY}`; const EVENT_KEY = `.${DATA_KEY}`;
const CLASS_PREFIX = 'bs-tooltip'; const CLASS_PREFIX = 'bs-tooltip';
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g');
const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
const DefaultType = { const DefaultType = {
@ -110,6 +109,9 @@ const HOVER_STATE_SHOW = 'show';
const HOVER_STATE_OUT = 'out'; const HOVER_STATE_OUT = 'out';
const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
const EVENT_MODAL_HIDE = 'hide.bs.modal';
const TRIGGER_HOVER = 'hover'; const TRIGGER_HOVER = 'hover';
const TRIGGER_FOCUS = 'focus'; const TRIGGER_FOCUS = 'focus';
@ -205,19 +207,16 @@ class Tooltip extends BaseComponent {
clearTimeout(this._timeout); clearTimeout(this._timeout);
EventHandler.off( EventHandler.off(
this._element.closest(`.${CLASS_NAME_MODAL}`), this._element.closest(SELECTOR_MODAL),
'hide.bs.modal', EVENT_MODAL_HIDE,
this._hideModalHandler this._hideModalHandler
); );
if (this.tip && this.tip.parentNode) { if (this.tip) {
this.tip.parentNode.removeChild(this.tip); this.tip.remove();
}
if (this._popper) {
this._popper.destroy();
} }
this._disposePopper();
super.dispose(); super.dispose();
} }
@ -241,14 +240,24 @@ class Tooltip extends BaseComponent {
return; return;
} }
// A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title`
// This will be removed later in favor of a `setContent` method
if (
this.constructor.NAME === 'tooltip' &&
this.tip &&
this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML
) {
this._disposePopper();
this.tip.remove();
this.tip = null;
}
const tip = this.getTipElement(); const tip = this.getTipElement();
const tipId = getUID(this.constructor.NAME); const tipId = getUID(this.constructor.NAME);
tip.setAttribute('id', tipId); tip.setAttribute('id', tipId);
this._element.setAttribute('aria-describedby', tipId); this._element.setAttribute('aria-describedby', tipId);
this.setContent();
if (this._config.animation) { if (this._config.animation) {
tip.classList.add(CLASS_NAME_FADE); tip.classList.add(CLASS_NAME_FADE);
} }
@ -265,7 +274,7 @@ class Tooltip extends BaseComponent {
Data.set(tip, this.constructor.DATA_KEY, this); Data.set(tip, this.constructor.DATA_KEY, this);
if (!this._element.ownerDocument.documentElement.contains(this.tip)) { if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip); container.append(tip);
EventHandler.trigger(this._element, this.constructor.Event.INSERTED); EventHandler.trigger(this._element, this.constructor.Event.INSERTED);
} }
@ -277,10 +286,7 @@ class Tooltip extends BaseComponent {
tip.classList.add(CLASS_NAME_SHOW); tip.classList.add(CLASS_NAME_SHOW);
const customClass = const customClass = this._resolvePossibleFunction(this._config.customClass);
typeof this._config.customClass === 'function'
? this._config.customClass()
: this._config.customClass;
if (customClass) { if (customClass) {
tip.classList.add(...customClass.split(' ')); tip.classList.add(...customClass.split(' '));
} }
@ -321,18 +327,15 @@ class Tooltip extends BaseComponent {
return; return;
} }
if (this._hoverState !== HOVER_STATE_SHOW && tip.parentNode) { if (this._hoverState !== HOVER_STATE_SHOW) {
tip.parentNode.removeChild(tip); tip.remove();
} }
this._cleanTipClass(); this._cleanTipClass();
this._element.removeAttribute('aria-describedby'); this._element.removeAttribute('aria-describedby');
EventHandler.trigger(this._element, this.constructor.Event.HIDDEN); EventHandler.trigger(this._element, this.constructor.Event.HIDDEN);
if (this._popper) { this._disposePopper();
this._popper.destroy();
this._popper = null;
}
}; };
const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE); const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE);
@ -379,14 +382,28 @@ class Tooltip extends BaseComponent {
const element = document.createElement('div'); const element = document.createElement('div');
element.innerHTML = this._config.template; element.innerHTML = this._config.template;
this.tip = element.children[0]; const tip = element.children[0];
this.setContent(tip);
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
this.tip = tip;
return this.tip; return this.tip;
} }
setContent() { setContent(tip) {
const tip = this.getTipElement(); this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER);
this.setElementContent(SelectorEngine.findOne(SELECTOR_TOOLTIP_INNER, tip), this.getTitle()); }
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
_sanitizeAndSetContent(template, content, selector) {
const templateElement = SelectorEngine.findOne(selector, template);
if (!content && templateElement) {
templateElement.remove();
return;
}
// we use append for html objects to maintain js events
this.setElementContent(templateElement, content);
} }
setElementContent(element, content) { setElementContent(element, content) {
@ -401,7 +418,7 @@ class Tooltip extends BaseComponent {
if (this._config.html) { if (this._config.html) {
if (content.parentNode !== element) { if (content.parentNode !== element) {
element.innerHTML = ''; element.innerHTML = '';
element.appendChild(content); element.append(content);
} }
} else { } else {
element.textContent = content.textContent; element.textContent = content.textContent;
@ -422,16 +439,9 @@ class Tooltip extends BaseComponent {
} }
getTitle() { getTitle() {
let title = this._element.getAttribute('data-bs-original-title'); const title = this._element.getAttribute('data-bs-original-title') || this._config.title;
if (!title) { return this._resolvePossibleFunction(title);
title =
typeof this._config.title === 'function'
? this._config.title.call(this._element)
: this._config.title;
}
return title;
} }
updateAttachment(attachment) { updateAttachment(attachment) {
@ -449,15 +459,10 @@ class Tooltip extends BaseComponent {
// Private // Private
_initializeOnDelegatedTarget(event, context) { _initializeOnDelegatedTarget(event, context) {
const dataKey = this.constructor.DATA_KEY; return (
context = context || Data.get(event.delegateTarget, dataKey); context ||
this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig())
if (!context) { );
context = new this.constructor(event.delegateTarget, this._getDelegateConfig());
Data.set(event.delegateTarget, dataKey, context);
}
return context;
} }
_getOffset() { _getOffset() {
@ -474,6 +479,10 @@ class Tooltip extends BaseComponent {
return offset; return offset;
} }
_resolvePossibleFunction(content) {
return typeof content === 'function' ? content.call(this._element) : content;
}
_getPopperConfig(attachment) { _getPopperConfig(attachment) {
const defaultBsPopperConfig = { const defaultBsPopperConfig = {
placement: attachment, placement: attachment,
@ -525,7 +534,9 @@ class Tooltip extends BaseComponent {
} }
_addAttachmentClass(attachment) { _addAttachmentClass(attachment) {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`); this.getTipElement().classList.add(
`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`
);
} }
_getAttachment(placement) { _getAttachment(placement) {
@ -569,8 +580,8 @@ class Tooltip extends BaseComponent {
}; };
EventHandler.on( EventHandler.on(
this._element.closest(`.${CLASS_NAME_MODAL}`), this._element.closest(SELECTOR_MODAL),
'hide.bs.modal', EVENT_MODAL_HIDE,
this._hideModalHandler this._hideModalHandler
); );
@ -634,9 +645,8 @@ class Tooltip extends BaseComponent {
context = this._initializeOnDelegatedTarget(event, context); context = this._initializeOnDelegatedTarget(event, context);
if (event) { if (event) {
context._activeTrigger[ context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] =
event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER context._element.contains(event.relatedTarget);
] = context._element.contains(event.relatedTarget);
} }
if (context._isWithActiveTrigger()) { if (context._isWithActiveTrigger()) {
@ -713,25 +723,31 @@ class Tooltip extends BaseComponent {
_getDelegateConfig() { _getDelegateConfig() {
const config = {}; const config = {};
if (this._config) {
for (const key in this._config) { for (const key in this._config) {
if (this.constructor.Default[key] !== this._config[key]) { if (this.constructor.Default[key] !== this._config[key]) {
config[key] = this._config[key]; config[key] = this._config[key];
} }
} }
}
// In the future can be replaced with:
// const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
// `Object.fromEntries(keysWithDifferentValues)`
return config; return config;
} }
_cleanTipClass() { _cleanTipClass() {
const tip = this.getTipElement(); const tip = this.getTipElement();
const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX); const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g');
const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex);
if (tabClass !== null && tabClass.length > 0) { if (tabClass !== null && tabClass.length > 0) {
tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass)); tabClass.map((token) => token.trim()).forEach((tClass) => tip.classList.remove(tClass));
} }
} }
_getBasicClassPrefix() {
return CLASS_PREFIX;
}
_handlePopperPlacementChange(popperData) { _handlePopperPlacementChange(popperData) {
const { state } = popperData; const { state } = popperData;
@ -744,20 +760,18 @@ class Tooltip extends BaseComponent {
this._addAttachmentClass(this._getAttachment(state.placement)); this._addAttachmentClass(this._getAttachment(state.placement));
} }
_disposePopper() {
if (this._popper) {
this._popper.destroy();
this._popper = null;
}
}
// Static // Static
static jQueryInterface(config) { static jQueryInterface(config) {
return this.each(function () { return this.each(function () {
let data = Data.get(this, DATA_KEY); const data = Tooltip.getOrCreateInstance(this, config);
const _config = typeof config === 'object' && config;
if (!data && /dispose|hide/.test(config)) {
return;
}
if (!data) {
data = new Tooltip(this, _config);
}
if (typeof config === 'string') { if (typeof config === 'string') {
if (typeof data[config] === 'undefined') { if (typeof data[config] === 'undefined') {

View File

@ -1,34 +1,29 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/backdrop.js * Bootstrap (v5.1.3): util/backdrop.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import EventHandler from '../dom/event-handler'; import EventHandler from '../dom/event-handler';
import { import { execute, executeAfterTransition, getElement, reflow, typeCheckConfig } from './index';
emulateTransitionEnd,
execute,
getTransitionDurationFromElement,
reflow,
typeCheckConfig,
} from './index';
const Default = { const Default = {
className: 'modal-backdrop',
isVisible: true, // if false, we use the backdrop helper without adding any element to the dom isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
isAnimated: false, isAnimated: false,
rootElement: document.body, // give the choice to place backdrop under different elements rootElement: 'body', // give the choice to place backdrop under different elements
clickCallback: null, clickCallback: null,
}; };
const DefaultType = { const DefaultType = {
className: 'string',
isVisible: 'boolean', isVisible: 'boolean',
isAnimated: 'boolean', isAnimated: 'boolean',
rootElement: 'element', rootElement: '(element|string)',
clickCallback: '(function|null)', clickCallback: '(function|null)',
}; };
const NAME = 'backdrop'; const NAME = 'backdrop';
const CLASS_NAME_BACKDROP = 'modal-backdrop';
const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_FADE = 'fade';
const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_SHOW = 'show';
@ -79,7 +74,7 @@ class Backdrop {
_getElement() { _getElement() {
if (!this._element) { if (!this._element) {
const backdrop = document.createElement('div'); const backdrop = document.createElement('div');
backdrop.className = CLASS_NAME_BACKDROP; backdrop.className = this._config.className;
if (this._config.isAnimated) { if (this._config.isAnimated) {
backdrop.classList.add(CLASS_NAME_FADE); backdrop.classList.add(CLASS_NAME_FADE);
} }
@ -96,7 +91,8 @@ class Backdrop {
...(typeof config === 'object' ? config : {}), ...(typeof config === 'object' ? config : {}),
}; };
config.rootElement = config.rootElement || document.body; // use getElement() with the default "body" to get a fresh Element on each instantiation
config.rootElement = getElement(config.rootElement);
typeCheckConfig(NAME, config, DefaultType); typeCheckConfig(NAME, config, DefaultType);
return config; return config;
} }
@ -106,7 +102,7 @@ class Backdrop {
return; return;
} }
this._config.rootElement.appendChild(this._getElement()); this._config.rootElement.append(this._getElement());
EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => { EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => {
execute(this._config.clickCallback); execute(this._config.clickCallback);
@ -122,19 +118,12 @@ class Backdrop {
EventHandler.off(this._element, EVENT_MOUSEDOWN); EventHandler.off(this._element, EVENT_MOUSEDOWN);
this._getElement().parentNode.removeChild(this._element); this._element.remove();
this._isAppended = false; this._isAppended = false;
} }
_emulateAnimation(callback) { _emulateAnimation(callback) {
if (!this._config.isAnimated) { executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
execute(callback);
return;
}
const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement());
EventHandler.one(this._getElement(), 'transitionend', () => execute(callback));
emulateTransitionEnd(this._getElement(), backdropTransitionDuration);
} }
} }

View File

@ -0,0 +1,32 @@
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/component-functions.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
import EventHandler from '../dom/event-handler';
import { getElementFromSelector, isDisabled } from './index';
const enableDismissTrigger = (component, method = 'hide') => {
const clickEvent = `click.dismiss${component.EVENT_KEY}`;
const name = component.NAME;
EventHandler.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]();
});
};
export { enableDismissTrigger };

View File

@ -0,0 +1,105 @@
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.1.3): util/focustrap.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
import EventHandler from '../dom/event-handler';
import SelectorEngine from '../dom/selector-engine';
import { typeCheckConfig } from './index';
const Default = {
trapElement: null, // The element to trap focus inside of
autofocus: true,
};
const DefaultType = {
trapElement: 'element',
autofocus: 'boolean',
};
const NAME = 'focustrap';
const DATA_KEY = 'bs.focustrap';
const EVENT_KEY = `.${DATA_KEY}`;
const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY}`;
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.off(document, EVENT_KEY); // guard against infinite focus loop
EventHandler.on(document, EVENT_FOCUSIN, (event) => this._handleFocusin(event));
EventHandler.on(document, EVENT_KEYDOWN_TAB, (event) => this._handleKeydown(event));
this._isActive = true;
}
deactivate() {
if (!this._isActive) {
return;
}
this._isActive = false;
EventHandler.off(document, EVENT_KEY);
}
// Private
_handleFocusin(event) {
const { target } = event;
const { trapElement } = this._config;
if (target === document || target === trapElement || trapElement.contains(target)) {
return;
}
const elements = SelectorEngine.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,
...(typeof config === 'object' ? config : {}),
};
typeCheckConfig(NAME, config, DefaultType);
return config;
}
}
export default FocusTrap;

View File

@ -1,8 +1,6 @@
import SelectorEngine from '../dom/selector-engine';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/index.js * Bootstrap (v5.1.3): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
@ -127,30 +125,12 @@ const getElement = (obj) => {
} }
if (typeof obj === 'string' && obj.length > 0) { if (typeof obj === 'string' && obj.length > 0) {
return SelectorEngine.findOne(obj); return document.querySelector(obj);
} }
return null; return null;
}; };
const emulateTransitionEnd = (element, duration) => {
let called = false;
const durationPadding = 5;
const emulatedDuration = duration + durationPadding;
function listener() {
called = true;
element.removeEventListener(TRANSITION_END, listener);
}
element.addEventListener(TRANSITION_END, listener);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(element);
}
}, emulatedDuration);
};
const typeCheckConfig = (componentName, config, configTypes) => { const typeCheckConfig = (componentName, config, configTypes) => {
Object.keys(configTypes).forEach((property) => { Object.keys(configTypes).forEach((property) => {
const expectedTypes = configTypes[property]; const expectedTypes = configTypes[property];
@ -166,22 +146,11 @@ const typeCheckConfig = (componentName, config, configTypes) => {
}; };
const isVisible = (element) => { const isVisible = (element) => {
if (!element) { if (!isElement(element) || element.getClientRects().length === 0) {
return false; return false;
} }
if (element.style && element.parentNode && element.parentNode.style) { return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
const elementStyle = getComputedStyle(element);
const parentNodeStyle = getComputedStyle(element.parentNode);
return (
elementStyle.display !== 'none' &&
parentNodeStyle.display !== 'none' &&
elementStyle.visibility !== 'hidden'
);
}
return false;
}; };
const isDisabled = (element) => { const isDisabled = (element) => {
@ -225,7 +194,18 @@ const findShadowRoot = (element) => {
const noop = () => {}; const noop = () => {};
const reflow = (element) => element.offsetHeight; /**
* 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 getjQuery = () => {
const { jQuery } = window; const { jQuery } = window;
@ -237,9 +217,18 @@ const getjQuery = () => {
return null; return null;
}; };
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = (callback) => { const onDOMContentLoaded = (callback) => {
if (document.readyState === 'loading') { 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 { } else {
callback(); callback();
} }
@ -270,6 +259,63 @@ const execute = (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);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element depending on the direction and if cycle is allowed
if (index === -1) {
return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];
}
const listLength = list.length;
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
export { export {
getElement, getElement,
getUID, getUID,
@ -278,16 +324,17 @@ export {
getTransitionDurationFromElement, getTransitionDurationFromElement,
triggerTransitionEnd, triggerTransitionEnd,
isElement, isElement,
emulateTransitionEnd,
typeCheckConfig, typeCheckConfig,
isVisible, isVisible,
isDisabled, isDisabled,
findShadowRoot, findShadowRoot,
noop, noop,
getNextActiveElement,
reflow, reflow,
getjQuery, getjQuery,
onDOMContentLoaded, onDOMContentLoaded,
isRTL, isRTL,
defineJQueryPlugin, defineJQueryPlugin,
execute, execute,
executeAfterTransition,
}; };

View File

@ -1,11 +1,11 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/sanitizer.js * Bootstrap (v5.1.3): util/sanitizer.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
const uriAttrs = new Set([ const uriAttributes = new Set([
'background', 'background',
'cite', 'cite',
'href', 'href',
@ -21,35 +21,36 @@ const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
/** /**
* A pattern that recognizes a commonly useful subset of URLs that are safe. * A pattern that recognizes a commonly useful subset of URLs that are safe.
* *
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
*/ */
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i; const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i;
/** /**
* A pattern that matches safe data URLs. Only matches image, video and audio types. * A pattern that matches safe data URLs. Only matches image, video and audio types.
* *
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
*/ */
const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; const DATA_URL_PATTERN =
/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;
const allowedAttribute = (attr, allowedAttributeList) => { const allowedAttribute = (attribute, allowedAttributeList) => {
const attrName = attr.nodeName.toLowerCase(); const attributeName = attribute.nodeName.toLowerCase();
if (allowedAttributeList.includes(attrName)) { if (allowedAttributeList.includes(attributeName)) {
if (uriAttrs.has(attrName)) { if (uriAttributes.has(attributeName)) {
return Boolean( return Boolean(
SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue) SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)
); );
} }
return true; return true;
} }
const regExp = allowedAttributeList.filter((attrRegex) => attrRegex instanceof RegExp); const regExp = allowedAttributeList.filter((attributeRegex) => attributeRegex instanceof RegExp);
// Check if a regular expression validates the attribute. // Check if a regular expression validates the attribute.
for (let i = 0, len = regExp.length; i < len; i++) { for (let i = 0, len = regExp.length; i < len; i++) {
if (regExp[i].test(attrName)) { if (regExp[i].test(attributeName)) {
return true; return true;
} }
} }
@ -102,25 +103,24 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
const domParser = new window.DOMParser(); const domParser = new window.DOMParser();
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
const allowlistKeys = Object.keys(allowList);
const elements = [].concat(...createdDocument.body.querySelectorAll('*')); const elements = [].concat(...createdDocument.body.querySelectorAll('*'));
for (let i = 0, len = elements.length; i < len; i++) { for (let i = 0, len = elements.length; i < len; i++) {
const el = elements[i]; const element = elements[i];
const elName = el.nodeName.toLowerCase(); const elementName = element.nodeName.toLowerCase();
if (!allowlistKeys.includes(elName)) { if (!Object.keys(allowList).includes(elementName)) {
el.parentNode.removeChild(el); element.remove();
continue; continue;
} }
const attributeList = [].concat(...el.attributes); const attributeList = [].concat(...element.attributes);
const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []); const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);
attributeList.forEach((attr) => { attributeList.forEach((attribute) => {
if (!allowedAttribute(attr, allowedAttributes)) { if (!allowedAttribute(attribute, allowedAttributes)) {
el.removeAttribute(attr.nodeName); element.removeAttribute(attribute.nodeName);
} }
}); });
} }

View File

@ -1,71 +1,86 @@
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Bootstrap (v5.0.1): util/scrollBar.js * Bootstrap (v5.1.3): util/scrollBar.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
import SelectorEngine from '../dom/selector-engine'; import SelectorEngine from '../dom/selector-engine';
import Manipulator from '../dom/manipulator'; import Manipulator from '../dom/manipulator';
import { isElement } from './index';
const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
const SELECTOR_STICKY_CONTENT = '.sticky-top'; const SELECTOR_STICKY_CONTENT = '.sticky-top';
const getWidth = () => { class ScrollBarHelper {
constructor() {
this._element = document.body;
}
getWidth() {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
const documentWidth = document.documentElement.clientWidth; const documentWidth = document.documentElement.clientWidth;
return Math.abs(window.innerWidth - documentWidth); return Math.abs(window.innerWidth - documentWidth);
}; }
const hide = (width = getWidth()) => { hide() {
_disableOverFlow(); const width = this.getWidth();
// give padding to element to balances the hidden scrollbar width this._disableOverFlow();
_setElementAttributes('body', 'paddingRight', (calculatedValue) => calculatedValue + width); // give padding to element to balance the hidden scrollbar width
// trick: We adjust positive paddingRight and negative marginRight to sticky-top elements, to keep shown fullwidth this._setElementAttributes(
_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, SELECTOR_FIXED_CONTENT,
'paddingRight', 'paddingRight',
(calculatedValue) => calculatedValue + width (calculatedValue) => calculatedValue + width
); );
_setElementAttributes( this._setElementAttributes(
SELECTOR_STICKY_CONTENT, SELECTOR_STICKY_CONTENT,
'marginRight', 'marginRight',
(calculatedValue) => calculatedValue - width (calculatedValue) => calculatedValue - width
); );
};
const _disableOverFlow = () => {
const actualValue = document.body.style.overflow;
if (actualValue) {
Manipulator.setDataAttribute(document.body, 'overflow', actualValue);
} }
document.body.style.overflow = 'hidden'; _disableOverFlow() {
}; this._saveInitialAttribute(this._element, 'overflow');
this._element.style.overflow = 'hidden';
}
const _setElementAttributes = (selector, styleProp, callback) => { _setElementAttributes(selector, styleProp, callback) {
const scrollbarWidth = getWidth(); const scrollbarWidth = this.getWidth();
SelectorEngine.find(selector).forEach((element) => { const manipulationCallBack = (element) => {
if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) { if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
return; return;
} }
const actualValue = element.style[styleProp]; this._saveInitialAttribute(element, styleProp);
const calculatedValue = window.getComputedStyle(element)[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`;
});
}; };
const reset = () => { this._applyManipulationCallback(selector, manipulationCallBack);
_resetElementAttributes('body', 'overflow'); }
_resetElementAttributes('body', 'paddingRight');
_resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
_resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
};
const _resetElementAttributes = (selector, styleProp) => { reset() {
SelectorEngine.find(selector).forEach((element) => { 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.setDataAttribute(element, styleProp, actualValue);
}
}
_resetElementAttributes(selector, styleProp) {
const manipulationCallBack = (element) => {
const value = Manipulator.getDataAttribute(element, styleProp); const value = Manipulator.getDataAttribute(element, styleProp);
if (typeof value === 'undefined') { if (typeof value === 'undefined') {
element.style.removeProperty(styleProp); element.style.removeProperty(styleProp);
@ -73,11 +88,22 @@ const _resetElementAttributes = (selector, styleProp) => {
Manipulator.removeDataAttribute(element, styleProp); Manipulator.removeDataAttribute(element, styleProp);
element.style[styleProp] = value; element.style[styleProp] = value;
} }
});
}; };
const isBodyOverflowing = () => { this._applyManipulationCallback(selector, manipulationCallBack);
return getWidth() > 0; }
};
export { getWidth, hide, isBodyOverflowing, reset }; _applyManipulationCallback(selector, callBack) {
if (isElement(selector)) {
callBack(selector);
} else {
SelectorEngine.find(selector, this._element).forEach(callBack);
}
}
isOverflowing() {
return this.getWidth() > 0;
}
}
export default ScrollBarHelper;

View File

@ -297,6 +297,12 @@ class Input {
static getInstance(element) { static getInstance(element) {
return Data.getData(element, DATA_KEY); return Data.getData(element, DATA_KEY);
} }
static getOrCreateInstance(element, config = {}) {
return (
this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
);
}
} }
EventHandler.on(document, 'focus', SELECTOR_OUTLINE_INPUT, Input.activate(new Input())); EventHandler.on(document, 'focus', SELECTOR_OUTLINE_INPUT, Input.activate(new Input()));

View File

@ -118,6 +118,12 @@ class Range {
return Data.getData(element, DATA_KEY); return Data.getData(element, DATA_KEY);
} }
static getOrCreateInstance(element, config = {}) {
return (
this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
);
}
static jQueryInterface(config, options) { static jQueryInterface(config, options) {
return this.each(function () { return this.each(function () {
let data = Data.getData(this, DATA_KEY); let data = Data.getData(this, DATA_KEY);

View File

@ -337,6 +337,12 @@ class Ripple {
static getInstance(element) { static getInstance(element) {
return Data.getData(element, DATA_KEY); return Data.getData(element, DATA_KEY);
} }
static getOrCreateInstance(element, config = {}) {
return (
this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
);
}
} }
/** /**

View File

@ -1,4 +1,3 @@
import TouchUtil from './touchUtil';
import EventHandler from '../../dom/event-handler'; import EventHandler from '../../dom/event-handler';
const DEFAULT_OPTIONS = { const DEFAULT_OPTIONS = {
@ -6,9 +5,8 @@ const DEFAULT_OPTIONS = {
direction: 'all', direction: 'all',
}; };
class Swipe extends TouchUtil { class Swipe {
constructor(element, options) { constructor(element, options) {
super();
this._element = element; this._element = element;
this._startPosition = null; this._startPosition = null;
this._options = { this._options = {
@ -57,6 +55,27 @@ class Swipe extends TouchUtil {
handleTouchEnd() { handleTouchEnd() {
this._startPosition = null; this._startPosition = null;
} }
_getCoordinates(e) {
const [touch] = e.touches;
return {
x: touch.clientX,
y: touch.clientY,
};
}
_getDirection(displacement) {
return {
x: {
direction: displacement.x < 0 ? 'left' : 'right',
value: Math.abs(displacement.x),
},
y: {
direction: displacement.y < 0 ? 'up' : 'down',
value: Math.abs(displacement.y),
},
};
}
} }
export default Swipe; export default Swipe;

View File

@ -13,6 +13,7 @@
background-clip: border-box; background-clip: border-box;
border: $card-border-width solid $card-border-color; border: $card-border-width solid $card-border-color;
@include border-radius($card-border-radius); @include border-radius($card-border-radius);
@include box-shadow($card-box-shadow);
> hr { > hr {
margin-right: 0; margin-right: 0;
@ -55,7 +56,7 @@
} }
.card-subtitle { .card-subtitle {
margin-top: -$card-title-spacer-y / 2; margin-top: -$card-title-spacer-y * 0.5;
margin-bottom: 0; margin-bottom: 0;
} }
@ -65,7 +66,7 @@
.card-link { .card-link {
&:hover { &:hover {
text-decoration: none; text-decoration: if($link-hover-decoration == underline, none, null);
} }
+ .card-link { + .card-link {
@ -105,9 +106,9 @@
// //
.card-header-tabs { .card-header-tabs {
margin-right: -$card-cap-padding-x / 2; margin-right: -$card-cap-padding-x * 0.5;
margin-bottom: -$card-cap-padding-y; margin-bottom: -$card-cap-padding-y;
margin-left: -$card-cap-padding-x / 2; margin-left: -$card-cap-padding-x * 0.5;
border-bottom: 0; border-bottom: 0;
@if $nav-tabs-link-active-bg != $card-bg { @if $nav-tabs-link-active-bg != $card-bg {
@ -119,8 +120,8 @@
} }
.card-header-pills { .card-header-pills {
margin-right: -$card-cap-padding-x / 2; margin-right: -$card-cap-padding-x * 0.5;
margin-left: -$card-cap-padding-x / 2; margin-left: -$card-cap-padding-x * 0.5;
} }
// Card image // Card image

View File

@ -207,9 +207,9 @@
.carousel-caption { .carousel-caption {
position: absolute; position: absolute;
right: (100% - $carousel-caption-width) / 2; right: (100% - $carousel-caption-width) * 0.5;
bottom: $carousel-caption-spacer; bottom: $carousel-caption-spacer;
left: (100% - $carousel-caption-width) / 2; left: (100% - $carousel-caption-width) * 0.5;
padding-top: $carousel-caption-padding-y; padding-top: $carousel-caption-padding-y;
padding-bottom: $carousel-caption-padding-y; padding-bottom: $carousel-caption-padding-y;
color: $carousel-caption-color; color: $carousel-caption-color;

View File

@ -50,9 +50,7 @@
--bs-position: start; --bs-position: start;
&[data-mdb-popper] { &[data-mdb-popper] {
/*!rtl:ignore*/
right: auto; right: auto;
/*!rtl:ignore*/
left: 0; left: 0;
} }
} }
@ -61,9 +59,7 @@
--bs-position: end; --bs-position: end;
&[data-mdb-popper] { &[data-mdb-popper] {
/*!rtl:ignore*/
right: 0; right: 0;
/*!rtl:ignore*/
left: auto; left: auto;
} }
} }

Some files were not shown because too many files have changed in this diff Show More