2013-09-11 04:21:44 +02:00
/ * !
2022-07-19 17:43:58 +02:00
* Bootstrap v5 . 2.0 ( https : //getbootstrap.com/)
2022-05-13 08:07:23 +02:00
* Copyright 2011 - 2022 The Bootstrap Authors ( https : //github.com/twbs/bootstrap/graphs/contributors)
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2017-09-06 06:05:12 +02:00
* /
2017-12-23 01:21:54 +01:00
( function ( global , factory ) {
2020-12-07 16:50:24 +01:00
typeof exports === 'object' && typeof module !== 'undefined' ? module . exports = factory ( require ( '@popperjs/core' ) ) :
typeof define === 'function' && define . amd ? define ( [ '@popperjs/core' ] , factory ) :
2020-09-14 17:12:06 +02:00
( global = typeof globalThis !== 'undefined' ? globalThis : global || self , global . bootstrap = factory ( global . Popper ) ) ;
2021-10-05 17:50:18 +02:00
} ) ( this , ( function ( Popper ) { 'use strict' ;
2016-10-10 02:26:51 +02:00
2020-12-07 16:50:24 +01:00
function _interopNamespace ( e ) {
if ( e && e . _ _esModule ) return e ;
2022-05-13 08:07:23 +02:00
const n = Object . create ( null , { [ Symbol . toStringTag ] : { value : 'Module' } } ) ;
2020-12-07 16:50:24 +01:00
if ( e ) {
2021-10-05 17:50:18 +02:00
for ( const k in e ) {
2020-12-07 16:50:24 +01:00
if ( k !== 'default' ) {
2021-10-05 17:50:18 +02:00
const d = Object . getOwnPropertyDescriptor ( e , k ) ;
2020-12-07 16:50:24 +01:00
Object . defineProperty ( n , k , d . get ? d : {
enumerable : true ,
2021-10-05 17:50:18 +02:00
get : ( ) => e [ k ]
2020-12-07 16:50:24 +01:00
} ) ;
}
2021-10-05 17:50:18 +02:00
}
2020-12-07 16:50:24 +01:00
}
2021-10-05 17:50:18 +02:00
n . default = e ;
2020-12-07 16:50:24 +01:00
return Object . freeze ( n ) ;
}
2020-09-14 17:12:06 +02:00
2021-10-05 17:50:18 +02:00
const Popper _ _namespace = /*#__PURE__*/ _interopNamespace ( Popper ) ;
2015-08-15 21:19:11 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / index . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2015-08-15 21:19:11 +02:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const MAX _UID = 1000000 ;
const MILLISECONDS _MULTIPLIER = 1000 ;
2022-07-19 17:43:58 +02:00
const TRANSITION _END = 'transitionend' ; // Shout-out Angus Croll (https://goo.gl/pxwQGp)
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
const toType = object => {
if ( object === null || object === undefined ) {
return ` ${ object } ` ;
2020-03-28 11:29:08 +01:00
}
2022-05-13 08:07:23 +02:00
return Object . prototype . toString . call ( object ) . match ( /\s([a-z]+)/i ) [ 1 ] . toLowerCase ( ) ;
2019-03-01 17:31:34 +01:00
} ;
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Public Util API
2018-11-13 07:41:12 +01:00
* /
2018-03-31 22:59:37 +02:00
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const getUID = prefix => {
2019-03-01 17:31:34 +01:00
do {
2020-06-14 00:40:28 +02:00
prefix += Math . floor ( Math . random ( ) * MAX _UID ) ;
2019-03-01 17:31:34 +01:00
} while ( document . getElementById ( prefix ) ) ;
2017-09-30 23:28:03 +02:00
2019-03-01 17:31:34 +01:00
return prefix ;
} ;
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
const getSelector = element => {
let selector = element . getAttribute ( 'data-bs-target' ) ;
2019-03-01 17:31:34 +01:00
if ( ! selector || selector === '#' ) {
2022-05-13 08:07:23 +02:00
let hrefAttribute = element . getAttribute ( 'href' ) ; // The only valid content that could double as a selector are IDs or classes,
2021-02-10 17:14:51 +01:00
// 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
2022-05-13 08:07:23 +02:00
if ( ! hrefAttribute || ! hrefAttribute . includes ( '#' ) && ! hrefAttribute . startsWith ( '.' ) ) {
2021-02-10 17:14:51 +01:00
return null ;
} // Just in case some CMS puts out a full URL with the anchor appended
2022-05-13 08:07:23 +02:00
if ( hrefAttribute . includes ( '#' ) && ! hrefAttribute . startsWith ( '#' ) ) {
hrefAttribute = ` # ${ hrefAttribute . split ( '#' ) [ 1 ] } ` ;
2021-02-10 17:14:51 +01:00
}
2022-05-13 08:07:23 +02:00
selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute . trim ( ) : null ;
2019-03-01 17:31:34 +01:00
}
2019-08-27 15:03:21 +02:00
return selector ;
} ;
2021-03-23 17:26:54 +01:00
const getSelectorFromElement = element => {
const selector = getSelector ( element ) ;
2019-08-27 15:03:21 +02:00
if ( selector ) {
2019-03-01 17:31:34 +01:00
return document . querySelector ( selector ) ? selector : null ;
}
2019-08-27 15:03:21 +02:00
return null ;
} ;
2021-03-23 17:26:54 +01:00
const getElementFromSelector = element => {
const selector = getSelector ( element ) ;
2019-08-27 15:03:21 +02:00
return selector ? document . querySelector ( selector ) : null ;
2019-03-01 17:31:34 +01:00
} ;
2021-03-23 17:26:54 +01:00
const getTransitionDurationFromElement = element => {
2019-03-01 17:31:34 +01:00
if ( ! element ) {
return 0 ;
} // Get transition-duration of the element
2015-08-15 21:19:11 +02:00
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
let {
transitionDuration ,
transitionDelay
} = window . getComputedStyle ( element ) ;
const floatTransitionDuration = Number . parseFloat ( transitionDuration ) ;
const floatTransitionDelay = Number . parseFloat ( transitionDelay ) ; // Return 0 if element or transition duration is not found
2019-03-01 17:31:34 +01:00
if ( ! floatTransitionDuration && ! floatTransitionDelay ) {
return 0 ;
} // If multiple durations are defined, take the first
transitionDuration = transitionDuration . split ( ',' ) [ 0 ] ;
transitionDelay = transitionDelay . split ( ',' ) [ 0 ] ;
2020-11-23 14:17:16 +01:00
return ( Number . parseFloat ( transitionDuration ) + Number . parseFloat ( transitionDelay ) ) * MILLISECONDS _MULTIPLIER ;
2019-03-01 17:31:34 +01:00
} ;
2021-03-23 17:26:54 +01:00
const triggerTransitionEnd = element => {
2020-03-28 11:29:08 +01:00
element . dispatchEvent ( new Event ( TRANSITION _END ) ) ;
2019-03-01 17:31:34 +01:00
} ;
2022-05-13 08:07:23 +02:00
const isElement = object => {
if ( ! object || typeof object !== 'object' ) {
2021-05-13 18:22:20 +02:00
return false ;
}
2022-05-13 08:07:23 +02:00
if ( typeof object . jquery !== 'undefined' ) {
object = object [ 0 ] ;
2021-05-13 18:22:20 +02:00
}
2022-05-13 08:07:23 +02:00
return typeof object . nodeType !== 'undefined' ;
2021-05-13 18:22:20 +02:00
} ;
2022-05-13 08:07:23 +02:00
const getElement = object => {
// it's a jQuery object or a node element
if ( isElement ( object ) ) {
return object . jquery ? object [ 0 ] : object ;
2021-05-13 18:22:20 +02:00
}
2022-05-13 08:07:23 +02:00
if ( typeof object === 'string' && object . length > 0 ) {
return document . querySelector ( object ) ;
2021-05-13 18:22:20 +02:00
}
return null ;
} ;
2019-03-01 17:31:34 +01:00
2021-03-23 17:26:54 +01:00
const isVisible = element => {
2021-06-22 20:29:16 +02:00
if ( ! isElement ( element ) || element . getClientRects ( ) . length === 0 ) {
2019-03-01 17:31:34 +01:00
return false ;
}
2022-05-13 08:07:23 +02:00
const elementIsVisible = getComputedStyle ( element ) . getPropertyValue ( 'visibility' ) === 'visible' ; // Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element . closest ( 'details:not([open])' ) ;
if ( ! closedDetails ) {
return elementIsVisible ;
}
if ( closedDetails !== element ) {
const summary = element . closest ( 'summary' ) ;
if ( summary && summary . parentNode !== closedDetails ) {
return false ;
}
if ( summary === null ) {
return false ;
}
}
return elementIsVisible ;
2019-03-01 17:31:34 +01:00
} ;
2021-03-23 17:26:54 +01:00
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 findShadowRoot = element => {
2019-03-01 17:31:34 +01:00
if ( ! document . documentElement . attachShadow ) {
return null ;
} // Can find the shadow root otherwise it'll return the document
if ( typeof element . getRootNode === 'function' ) {
2021-03-23 17:26:54 +01:00
const root = element . getRootNode ( ) ;
2019-03-01 17:31:34 +01:00
return root instanceof ShadowRoot ? root : null ;
}
if ( element instanceof ShadowRoot ) {
return element ;
} // when we don't find a shadow root
if ( ! element . parentNode ) {
return null ;
}
return findShadowRoot ( element . parentNode ) ;
2019-10-08 08:39:10 +02:00
} ;
2019-03-01 17:31:34 +01:00
2021-05-05 21:32:12 +02:00
const noop = ( ) => { } ;
2021-08-04 17:41:51 +02:00
/ * *
* 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
* /
2019-03-01 17:31:34 +01:00
2021-08-04 17:41:51 +02:00
const reflow = element => {
2022-05-13 08:07:23 +02:00
element . offsetHeight ; // eslint-disable-line no-unused-expressions
2021-08-04 17:41:51 +02:00
} ;
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
const getjQuery = ( ) => {
2022-05-13 08:07:23 +02:00
if ( window . jQuery && ! document . body . hasAttribute ( 'data-bs-no-jquery' ) ) {
return window . jQuery ;
2019-08-27 15:03:21 +02:00
}
return null ;
} ;
2021-06-22 20:29:16 +02:00
const DOMContentLoadedCallbacks = [ ] ;
2021-03-23 17:26:54 +01:00
const onDOMContentLoaded = callback => {
2020-11-11 18:07:37 +01:00
if ( document . readyState === 'loading' ) {
2021-06-22 20:29:16 +02:00
// add listener on the first call when the document is in loading state
if ( ! DOMContentLoadedCallbacks . length ) {
document . addEventListener ( 'DOMContentLoaded' , ( ) => {
2022-05-13 08:07:23 +02:00
for ( const callback of DOMContentLoadedCallbacks ) {
callback ( ) ;
}
2021-06-22 20:29:16 +02:00
} ) ;
}
DOMContentLoadedCallbacks . push ( callback ) ;
2020-11-11 18:07:37 +01:00
} else {
callback ( ) ;
}
} ;
2021-03-23 17:26:54 +01:00
const isRTL = ( ) => document . documentElement . dir === 'rtl' ;
2020-12-03 14:08:31 +01:00
2021-05-13 18:22:20 +02:00
const defineJQueryPlugin = plugin => {
2021-03-23 17:26:54 +01:00
onDOMContentLoaded ( ( ) => {
const $ = getjQuery ( ) ;
2021-02-10 17:14:51 +01:00
/* istanbul ignore if */
if ( $ ) {
2021-05-13 18:22:20 +02:00
const name = plugin . NAME ;
2021-03-23 17:26:54 +01:00
const JQUERY _NO _CONFLICT = $ . fn [ name ] ;
2021-02-10 17:14:51 +01:00
$ . fn [ name ] = plugin . jQueryInterface ;
$ . fn [ name ] . Constructor = plugin ;
2021-03-23 17:26:54 +01:00
$ . fn [ name ] . noConflict = ( ) => {
2021-02-10 17:14:51 +01:00
$ . fn [ name ] = JQUERY _NO _CONFLICT ;
return plugin . jQueryInterface ;
} ;
}
} ) ;
} ;
2021-05-05 21:32:12 +02:00
const execute = callback => {
if ( typeof callback === 'function' ) {
callback ( ) ;
}
} ;
2021-06-22 20:29:16 +02:00
const executeAfterTransition = ( callback , transitionElement , waitForTransition = true ) => {
if ( ! waitForTransition ) {
execute ( callback ) ;
return ;
}
2019-03-01 17:31:34 +01:00
2021-06-22 20:29:16 +02:00
const durationPadding = 5 ;
const emulatedDuration = getTransitionDurationFromElement ( transitionElement ) + durationPadding ;
let called = false ;
2018-11-13 07:41:12 +01:00
2021-06-22 20:29:16 +02:00
const handler = ( {
target
} ) => {
if ( target !== transitionElement ) {
2021-03-23 17:26:54 +01:00
return ;
}
2018-11-13 07:41:12 +01:00
2021-06-22 20:29:16 +02:00
called = true ;
transitionElement . removeEventListener ( TRANSITION _END , handler ) ;
execute ( callback ) ;
} ;
2019-03-01 17:31:34 +01:00
2021-06-22 20:29:16 +02:00
transitionElement . addEventListener ( TRANSITION _END , handler ) ;
setTimeout ( ( ) => {
if ( ! called ) {
triggerTransitionEnd ( transitionElement ) ;
2021-03-23 17:26:54 +01:00
}
2021-06-22 20:29:16 +02:00
} , 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
* /
2018-11-13 07:41:12 +01:00
2019-03-01 17:31:34 +01:00
2021-06-22 20:29:16 +02:00
const getNextActiveElement = ( list , activeElement , shouldGetNext , isCycleAllowed ) => {
2022-05-13 08:07:23 +02:00
const listLength = list . length ;
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
2019-03-01 17:31:34 +01:00
2021-06-22 20:29:16 +02:00
if ( index === - 1 ) {
2022-05-13 08:07:23 +02:00
return ! shouldGetNext && isCycleAllowed ? list [ listLength - 1 ] : list [ 0 ] ;
2021-06-22 20:29:16 +02:00
}
2021-03-23 17:26:54 +01:00
2021-06-22 20:29:16 +02:00
index += shouldGetNext ? 1 : - 1 ;
if ( isCycleAllowed ) {
index = ( index + listLength ) % listLength ;
2019-03-01 17:31:34 +01:00
}
2021-03-23 17:26:54 +01:00
2021-06-22 20:29:16 +02:00
return list [ Math . max ( 0 , Math . min ( index , listLength - 1 ) ) ] ;
2019-03-01 17:31:34 +01:00
} ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : dom / event - handler . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2019-03-01 17:31:34 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* Constants
* /
2021-03-23 17:26:54 +01:00
const namespaceRegex = /[^.]*(?=\..*)\.|.*/ ;
const stripNameRegex = /\..*/ ;
const stripUidRegex = /::\d+$/ ;
const eventRegistry = { } ; // Events storage
2019-03-01 17:31:34 +01:00
2021-03-23 17:26:54 +01:00
let uidEvent = 1 ;
const customEvents = {
2019-03-01 17:31:34 +01:00
mouseenter : 'mouseover' ,
mouseleave : 'mouseout'
} ;
2021-03-23 17:26:54 +01:00
const nativeEvents = new Set ( [ 'click' , 'dblclick' , 'mouseup' , 'mousedown' , 'contextmenu' , 'mousewheel' , 'DOMMouseScroll' , 'mouseover' , 'mouseout' , 'mousemove' , 'selectstart' , 'selectend' , 'keydown' , 'keypress' , 'keyup' , 'orientationchange' , 'touchstart' , 'touchmove' , 'touchend' , 'touchcancel' , 'pointerdown' , 'pointermove' , 'pointerup' , 'pointerleave' , 'pointercancel' , 'gesturestart' , 'gesturechange' , 'gestureend' , 'focus' , 'blur' , 'change' , 'reset' , 'select' , 'submit' , 'focusin' , 'focusout' , 'load' , 'unload' , 'beforeunload' , 'resize' , 'move' , 'DOMContentLoaded' , 'readystatechange' , 'error' , 'abort' , 'scroll' ] ) ;
2019-03-01 17:31:34 +01:00
/ * *
* Private methods
* /
2022-07-19 17:43:58 +02:00
function makeEventUid ( element , uid ) {
2021-03-23 17:26:54 +01:00
return uid && ` ${ uid } :: ${ uidEvent ++ } ` || element . uidEvent || uidEvent ++ ;
2019-03-01 17:31:34 +01:00
}
2022-07-19 17:43:58 +02:00
function getElementEvents ( element ) {
const uid = makeEventUid ( element ) ;
2019-03-01 17:31:34 +01:00
element . uidEvent = uid ;
2019-03-11 16:13:30 +01:00
eventRegistry [ uid ] = eventRegistry [ uid ] || { } ;
return eventRegistry [ uid ] ;
2019-03-01 17:31:34 +01:00
}
function bootstrapHandler ( element , fn ) {
return function handler ( event ) {
2022-07-19 17:43:58 +02:00
hydrateObj ( event , {
delegateTarget : element
} ) ;
2020-09-14 17:12:06 +02:00
2019-03-01 17:31:34 +01:00
if ( handler . oneOff ) {
EventHandler . off ( element , event . type , fn ) ;
}
return fn . apply ( element , [ event ] ) ;
} ;
}
function bootstrapDelegationHandler ( element , selector , fn ) {
return function handler ( event ) {
2021-03-23 17:26:54 +01:00
const domElements = element . querySelectorAll ( selector ) ;
2019-03-01 17:31:34 +01:00
2021-03-23 17:26:54 +01:00
for ( let {
target
} = event ; target && target !== this ; target = target . parentNode ) {
2022-05-13 08:07:23 +02:00
for ( const domElement of domElements ) {
if ( domElement !== target ) {
continue ;
}
2020-09-14 17:12:06 +02:00
2022-07-19 17:43:58 +02:00
hydrateObj ( event , {
delegateTarget : target
} ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
if ( handler . oneOff ) {
EventHandler . off ( element , event . type , selector , fn ) ;
2019-03-01 17:31:34 +01:00
}
2022-05-13 08:07:23 +02:00
return fn . apply ( target , [ event ] ) ;
}
}
2019-03-01 17:31:34 +01:00
} ;
}
2022-07-19 17:43:58 +02:00
function findHandler ( events , callable , delegationSelector = null ) {
return Object . values ( events ) . find ( event => event . callable === callable && event . delegationSelector === delegationSelector ) ;
2019-03-01 17:31:34 +01:00
}
2022-05-13 08:07:23 +02:00
function normalizeParameters ( originalTypeEvent , handler , delegationFunction ) {
2022-07-19 17:43:58 +02:00
const isDelegated = typeof handler === 'string' ; // todo: tooltip passes `false` instead of selector, so we need to check
const callable = isDelegated ? delegationFunction : handler || delegationFunction ;
2021-05-05 21:32:12 +02:00
let typeEvent = getTypeEvent ( originalTypeEvent ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
if ( ! nativeEvents . has ( typeEvent ) ) {
2019-03-01 17:31:34 +01:00
typeEvent = originalTypeEvent ;
}
2022-07-19 17:43:58 +02:00
return [ isDelegated , callable , typeEvent ] ;
2019-03-01 17:31:34 +01:00
}
2022-05-13 08:07:23 +02:00
function addHandler ( element , originalTypeEvent , handler , delegationFunction , oneOff ) {
2019-03-01 17:31:34 +01:00
if ( typeof originalTypeEvent !== 'string' || ! element ) {
return ;
}
2022-07-19 17:43:58 +02:00
let [ isDelegated , callable , typeEvent ] = normalizeParameters ( originalTypeEvent , handler , delegationFunction ) ; // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position
2021-05-05 21:32:12 +02:00
// this prevents the handler from being dispatched the same way as mouseover or mouseout does
2022-05-13 08:07:23 +02:00
if ( originalTypeEvent in customEvents ) {
const wrapFunction = fn => {
2021-05-05 21:32:12 +02:00
return function ( event ) {
if ( ! event . relatedTarget || event . relatedTarget !== event . delegateTarget && ! event . delegateTarget . contains ( event . relatedTarget ) ) {
return fn . call ( this , event ) ;
}
} ;
} ;
2022-07-19 17:43:58 +02:00
callable = wrapFunction ( callable ) ;
2019-03-01 17:31:34 +01:00
}
2022-07-19 17:43:58 +02:00
const events = getElementEvents ( element ) ;
2021-03-23 17:26:54 +01:00
const handlers = events [ typeEvent ] || ( events [ typeEvent ] = { } ) ;
2022-07-19 17:43:58 +02:00
const previousFunction = findHandler ( handlers , callable , isDelegated ? handler : null ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
if ( previousFunction ) {
previousFunction . oneOff = previousFunction . oneOff && oneOff ;
2019-03-01 17:31:34 +01:00
return ;
}
2022-07-19 17:43:58 +02:00
const uid = makeEventUid ( callable , originalTypeEvent . replace ( namespaceRegex , '' ) ) ;
const fn = isDelegated ? bootstrapDelegationHandler ( element , handler , callable ) : bootstrapHandler ( element , callable ) ;
fn . delegationSelector = isDelegated ? handler : null ;
fn . callable = callable ;
2019-03-01 17:31:34 +01:00
fn . oneOff = oneOff ;
fn . uidEvent = uid ;
handlers [ uid ] = fn ;
2022-07-19 17:43:58 +02:00
element . addEventListener ( typeEvent , fn , isDelegated ) ;
2019-03-01 17:31:34 +01:00
}
function removeHandler ( element , events , typeEvent , handler , delegationSelector ) {
2021-03-23 17:26:54 +01:00
const fn = findHandler ( events [ typeEvent ] , handler , delegationSelector ) ;
2019-03-01 17:31:34 +01:00
2019-07-12 23:56:26 +02:00
if ( ! fn ) {
2019-03-01 17:31:34 +01:00
return ;
}
element . removeEventListener ( typeEvent , fn , Boolean ( delegationSelector ) ) ;
delete events [ typeEvent ] [ fn . uidEvent ] ;
}
function removeNamespacedHandlers ( element , events , typeEvent , namespace ) {
2021-03-23 17:26:54 +01:00
const storeElementEvent = events [ typeEvent ] || { } ;
2022-05-13 08:07:23 +02:00
for ( const handlerKey of Object . keys ( storeElementEvent ) ) {
2020-11-23 14:17:16 +01:00
if ( handlerKey . includes ( namespace ) ) {
2021-03-23 17:26:54 +01:00
const event = storeElementEvent [ handlerKey ] ;
2022-07-19 17:43:58 +02:00
removeHandler ( element , events , typeEvent , event . callable , event . delegationSelector ) ;
2019-01-04 17:29:45 +01:00
}
2022-05-13 08:07:23 +02:00
}
2019-03-01 17:31:34 +01:00
}
2021-05-05 21:32:12 +02:00
function getTypeEvent ( event ) {
// allow to get the native events from namespaced events ('click.bs.button' --> 'click')
event = event . replace ( stripNameRegex , '' ) ;
return customEvents [ event ] || event ;
}
2021-03-23 17:26:54 +01:00
const EventHandler = {
2022-05-13 08:07:23 +02:00
on ( element , event , handler , delegationFunction ) {
addHandler ( element , event , handler , delegationFunction , false ) ;
2018-11-13 07:41:12 +01:00
} ,
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
one ( element , event , handler , delegationFunction ) {
addHandler ( element , event , handler , delegationFunction , true ) ;
2019-03-01 17:31:34 +01:00
} ,
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
off ( element , originalTypeEvent , handler , delegationFunction ) {
2019-03-01 17:31:34 +01:00
if ( typeof originalTypeEvent !== 'string' || ! element ) {
return ;
}
2018-11-13 07:41:12 +01:00
2022-07-19 17:43:58 +02:00
const [ isDelegated , callable , typeEvent ] = normalizeParameters ( originalTypeEvent , handler , delegationFunction ) ;
2021-03-23 17:26:54 +01:00
const inNamespace = typeEvent !== originalTypeEvent ;
2022-07-19 17:43:58 +02:00
const events = getElementEvents ( element ) ;
const storeElementEvent = events [ typeEvent ] || { } ;
2021-03-23 17:26:54 +01:00
const isNamespace = originalTypeEvent . startsWith ( '.' ) ;
2018-11-13 07:41:12 +01:00
2022-07-19 17:43:58 +02:00
if ( typeof callable !== 'undefined' ) {
2019-03-01 17:31:34 +01:00
// Simplest case: handler is passed, remove that listener ONLY.
2022-07-19 17:43:58 +02:00
if ( ! Object . keys ( storeElementEvent ) . length ) {
2019-03-01 17:31:34 +01:00
return ;
}
2018-11-13 07:41:12 +01:00
2022-07-19 17:43:58 +02:00
removeHandler ( element , events , typeEvent , callable , isDelegated ? handler : null ) ;
2019-03-01 17:31:34 +01:00
return ;
}
2018-11-13 07:41:12 +01:00
2019-03-01 17:31:34 +01:00
if ( isNamespace ) {
2022-05-13 08:07:23 +02:00
for ( const elementEvent of Object . keys ( events ) ) {
2019-10-08 08:39:10 +02:00
removeNamespacedHandlers ( element , events , elementEvent , originalTypeEvent . slice ( 1 ) ) ;
2022-05-13 08:07:23 +02:00
}
2019-03-01 17:31:34 +01:00
}
2022-05-13 08:07:23 +02:00
for ( const keyHandlers of Object . keys ( storeElementEvent ) ) {
2021-03-23 17:26:54 +01:00
const handlerKey = keyHandlers . replace ( stripUidRegex , '' ) ;
2019-03-01 17:31:34 +01:00
2020-11-23 14:17:16 +01:00
if ( ! inNamespace || originalTypeEvent . includes ( handlerKey ) ) {
2021-03-23 17:26:54 +01:00
const event = storeElementEvent [ keyHandlers ] ;
2022-07-19 17:43:58 +02:00
removeHandler ( element , events , typeEvent , event . callable , event . delegationSelector ) ;
2019-03-01 17:31:34 +01:00
}
2022-05-13 08:07:23 +02:00
}
2018-11-13 07:41:12 +01:00
} ,
2021-03-23 17:26:54 +01:00
trigger ( element , event , args ) {
2019-03-01 17:31:34 +01:00
if ( typeof event !== 'string' || ! element ) {
return null ;
}
2021-03-23 17:26:54 +01:00
const $ = getjQuery ( ) ;
2021-05-05 21:32:12 +02:00
const typeEvent = getTypeEvent ( event ) ;
2021-03-23 17:26:54 +01:00
const inNamespace = event !== typeEvent ;
2022-05-13 08:07:23 +02:00
let jQueryEvent = null ;
2021-03-23 17:26:54 +01:00
let bubbles = true ;
let nativeDispatch = true ;
let defaultPrevented = false ;
2019-03-01 17:31:34 +01:00
2019-08-27 15:03:21 +02:00
if ( inNamespace && $ ) {
jQueryEvent = $ . Event ( event , args ) ;
$ ( element ) . trigger ( jQueryEvent ) ;
2019-03-01 17:31:34 +01:00
bubbles = ! jQueryEvent . isPropagationStopped ( ) ;
nativeDispatch = ! jQueryEvent . isImmediatePropagationStopped ( ) ;
defaultPrevented = jQueryEvent . isDefaultPrevented ( ) ;
}
2022-07-19 17:43:58 +02:00
let evt = new Event ( event , {
2022-05-13 08:07:23 +02:00
bubbles ,
cancelable : true
2022-07-19 17:43:58 +02:00
} ) ;
evt = hydrateObj ( evt , args ) ;
2019-03-01 17:31:34 +01:00
if ( defaultPrevented ) {
evt . preventDefault ( ) ;
}
if ( nativeDispatch ) {
element . dispatchEvent ( evt ) ;
}
2022-05-13 08:07:23 +02:00
if ( evt . defaultPrevented && jQueryEvent ) {
2019-03-01 17:31:34 +01:00
jQueryEvent . preventDefault ( ) ;
}
return evt ;
}
2021-03-23 17:26:54 +01:00
2019-03-01 17:31:34 +01:00
} ;
2022-07-19 17:43:58 +02:00
function hydrateObj ( obj , meta ) {
for ( const [ key , value ] of Object . entries ( meta || { } ) ) {
try {
obj [ key ] = value ;
} catch ( _unused ) {
Object . defineProperty ( obj , key , {
configurable : true ,
get ( ) {
return value ;
}
} ) ;
}
}
return obj ;
}
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : dom / data . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-06-22 20:29:16 +02:00
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2021-06-22 20:29:16 +02:00
const elementMap = new Map ( ) ;
2021-10-05 17:50:18 +02:00
const Data = {
2021-06-22 20:29:16 +02:00
set ( element , key , instance ) {
if ( ! elementMap . has ( element ) ) {
elementMap . set ( element , new Map ( ) ) ;
}
const instanceMap = elementMap . get ( element ) ; // make it clear we only want one instance per element
// can be removed later when multiple key/instances are fine to be used
2018-11-13 07:41:12 +01:00
2021-06-22 20:29:16 +02:00
if ( ! instanceMap . has ( key ) && instanceMap . size !== 0 ) {
// eslint-disable-next-line no-console
console . error ( ` Bootstrap doesn't allow more than one instance per element. Bound instance: ${ Array . from ( instanceMap . keys ( ) ) [ 0 ] } . ` ) ;
return ;
}
instanceMap . set ( key , instance ) ;
} ,
get ( element , key ) {
if ( elementMap . has ( element ) ) {
return elementMap . get ( element ) . get ( key ) || null ;
}
return null ;
} ,
remove ( element , key ) {
if ( ! elementMap . has ( element ) ) {
return ;
}
const instanceMap = elementMap . get ( element ) ;
instanceMap . delete ( key ) ; // free up element references if there are no instances left for an element
if ( instanceMap . size === 0 ) {
elementMap . delete ( element ) ;
}
}
} ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : dom / manipulator . js
2022-05-13 08:07:23 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
function normalizeData ( value ) {
if ( value === 'true' ) {
return true ;
}
if ( value === 'false' ) {
return false ;
}
if ( value === Number ( value ) . toString ( ) ) {
return Number ( value ) ;
}
if ( value === '' || value === 'null' ) {
return null ;
}
if ( typeof value !== 'string' ) {
return value ;
}
try {
return JSON . parse ( decodeURIComponent ( value ) ) ;
} catch ( _unused ) {
return value ;
}
}
function normalizeDataKey ( key ) {
return key . replace ( /[A-Z]/g , chr => ` - ${ chr . toLowerCase ( ) } ` ) ;
}
const Manipulator = {
setDataAttribute ( element , key , value ) {
element . setAttribute ( ` data-bs- ${ normalizeDataKey ( key ) } ` , value ) ;
} ,
removeDataAttribute ( element , key ) {
element . removeAttribute ( ` data-bs- ${ normalizeDataKey ( key ) } ` ) ;
} ,
getDataAttributes ( element ) {
if ( ! element ) {
return { } ;
}
const attributes = { } ;
const bsKeys = Object . keys ( element . dataset ) . filter ( key => key . startsWith ( 'bs' ) && ! key . startsWith ( 'bsConfig' ) ) ;
for ( const key of bsKeys ) {
let pureKey = key . replace ( /^bs/ , '' ) ;
pureKey = pureKey . charAt ( 0 ) . toLowerCase ( ) + pureKey . slice ( 1 , pureKey . length ) ;
attributes [ pureKey ] = normalizeData ( element . dataset [ key ] ) ;
}
return attributes ;
} ,
getDataAttribute ( element , key ) {
return normalizeData ( element . getAttribute ( ` data-bs- ${ normalizeDataKey ( key ) } ` ) ) ;
}
} ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / config . js
2022-05-13 08:07:23 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* Class definition
* /
class Config {
// Getters
static get Default ( ) {
return { } ;
}
static get DefaultType ( ) {
return { } ;
}
static get NAME ( ) {
throw new Error ( 'You have to implement the static method "NAME", for each component!' ) ;
}
_getConfig ( config ) {
config = this . _mergeConfigObj ( config ) ;
config = this . _configAfterMerge ( config ) ;
this . _typeCheckConfig ( config ) ;
return config ;
}
_configAfterMerge ( config ) {
return config ;
}
_mergeConfigObj ( config , element ) {
const jsonConfig = isElement ( element ) ? Manipulator . getDataAttribute ( element , 'config' ) : { } ; // try to parse
return { ... this . constructor . Default ,
... ( typeof jsonConfig === 'object' ? jsonConfig : { } ) ,
... ( isElement ( element ) ? Manipulator . getDataAttributes ( element ) : { } ) ,
... ( typeof config === 'object' ? config : { } )
} ;
}
_typeCheckConfig ( config , configTypes = this . constructor . DefaultType ) {
for ( const property of Object . keys ( configTypes ) ) {
const expectedTypes = configTypes [ property ] ;
const value = config [ property ] ;
const valueType = isElement ( value ) ? 'element' : toType ( value ) ;
if ( ! new RegExp ( expectedTypes ) . test ( valueType ) ) {
throw new TypeError ( ` ${ this . constructor . NAME . toUpperCase ( ) } : Option " ${ property } " provided type " ${ valueType } " but expected type " ${ expectedTypes } ". ` ) ;
}
}
}
}
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : base - component . js
2021-06-22 20:29:16 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* Constants
* /
2022-07-19 17:43:58 +02:00
const VERSION = '5.2.0' ;
2022-05-13 08:07:23 +02:00
/ * *
* Class definition
* /
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
class BaseComponent extends Config {
constructor ( element , config ) {
super ( ) ;
2021-05-13 18:22:20 +02:00
element = getElement ( element ) ;
2020-12-03 15:18:59 +01:00
if ( ! element ) {
return ;
}
this . _element = element ;
2022-05-13 08:07:23 +02:00
this . _config = this . _getConfig ( config ) ;
2021-03-23 17:26:54 +01:00
Data . set ( this . _element , this . constructor . DATA _KEY , this ) ;
2022-05-13 08:07:23 +02:00
} // Public
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
Data . remove ( this . _element , this . constructor . DATA _KEY ) ;
2021-05-13 18:22:20 +02:00
EventHandler . off ( this . _element , this . constructor . EVENT _KEY ) ;
2022-05-13 08:07:23 +02:00
for ( const propertyName of Object . getOwnPropertyNames ( this ) ) {
2021-05-13 18:22:20 +02:00
this [ propertyName ] = null ;
2022-05-13 08:07:23 +02:00
}
2021-05-13 18:22:20 +02:00
}
_queueCallback ( callback , element , isAnimated = true ) {
2021-06-22 20:29:16 +02:00
executeAfterTransition ( callback , element , isAnimated ) ;
2020-12-03 15:18:59 +01:00
}
2022-05-13 08:07:23 +02:00
_getConfig ( config ) {
config = this . _mergeConfigObj ( config , this . _element ) ;
config = this . _configAfterMerge ( config ) ;
this . _typeCheckConfig ( config ) ;
return config ;
} // Static
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
static getInstance ( element ) {
2021-08-04 17:41:51 +02:00
return Data . get ( getElement ( element ) , this . DATA _KEY ) ;
2021-03-23 17:26:54 +01:00
}
2021-06-22 20:29:16 +02:00
static getOrCreateInstance ( element , config = { } ) {
return this . getInstance ( element ) || new this ( element , typeof config === 'object' ? config : null ) ;
}
2021-03-23 17:26:54 +01:00
static get VERSION ( ) {
return VERSION ;
}
2020-12-03 15:18:59 +01:00
2021-05-13 18:22:20 +02:00
static get DATA _KEY ( ) {
return ` bs. ${ this . NAME } ` ;
}
static get EVENT _KEY ( ) {
return ` . ${ this . DATA _KEY } ` ;
}
2022-05-13 08:07:23 +02:00
static eventName ( name ) {
return ` ${ name } ${ this . EVENT _KEY } ` ;
}
2021-03-23 17:26:54 +01:00
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / component - functions . js
2021-08-04 17:41:51 +02:00
* 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 . 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 ] ( ) ;
} ) ;
} ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : alert . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2020-12-03 15:18:59 +01:00
/ * *
* Constants
* /
2022-05-13 08:07:23 +02:00
const NAME$f = 'alert' ;
const DATA _KEY$a = 'bs.alert' ;
const EVENT _KEY$b = ` . ${ DATA _KEY$a } ` ;
const EVENT _CLOSE = ` close ${ EVENT _KEY$b } ` ;
const EVENT _CLOSED = ` closed ${ EVENT _KEY$b } ` ;
2021-08-04 17:41:51 +02:00
const CLASS _NAME _FADE$5 = 'fade' ;
const CLASS _NAME _SHOW$8 = 'show' ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
class Alert extends BaseComponent {
// Getters
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
2022-05-13 08:07:23 +02:00
return NAME$f ;
2021-03-23 17:26:54 +01:00
} // Public
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
close ( ) {
const closeEvent = EventHandler . trigger ( this . _element , EVENT _CLOSE ) ;
2016-10-10 02:26:51 +02:00
2021-08-04 17:41:51 +02:00
if ( closeEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
this . _element . classList . remove ( CLASS _NAME _SHOW$8 ) ;
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
const isAnimated = this . _element . classList . contains ( CLASS _NAME _FADE$5 ) ;
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
this . _queueCallback ( ( ) => this . _destroyElement ( ) , this . _element , isAnimated ) ;
} // Private
2016-11-01 05:36:10 +01:00
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
_destroyElement ( ) {
this . _element . remove ( ) ;
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
EventHandler . trigger ( this . _element , EVENT _CLOSED ) ;
this . dispose ( ) ;
2019-01-04 17:29:45 +01:00
} // Static
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2018-11-13 07:41:12 +01:00
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Alert . getOrCreateInstance ( this ) ;
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
if ( typeof config !== 'string' ) {
return ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
if ( data [ config ] === undefined || config . startsWith ( '_' ) || config === 'constructor' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
data [ config ] ( this ) ;
} ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2018-11-13 07:41:12 +01:00
* /
2015-08-15 21:19:11 +02:00
2017-09-30 23:28:03 +02:00
2021-08-04 17:41:51 +02:00
enableDismissTrigger ( Alert , 'close' ) ;
2018-11-13 07:41:12 +01:00
/ * *
* jQuery
* /
2015-08-15 21:19:11 +02:00
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Alert ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : button . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2022-05-13 08:07:23 +02:00
const NAME$e = 'button' ;
const DATA _KEY$9 = 'bs.button' ;
const EVENT _KEY$a = ` . ${ DATA _KEY$9 } ` ;
const DATA _API _KEY$6 = '.data-api' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _ACTIVE$3 = 'active' ;
const SELECTOR _DATA _TOGGLE$5 = '[data-bs-toggle="button"]' ;
2022-05-13 08:07:23 +02:00
const EVENT _CLICK _DATA _API$6 = ` click ${ EVENT _KEY$a } ${ DATA _API _KEY$6 } ` ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
class Button extends BaseComponent {
// Getters
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
2022-05-13 08:07:23 +02:00
return NAME$e ;
2021-03-23 17:26:54 +01:00
} // Public
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
toggle ( ) {
2020-06-16 20:50:01 +02:00
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
2021-03-23 17:26:54 +01:00
this . _element . setAttribute ( 'aria-pressed' , this . _element . classList . toggle ( CLASS _NAME _ACTIVE$3 ) ) ;
2019-01-04 17:29:45 +01:00
} // Static
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2018-11-13 07:41:12 +01:00
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Button . getOrCreateInstance ( this ) ;
2016-10-10 02:26:51 +02:00
2018-11-13 07:41:12 +01:00
if ( config === 'toggle' ) {
data [ config ] ( ) ;
2016-10-10 02:26:51 +02:00
}
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2018-11-13 07:41:12 +01:00
* /
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$6 , SELECTOR _DATA _TOGGLE$5 , event => {
2018-11-13 07:41:12 +01:00
event . preventDefault ( ) ;
2021-03-23 17:26:54 +01:00
const button = event . target . closest ( SELECTOR _DATA _TOGGLE$5 ) ;
2021-06-22 20:29:16 +02:00
const data = Button . getOrCreateInstance ( button ) ;
2019-03-01 17:31:34 +01:00
data . toggle ( ) ;
} ) ;
2018-11-13 07:41:12 +01:00
/ * *
* jQuery
2019-03-01 17:31:34 +01:00
* /
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Button ) ;
2019-03-01 17:31:34 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : dom / selector - engine . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2019-03-01 17:31:34 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2018-11-13 07:41:12 +01:00
* /
2020-06-16 20:50:01 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Constants
2021-08-04 17:41:51 +02:00
* /
2022-05-13 08:07:23 +02:00
2021-08-04 17:41:51 +02:00
const SelectorEngine = {
find ( selector , element = document . documentElement ) {
return [ ] . concat ( ... Element . prototype . querySelectorAll . call ( element , selector ) ) ;
} ,
findOne ( selector , element = document . documentElement ) {
return Element . prototype . querySelector . call ( element , selector ) ;
} ,
children ( element , selector ) {
return [ ] . concat ( ... element . children ) . filter ( child => child . matches ( selector ) ) ;
} ,
parents ( element , selector ) {
const parents = [ ] ;
2022-05-13 08:07:23 +02:00
let ancestor = element . parentNode . closest ( selector ) ;
2021-08-04 17:41:51 +02:00
2022-05-13 08:07:23 +02:00
while ( ancestor ) {
parents . push ( ancestor ) ;
ancestor = ancestor . parentNode . closest ( selector ) ;
2021-08-04 17:41:51 +02:00
}
return parents ;
} ,
prev ( element , selector ) {
let previous = element . previousElementSibling ;
while ( previous ) {
if ( previous . matches ( selector ) ) {
return [ previous ] ;
}
previous = previous . previousElementSibling ;
}
return [ ] ;
} ,
2022-05-13 08:07:23 +02:00
// TODO: this is now unused; remove later along with prev()
2021-08-04 17:41:51 +02:00
next ( element , selector ) {
let next = element . nextElementSibling ;
while ( next ) {
if ( next . matches ( selector ) ) {
return [ next ] ;
}
next = next . nextElementSibling ;
}
return [ ] ;
} ,
focusableChildren ( element ) {
2022-05-13 08:07:23 +02:00
const focusables = [ 'a' , 'button' , 'input' , 'textarea' , 'select' , 'details' , '[tabindex]' , '[contenteditable="true"]' ] . map ( selector => ` ${ selector } :not([tabindex^="-"]) ` ) . join ( ',' ) ;
2021-08-04 17:41:51 +02:00
return this . find ( focusables , element ) . filter ( el => ! isDisabled ( el ) && isVisible ( el ) ) ;
}
} ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / swipe . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2015-08-15 21:19:11 +02:00
/ * *
2018-11-13 07:41:12 +01:00
* Constants
2015-08-15 21:19:11 +02:00
* /
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
const NAME$d = 'swipe' ;
const EVENT _KEY$9 = '.bs.swipe' ;
const EVENT _TOUCHSTART = ` touchstart ${ EVENT _KEY$9 } ` ;
const EVENT _TOUCHMOVE = ` touchmove ${ EVENT _KEY$9 } ` ;
const EVENT _TOUCHEND = ` touchend ${ EVENT _KEY$9 } ` ;
const EVENT _POINTERDOWN = ` pointerdown ${ EVENT _KEY$9 } ` ;
const EVENT _POINTERUP = ` pointerup ${ EVENT _KEY$9 } ` ;
const POINTER _TYPE _TOUCH = 'touch' ;
const POINTER _TYPE _PEN = 'pen' ;
const CLASS _NAME _POINTER _EVENT = 'pointer-event' ;
2021-03-23 17:26:54 +01:00
const SWIPE _THRESHOLD = 40 ;
2022-05-13 08:07:23 +02:00
const Default$c = {
2022-07-19 17:43:58 +02:00
endCallback : null ,
2022-05-13 08:07:23 +02:00
leftCallback : null ,
2022-07-19 17:43:58 +02:00
rightCallback : null
2018-11-13 07:41:12 +01:00
} ;
2022-05-13 08:07:23 +02:00
const DefaultType$c = {
2022-07-19 17:43:58 +02:00
endCallback : '(function|null)' ,
2022-05-13 08:07:23 +02:00
leftCallback : '(function|null)' ,
2022-07-19 17:43:58 +02:00
rightCallback : '(function|null)'
2021-06-22 20:29:16 +02:00
} ;
2022-05-13 08:07:23 +02:00
/ * *
* Class definition
* /
class Swipe extends Config {
constructor ( element , config ) {
super ( ) ;
this . _element = element ;
if ( ! element || ! Swipe . isSupported ( ) ) {
return ;
}
this . _config = this . _getConfig ( config ) ;
this . _deltaX = 0 ;
this . _supportPointerEvents = Boolean ( window . PointerEvent ) ;
this . _initEvents ( ) ;
} // Getters
static get Default ( ) {
return Default$c ;
}
static get DefaultType ( ) {
return DefaultType$c ;
}
static get NAME ( ) {
return NAME$d ;
} // Public
dispose ( ) {
EventHandler . off ( this . _element , EVENT _KEY$9 ) ;
} // Private
_start ( event ) {
if ( ! this . _supportPointerEvents ) {
this . _deltaX = event . touches [ 0 ] . clientX ;
return ;
}
if ( this . _eventIsPointerPenTouch ( event ) ) {
this . _deltaX = event . clientX ;
}
}
_end ( event ) {
if ( this . _eventIsPointerPenTouch ( event ) ) {
this . _deltaX = event . clientX - this . _deltaX ;
}
this . _handleSwipe ( ) ;
execute ( this . _config . endCallback ) ;
}
_move ( event ) {
this . _deltaX = event . touches && event . touches . length > 1 ? 0 : event . touches [ 0 ] . clientX - this . _deltaX ;
}
_handleSwipe ( ) {
const absDeltaX = Math . abs ( this . _deltaX ) ;
if ( absDeltaX <= SWIPE _THRESHOLD ) {
return ;
}
const direction = absDeltaX / this . _deltaX ;
this . _deltaX = 0 ;
if ( ! direction ) {
return ;
}
execute ( direction > 0 ? this . _config . rightCallback : this . _config . leftCallback ) ;
}
_initEvents ( ) {
if ( this . _supportPointerEvents ) {
EventHandler . on ( this . _element , EVENT _POINTERDOWN , event => this . _start ( event ) ) ;
EventHandler . on ( this . _element , EVENT _POINTERUP , event => this . _end ( event ) ) ;
this . _element . classList . add ( CLASS _NAME _POINTER _EVENT ) ;
} else {
EventHandler . on ( this . _element , EVENT _TOUCHSTART , event => this . _start ( event ) ) ;
EventHandler . on ( this . _element , EVENT _TOUCHMOVE , event => this . _move ( event ) ) ;
EventHandler . on ( this . _element , EVENT _TOUCHEND , event => this . _end ( event ) ) ;
}
}
_eventIsPointerPenTouch ( event ) {
return this . _supportPointerEvents && ( event . pointerType === POINTER _TYPE _PEN || event . pointerType === POINTER _TYPE _TOUCH ) ;
} // Static
static isSupported ( ) {
return 'ontouchstart' in document . documentElement || navigator . maxTouchPoints > 0 ;
}
}
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : carousel . js
2022-05-13 08:07:23 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* Constants
* /
const NAME$c = 'carousel' ;
const DATA _KEY$8 = 'bs.carousel' ;
const EVENT _KEY$8 = ` . ${ DATA _KEY$8 } ` ;
const DATA _API _KEY$5 = '.data-api' ;
const ARROW _LEFT _KEY$1 = 'ArrowLeft' ;
const ARROW _RIGHT _KEY$1 = 'ArrowRight' ;
const TOUCHEVENT _COMPAT _WAIT = 500 ; // Time for mouse compat events to fire after touch
const ORDER _NEXT = 'next' ;
const ORDER _PREV = 'prev' ;
const DIRECTION _LEFT = 'left' ;
const DIRECTION _RIGHT = 'right' ;
const EVENT _SLIDE = ` slide ${ EVENT _KEY$8 } ` ;
const EVENT _SLID = ` slid ${ EVENT _KEY$8 } ` ;
const EVENT _KEYDOWN$1 = ` keydown ${ EVENT _KEY$8 } ` ;
const EVENT _MOUSEENTER$1 = ` mouseenter ${ EVENT _KEY$8 } ` ;
const EVENT _MOUSELEAVE$1 = ` mouseleave ${ EVENT _KEY$8 } ` ;
const EVENT _DRAG _START = ` dragstart ${ EVENT _KEY$8 } ` ;
const EVENT _LOAD _DATA _API$3 = ` load ${ EVENT _KEY$8 } ${ DATA _API _KEY$5 } ` ;
const EVENT _CLICK _DATA _API$5 = ` click ${ EVENT _KEY$8 } ${ DATA _API _KEY$5 } ` ;
const CLASS _NAME _CAROUSEL = 'carousel' ;
const CLASS _NAME _ACTIVE$2 = 'active' ;
const CLASS _NAME _SLIDE = 'slide' ;
const CLASS _NAME _END = 'carousel-item-end' ;
const CLASS _NAME _START = 'carousel-item-start' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _NEXT = 'carousel-item-next' ;
const CLASS _NAME _PREV = 'carousel-item-prev' ;
2022-05-13 08:07:23 +02:00
const SELECTOR _ACTIVE = '.active' ;
2021-03-23 17:26:54 +01:00
const SELECTOR _ITEM = '.carousel-item' ;
2022-05-13 08:07:23 +02:00
const SELECTOR _ACTIVE _ITEM = SELECTOR _ACTIVE + SELECTOR _ITEM ;
2021-03-23 17:26:54 +01:00
const SELECTOR _ITEM _IMG = '.carousel-item img' ;
const SELECTOR _INDICATORS = '.carousel-indicators' ;
const SELECTOR _DATA _SLIDE = '[data-bs-slide], [data-bs-slide-to]' ;
const SELECTOR _DATA _RIDE = '[data-bs-ride="carousel"]' ;
2022-05-13 08:07:23 +02:00
const KEY _TO _DIRECTION = {
[ ARROW _LEFT _KEY$1 ] : DIRECTION _RIGHT ,
[ ARROW _RIGHT _KEY$1 ] : DIRECTION _LEFT
} ;
const Default$b = {
interval : 5000 ,
keyboard : true ,
pause : 'hover' ,
ride : false ,
touch : true ,
wrap : true
} ;
const DefaultType$b = {
interval : '(number|boolean)' ,
2022-07-19 17:43:58 +02:00
// TODO:v6 remove boolean support
2022-05-13 08:07:23 +02:00
keyboard : 'boolean' ,
pause : '(string|boolean)' ,
2022-07-19 17:43:58 +02:00
ride : '(boolean|string)' ,
2022-05-13 08:07:23 +02:00
touch : 'boolean' ,
wrap : 'boolean'
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
class Carousel extends BaseComponent {
constructor ( element , config ) {
2022-05-13 08:07:23 +02:00
super ( element , config ) ;
2021-03-23 17:26:54 +01:00
this . _interval = null ;
this . _activeElement = null ;
this . _isSliding = false ;
this . touchTimeout = null ;
2022-05-13 08:07:23 +02:00
this . _swipeHelper = null ;
2021-03-23 17:26:54 +01:00
this . _indicatorsElement = SelectorEngine . findOne ( SELECTOR _INDICATORS , this . _element ) ;
this . _addEventListeners ( ) ;
2022-05-13 08:07:23 +02:00
if ( this . _config . ride === CLASS _NAME _CAROUSEL ) {
this . cycle ( ) ;
}
2018-11-13 07:41:12 +01:00
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
2022-05-13 08:07:23 +02:00
return Default$b ;
}
static get DefaultType ( ) {
return DefaultType$b ;
2021-03-23 17:26:54 +01:00
}
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
2022-05-13 08:07:23 +02:00
return NAME$c ;
2021-03-23 17:26:54 +01:00
} // Public
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
next ( ) {
2021-06-22 20:29:16 +02:00
this . _slide ( ORDER _NEXT ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
nextWhenVisible ( ) {
2022-05-13 08:07:23 +02:00
// FIXME TODO use `document.visibilityState`
2018-11-13 07:41:12 +01:00
// Don't call next when the page isn't visible
// or the carousel or its parent isn't visible
2019-03-01 17:31:34 +01:00
if ( ! document . hidden && isVisible ( this . _element ) ) {
2018-11-13 07:41:12 +01:00
this . next ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2021-03-23 17:26:54 +01:00
prev ( ) {
2021-06-22 20:29:16 +02:00
this . _slide ( ORDER _PREV ) ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
pause ( ) {
if ( this . _isSliding ) {
2019-03-01 17:31:34 +01:00
triggerTransitionEnd ( this . _element ) ;
2018-11-13 07:41:12 +01:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
this . _clearInterval ( ) ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
cycle ( ) {
this . _clearInterval ( ) ;
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
this . _updateInterval ( ) ;
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
this . _interval = setInterval ( ( ) => this . nextWhenVisible ( ) , this . _config . interval ) ;
}
2020-11-11 18:07:37 +01:00
2022-05-13 08:07:23 +02:00
_maybeEnableCycle ( ) {
if ( ! this . _config . ride ) {
return ;
}
if ( this . _isSliding ) {
EventHandler . one ( this . _element , EVENT _SLID , ( ) => this . cycle ( ) ) ;
return ;
2018-11-13 07:41:12 +01:00
}
2022-05-13 08:07:23 +02:00
this . cycle ( ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
to ( index ) {
2022-05-13 08:07:23 +02:00
const items = this . _getItems ( ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( index > items . length - 1 || index < 0 ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
if ( this . _isSliding ) {
2021-03-23 17:26:54 +01:00
EventHandler . one ( this . _element , EVENT _SLID , ( ) => this . to ( index ) ) ;
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const activeIndex = this . _getItemIndex ( this . _getActive ( ) ) ;
2018-11-13 07:41:12 +01:00
if ( activeIndex === index ) {
return ;
}
2018-02-19 23:50:56 +01:00
2021-03-23 17:26:54 +01:00
const order = index > activeIndex ? ORDER _NEXT : ORDER _PREV ;
2018-02-19 23:50:56 +01:00
2022-05-13 08:07:23 +02:00
this . _slide ( order , items [ index ] ) ;
2021-03-23 17:26:54 +01:00
}
2018-02-19 23:50:56 +01:00
2022-05-13 08:07:23 +02:00
dispose ( ) {
if ( this . _swipeHelper ) {
this . _swipeHelper . dispose ( ) ;
2018-11-13 07:41:12 +01:00
}
2016-11-01 05:36:10 +01:00
2022-05-13 08:07:23 +02:00
super . dispose ( ) ;
} // Private
2017-09-30 23:28:03 +02:00
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
_configAfterMerge ( config ) {
config . defaultInterval = config . interval ;
return config ;
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
_addEventListeners ( ) {
2018-11-13 07:41:12 +01:00
if ( this . _config . keyboard ) {
2022-05-13 08:07:23 +02:00
EventHandler . on ( this . _element , EVENT _KEYDOWN$1 , event => this . _keydown ( event ) ) ;
2018-11-13 07:41:12 +01:00
}
2017-09-30 23:28:03 +02:00
2018-11-13 07:41:12 +01:00
if ( this . _config . pause === 'hover' ) {
2022-05-13 08:07:23 +02:00
EventHandler . on ( this . _element , EVENT _MOUSEENTER$1 , ( ) => this . pause ( ) ) ;
EventHandler . on ( this . _element , EVENT _MOUSELEAVE$1 , ( ) => this . _maybeEnableCycle ( ) ) ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( this . _config . touch && Swipe . isSupported ( ) ) {
2019-02-11 20:15:34 +01:00
this . _addTouchEventListeners ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
_addTouchEventListeners ( ) {
2022-05-13 08:07:23 +02:00
for ( const img of SelectorEngine . find ( SELECTOR _ITEM _IMG , this . _element ) ) {
EventHandler . on ( img , EVENT _DRAG _START , event => event . preventDefault ( ) ) ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const endCallBack = ( ) => {
if ( this . _config . pause !== 'hover' ) {
return ;
} // If it's a touch-enabled device, mouseenter/leave are fired as
// part of the mouse compatibility events on first tap - the carousel
// would stop cycling until user tapped out of it;
// here, we listen for touchend, explicitly pause the carousel
// (as if it's the second time we tap on it, mouseenter compat event
// is NOT fired) and after a timeout (to allow for mouse compatibility
// events to fire) we explicitly restart cycling
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
this . pause ( ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( this . touchTimeout ) {
clearTimeout ( this . touchTimeout ) ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
this . touchTimeout = setTimeout ( ( ) => this . _maybeEnableCycle ( ) , TOUCHEVENT _COMPAT _WAIT + this . _config . interval ) ;
} ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const swipeConfig = {
leftCallback : ( ) => this . _slide ( this . _directionToOrder ( DIRECTION _LEFT ) ) ,
rightCallback : ( ) => this . _slide ( this . _directionToOrder ( DIRECTION _RIGHT ) ) ,
endCallback : endCallBack
} ;
this . _swipeHelper = new Swipe ( this . _element , swipeConfig ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
_keydown ( event ) {
2018-11-13 07:41:12 +01:00
if ( /input|textarea/i . test ( event . target . tagName ) ) {
return ;
}
2017-09-30 23:28:03 +02:00
2021-06-22 20:29:16 +02:00
const direction = KEY _TO _DIRECTION [ event . key ] ;
2021-02-10 17:14:51 +01:00
2021-06-22 20:29:16 +02:00
if ( direction ) {
2021-02-10 17:14:51 +01:00
event . preventDefault ( ) ;
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
this . _slide ( this . _directionToOrder ( direction ) ) ;
2018-11-13 07:41:12 +01:00
}
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
_getItemIndex ( element ) {
2022-05-13 08:07:23 +02:00
return this . _getItems ( ) . indexOf ( element ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_setActiveIndicatorElement ( index ) {
if ( ! this . _indicatorsElement ) {
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const activeIndicator = SelectorEngine . findOne ( SELECTOR _ACTIVE , this . _indicatorsElement ) ;
activeIndicator . classList . remove ( CLASS _NAME _ACTIVE$2 ) ;
activeIndicator . removeAttribute ( 'aria-current' ) ;
const newActiveIndicator = SelectorEngine . findOne ( ` [data-bs-slide-to=" ${ index } "] ` , this . _indicatorsElement ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
if ( newActiveIndicator ) {
newActiveIndicator . classList . add ( CLASS _NAME _ACTIVE$2 ) ;
newActiveIndicator . setAttribute ( 'aria-current' , 'true' ) ;
2018-11-13 07:41:12 +01:00
}
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
_updateInterval ( ) {
2022-05-13 08:07:23 +02:00
const element = this . _activeElement || this . _getActive ( ) ;
2020-11-11 18:07:37 +01:00
if ( ! element ) {
return ;
}
2021-03-23 17:26:54 +01:00
const elementInterval = Number . parseInt ( element . getAttribute ( 'data-bs-interval' ) , 10 ) ;
2022-05-13 08:07:23 +02:00
this . _config . interval = elementInterval || this . _config . defaultInterval ;
2021-03-23 17:26:54 +01:00
}
2020-11-11 18:07:37 +01:00
2022-05-13 08:07:23 +02:00
_slide ( order , element = null ) {
if ( this . _isSliding ) {
return ;
}
2018-09-19 06:35:40 +02:00
2022-05-13 08:07:23 +02:00
const activeElement = this . _getActive ( ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const isNext = order === ORDER _NEXT ;
2022-05-13 08:07:23 +02:00
const nextElement = element || getNextActiveElement ( this . _getItems ( ) , activeElement , isNext , this . _config . wrap ) ;
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
if ( nextElement === activeElement ) {
2018-11-13 07:41:12 +01:00
return ;
}
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
const nextElementIndex = this . _getItemIndex ( nextElement ) ;
const triggerEvent = eventName => {
return EventHandler . trigger ( this . _element , eventName , {
relatedTarget : nextElement ,
direction : this . _orderToDirection ( order ) ,
from : this . _getItemIndex ( activeElement ) ,
to : nextElementIndex
} ) ;
} ;
2021-06-22 20:29:16 +02:00
2022-05-13 08:07:23 +02:00
const slideEvent = triggerEvent ( EVENT _SLIDE ) ;
2018-03-31 22:59:37 +02:00
2019-03-01 17:31:34 +01:00
if ( slideEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
}
2018-03-31 22:59:37 +02:00
2018-11-13 07:41:12 +01:00
if ( ! activeElement || ! nextElement ) {
// Some weirdness is happening, so we bail
2022-05-13 08:07:23 +02:00
// todo: change tests that use empty divs to avoid this check
2018-11-13 07:41:12 +01:00
return ;
}
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
const isCycling = Boolean ( this . _interval ) ;
this . pause ( ) ;
2018-11-13 07:41:12 +01:00
this . _isSliding = true ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
this . _setActiveIndicatorElement ( nextElementIndex ) ;
2017-09-30 23:28:03 +02:00
2020-11-11 18:07:37 +01:00
this . _activeElement = nextElement ;
2022-05-13 08:07:23 +02:00
const directionalClassName = isNext ? CLASS _NAME _START : CLASS _NAME _END ;
const orderClassName = isNext ? CLASS _NAME _NEXT : CLASS _NAME _PREV ;
nextElement . classList . add ( orderClassName ) ;
reflow ( nextElement ) ;
activeElement . classList . add ( directionalClassName ) ;
nextElement . classList . add ( directionalClassName ) ;
2020-11-11 18:07:37 +01:00
2022-05-13 08:07:23 +02:00
const completeCallBack = ( ) => {
nextElement . classList . remove ( directionalClassName , orderClassName ) ;
2021-03-23 17:26:54 +01:00
nextElement . classList . add ( CLASS _NAME _ACTIVE$2 ) ;
2022-05-13 08:07:23 +02:00
activeElement . classList . remove ( CLASS _NAME _ACTIVE$2 , orderClassName , directionalClassName ) ;
2018-11-13 07:41:12 +01:00
this . _isSliding = false ;
2022-05-13 08:07:23 +02:00
triggerEvent ( EVENT _SLID ) ;
} ;
this . _queueCallback ( completeCallBack , activeElement , this . _isAnimated ( ) ) ;
2018-11-13 07:41:12 +01:00
if ( isCycling ) {
this . cycle ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2022-05-13 08:07:23 +02:00
_isAnimated ( ) {
return this . _element . classList . contains ( CLASS _NAME _SLIDE ) ;
}
_getActive ( ) {
return SelectorEngine . findOne ( SELECTOR _ACTIVE _ITEM , this . _element ) ;
}
_getItems ( ) {
return SelectorEngine . find ( SELECTOR _ITEM , this . _element ) ;
}
_clearInterval ( ) {
if ( this . _interval ) {
clearInterval ( this . _interval ) ;
this . _interval = null ;
2021-03-23 17:26:54 +01:00
}
2022-05-13 08:07:23 +02:00
}
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
_directionToOrder ( direction ) {
2021-03-23 17:26:54 +01:00
if ( isRTL ( ) ) {
2021-05-05 21:32:12 +02:00
return direction === DIRECTION _LEFT ? ORDER _PREV : ORDER _NEXT ;
2021-03-23 17:26:54 +01:00
}
2021-05-05 21:32:12 +02:00
return direction === DIRECTION _LEFT ? ORDER _NEXT : ORDER _PREV ;
2021-03-23 17:26:54 +01:00
}
_orderToDirection ( order ) {
if ( isRTL ( ) ) {
2021-05-05 21:32:12 +02:00
return order === ORDER _PREV ? DIRECTION _LEFT : DIRECTION _RIGHT ;
2021-03-23 17:26:54 +01:00
}
2021-05-05 21:32:12 +02:00
return order === ORDER _PREV ? DIRECTION _RIGHT : DIRECTION _LEFT ;
2019-01-04 17:29:45 +01:00
} // Static
2015-08-15 21:19:11 +02:00
2015-08-19 04:22:46 +02:00
2022-05-13 08:07:23 +02:00
static jQueryInterface ( config ) {
return this . each ( function ( ) {
const data = Carousel . getOrCreateInstance ( this , config ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( typeof config === 'number' ) {
data . to ( config ) ;
return ;
2018-03-31 22:59:37 +02:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
if ( typeof config === 'string' ) {
if ( data [ config ] === undefined || config . startsWith ( '_' ) || config === 'constructor' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
data [ config ] ( ) ;
}
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
}
/ * *
* Data API implementation
* /
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$5 , SELECTOR _DATA _SLIDE , function ( event ) {
const target = getElementFromSelector ( this ) ;
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
if ( ! target || ! target . classList . contains ( CLASS _NAME _CAROUSEL ) ) {
return ;
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
event . preventDefault ( ) ;
const carousel = Carousel . getOrCreateInstance ( target ) ;
const slideIndex = this . getAttribute ( 'data-bs-slide-to' ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( slideIndex ) {
carousel . to ( slideIndex ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
carousel . _maybeEnableCycle ( ) ;
return ;
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
if ( Manipulator . getDataAttribute ( this , 'slide' ) === 'next' ) {
carousel . next ( ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
carousel . _maybeEnableCycle ( ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
return ;
}
carousel . prev ( ) ;
carousel . _maybeEnableCycle ( ) ;
} ) ;
EventHandler . on ( window , EVENT _LOAD _DATA _API$3 , ( ) => {
2021-03-23 17:26:54 +01:00
const carousels = SelectorEngine . find ( SELECTOR _DATA _RIDE ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
for ( const carousel of carousels ) {
Carousel . getOrCreateInstance ( carousel ) ;
2018-11-13 07:41:12 +01:00
}
} ) ;
/ * *
* jQuery
* /
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Carousel ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : collapse . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2022-05-13 08:07:23 +02:00
const NAME$b = 'collapse' ;
const DATA _KEY$7 = 'bs.collapse' ;
const EVENT _KEY$7 = ` . ${ DATA _KEY$7 } ` ;
const DATA _API _KEY$4 = '.data-api' ;
const EVENT _SHOW$6 = ` show ${ EVENT _KEY$7 } ` ;
const EVENT _SHOWN$6 = ` shown ${ EVENT _KEY$7 } ` ;
const EVENT _HIDE$6 = ` hide ${ EVENT _KEY$7 } ` ;
const EVENT _HIDDEN$6 = ` hidden ${ EVENT _KEY$7 } ` ;
const EVENT _CLICK _DATA _API$4 = ` click ${ EVENT _KEY$7 } ${ DATA _API _KEY$4 } ` ;
2021-08-04 17:41:51 +02:00
const CLASS _NAME _SHOW$7 = 'show' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _COLLAPSE = 'collapse' ;
const CLASS _NAME _COLLAPSING = 'collapsing' ;
const CLASS _NAME _COLLAPSED = 'collapsed' ;
2021-10-05 17:50:18 +02:00
const CLASS _NAME _DEEPER _CHILDREN = ` :scope . ${ CLASS _NAME _COLLAPSE } . ${ CLASS _NAME _COLLAPSE } ` ;
2021-08-04 17:41:51 +02:00
const CLASS _NAME _HORIZONTAL = 'collapse-horizontal' ;
2021-03-23 17:26:54 +01:00
const WIDTH = 'width' ;
const HEIGHT = 'height' ;
2021-09-07 17:37:44 +02:00
const SELECTOR _ACTIVES = '.collapse.show, .collapse.collapsing' ;
2021-03-23 17:26:54 +01:00
const SELECTOR _DATA _TOGGLE$4 = '[data-bs-toggle="collapse"]' ;
2022-05-13 08:07:23 +02:00
const Default$a = {
2022-07-19 17:43:58 +02:00
parent : null ,
toggle : true
2022-05-13 08:07:23 +02:00
} ;
const DefaultType$a = {
2022-07-19 17:43:58 +02:00
parent : '(null|element)' ,
toggle : 'boolean'
2022-05-13 08:07:23 +02:00
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
class Collapse extends BaseComponent {
constructor ( element , config ) {
2022-05-13 08:07:23 +02:00
super ( element , config ) ;
2021-03-23 17:26:54 +01:00
this . _isTransitioning = false ;
2021-08-04 17:41:51 +02:00
this . _triggerArray = [ ] ;
2021-03-23 17:26:54 +01:00
const toggleList = SelectorEngine . find ( SELECTOR _DATA _TOGGLE$4 ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
for ( const elem of toggleList ) {
2021-03-23 17:26:54 +01:00
const selector = getSelectorFromElement ( elem ) ;
2022-05-13 08:07:23 +02:00
const filterElement = SelectorEngine . find ( selector ) . filter ( foundElement => foundElement === this . _element ) ;
2017-05-16 09:59:44 +02:00
2019-03-01 17:31:34 +01:00
if ( selector !== null && filterElement . length ) {
2021-03-23 17:26:54 +01:00
this . _triggerArray . push ( elem ) ;
2018-03-31 22:59:37 +02:00
}
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
this . _initializeChildren ( ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
if ( ! this . _config . parent ) {
2021-08-04 17:41:51 +02:00
this . _addAriaAndCollapsedClass ( this . _triggerArray , this . _isShown ( ) ) ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
if ( this . _config . toggle ) {
this . toggle ( ) ;
2018-11-13 07:41:12 +01:00
}
} // Getters
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static get Default ( ) {
2022-05-13 08:07:23 +02:00
return Default$a ;
}
static get DefaultType ( ) {
return DefaultType$a ;
2021-03-23 17:26:54 +01:00
}
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
2022-05-13 08:07:23 +02:00
return NAME$b ;
2021-03-23 17:26:54 +01:00
} // Public
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
toggle ( ) {
2021-08-04 17:41:51 +02:00
if ( this . _isShown ( ) ) {
2018-11-13 07:41:12 +01:00
this . hide ( ) ;
} else {
this . show ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
show ( ) {
2021-08-04 17:41:51 +02:00
if ( this . _isTransitioning || this . _isShown ( ) ) {
2018-11-13 07:41:12 +01:00
return ;
}
2018-09-17 21:34:34 +02:00
2022-05-13 08:07:23 +02:00
let activeChildren = [ ] ; // find active children
2017-09-30 23:28:03 +02:00
2021-08-04 17:41:51 +02:00
if ( this . _config . parent ) {
2022-05-13 08:07:23 +02:00
activeChildren = this . _getFirstLevelChildren ( SELECTOR _ACTIVES ) . filter ( element => element !== this . _element ) . map ( element => Collapse . getOrCreateInstance ( element , {
toggle : false
} ) ) ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( activeChildren . length && activeChildren [ 0 ] . _isTransitioning ) {
return ;
2018-11-13 07:41:12 +01:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
const startEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$6 ) ;
2017-09-30 23:28:03 +02:00
2019-03-01 17:31:34 +01:00
if ( startEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
for ( const activeInstance of activeChildren ) {
activeInstance . hide ( ) ;
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const dimension = this . _getDimension ( ) ;
2015-08-15 21:19:11 +02:00
2020-03-28 11:29:08 +01:00
this . _element . classList . remove ( CLASS _NAME _COLLAPSE ) ;
2019-03-01 17:31:34 +01:00
2020-03-28 11:29:08 +01:00
this . _element . classList . add ( CLASS _NAME _COLLAPSING ) ;
2019-03-01 17:31:34 +01:00
2018-11-13 07:41:12 +01:00
this . _element . style [ dimension ] = 0 ;
2021-08-04 17:41:51 +02:00
this . _addAriaAndCollapsedClass ( this . _triggerArray , true ) ;
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
this . _isTransitioning = true ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
2021-08-04 17:41:51 +02:00
this . _isTransitioning = false ;
2021-03-23 17:26:54 +01:00
this . _element . classList . remove ( CLASS _NAME _COLLAPSING ) ;
2019-03-01 17:31:34 +01:00
2021-08-04 17:41:51 +02:00
this . _element . classList . add ( CLASS _NAME _COLLAPSE , CLASS _NAME _SHOW$7 ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
this . _element . style [ dimension ] = '' ;
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , EVENT _SHOWN$6 ) ;
2018-03-31 22:59:37 +02:00
} ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const capitalizedDimension = dimension [ 0 ] . toUpperCase ( ) + dimension . slice ( 1 ) ;
const scrollSize = ` scroll ${ capitalizedDimension } ` ;
2021-05-13 18:22:20 +02:00
this . _queueCallback ( complete , this . _element , true ) ;
2021-03-23 17:26:54 +01:00
this . _element . style [ dimension ] = ` ${ this . _element [ scrollSize ] } px ` ;
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
hide ( ) {
2021-08-04 17:41:51 +02:00
if ( this . _isTransitioning || ! this . _isShown ( ) ) {
2018-11-13 07:41:12 +01:00
return ;
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
const startEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$6 ) ;
2015-08-15 21:19:11 +02:00
2019-03-01 17:31:34 +01:00
if ( startEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const dimension = this . _getDimension ( ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
this . _element . style [ dimension ] = ` ${ this . _element . getBoundingClientRect ( ) [ dimension ] } px ` ;
2019-03-01 17:31:34 +01:00
reflow ( this . _element ) ;
2020-03-28 11:29:08 +01:00
this . _element . classList . add ( CLASS _NAME _COLLAPSING ) ;
2019-03-01 17:31:34 +01:00
2021-08-04 17:41:51 +02:00
this . _element . classList . remove ( CLASS _NAME _COLLAPSE , CLASS _NAME _SHOW$7 ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
for ( const trigger of this . _triggerArray ) {
const element = getElementFromSelector ( trigger ) ;
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
if ( element && ! this . _isShown ( element ) ) {
2021-08-04 17:41:51 +02:00
this . _addAriaAndCollapsedClass ( [ trigger ] , false ) ;
2017-06-15 05:44:32 +02:00
}
2018-11-13 07:41:12 +01:00
}
2017-09-30 23:28:03 +02:00
2021-08-04 17:41:51 +02:00
this . _isTransitioning = true ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
2021-08-04 17:41:51 +02:00
this . _isTransitioning = false ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
this . _element . classList . remove ( CLASS _NAME _COLLAPSING ) ;
2019-03-01 17:31:34 +01:00
2021-03-23 17:26:54 +01:00
this . _element . classList . add ( CLASS _NAME _COLLAPSE ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , EVENT _HIDDEN$6 ) ;
2018-03-31 22:59:37 +02:00
} ;
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
this . _element . style [ dimension ] = '' ;
2021-05-13 18:22:20 +02:00
this . _queueCallback ( complete , this . _element , true ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
_isShown ( element = this . _element ) {
return element . classList . contains ( CLASS _NAME _SHOW$7 ) ;
2019-01-04 17:29:45 +01:00
} // Private
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
_configAfterMerge ( config ) {
2018-11-13 07:41:12 +01:00
config . toggle = Boolean ( config . toggle ) ; // Coerce string values
2016-10-10 02:26:51 +02:00
2021-08-04 17:41:51 +02:00
config . parent = getElement ( config . parent ) ;
2018-11-13 07:41:12 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2021-03-23 17:26:54 +01:00
_getDimension ( ) {
2021-08-04 17:41:51 +02:00
return this . _element . classList . contains ( CLASS _NAME _HORIZONTAL ) ? WIDTH : HEIGHT ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2021-08-04 17:41:51 +02:00
_initializeChildren ( ) {
if ( ! this . _config . parent ) {
return ;
}
2022-05-13 08:07:23 +02:00
const children = this . _getFirstLevelChildren ( SELECTOR _DATA _TOGGLE$4 ) ;
for ( const element of children ) {
2021-03-23 17:26:54 +01:00
const selected = getElementFromSelector ( element ) ;
2019-07-24 08:13:50 +02:00
2021-08-04 17:41:51 +02:00
if ( selected ) {
this . _addAriaAndCollapsedClass ( [ element ] , this . _isShown ( selected ) ) ;
}
2022-05-13 08:07:23 +02:00
}
}
_getFirstLevelChildren ( selector ) {
const children = SelectorEngine . find ( CLASS _NAME _DEEPER _CHILDREN , this . _config . parent ) ; // remove children if greater depth
return SelectorEngine . find ( selector , this . _config . parent ) . filter ( element => ! children . includes ( element ) ) ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2021-08-04 17:41:51 +02:00
_addAriaAndCollapsedClass ( triggerArray , isOpen ) {
if ( ! triggerArray . length ) {
2020-09-14 17:12:06 +02:00
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
for ( const element of triggerArray ) {
element . classList . toggle ( CLASS _NAME _COLLAPSED , ! isOpen ) ;
element . setAttribute ( 'aria-expanded' , isOpen ) ;
}
2019-01-04 17:29:45 +01:00
} // Static
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
static jQueryInterface ( config ) {
2022-05-13 08:07:23 +02:00
const _config = { } ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
if ( typeof config === 'string' && /show|hide/ . test ( config ) ) {
_config . toggle = false ;
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
return this . each ( function ( ) {
2021-08-04 17:41:51 +02:00
const data = Collapse . getOrCreateInstance ( this , _config ) ;
2017-09-30 23:28:03 +02:00
2021-08-04 17:41:51 +02:00
if ( typeof config === 'string' ) {
if ( typeof data [ config ] === 'undefined' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
}
data [ config ] ( ) ;
}
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2018-11-13 07:41:12 +01:00
* /
2017-09-30 23:28:03 +02:00
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$4 , SELECTOR _DATA _TOGGLE$4 , function ( event ) {
2018-11-13 07:41:12 +01:00
// preventDefault only for <a> elements (which change the URL) not inside the collapsible element
2021-02-10 17:14:51 +01:00
if ( event . target . tagName === 'A' || event . delegateTarget && event . delegateTarget . tagName === 'A' ) {
2018-11-13 07:41:12 +01:00
event . preventDefault ( ) ;
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
const selector = getSelectorFromElement ( this ) ;
const selectorElements = SelectorEngine . find ( selector ) ;
2022-05-13 08:07:23 +02:00
for ( const element of selectorElements ) {
2021-08-04 17:41:51 +02:00
Collapse . getOrCreateInstance ( element , {
toggle : false
} ) . toggle ( ) ;
2022-05-13 08:07:23 +02:00
}
2018-11-13 07:41:12 +01:00
} ) ;
/ * *
* jQuery
* /
2015-08-15 21:19:11 +02:00
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Collapse ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : dropdown . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2022-05-13 08:07:23 +02:00
const NAME$a = 'dropdown' ;
const DATA _KEY$6 = 'bs.dropdown' ;
const EVENT _KEY$6 = ` . ${ DATA _KEY$6 } ` ;
const DATA _API _KEY$3 = '.data-api' ;
2021-03-23 17:26:54 +01:00
const ESCAPE _KEY$2 = 'Escape' ;
2021-08-04 17:41:51 +02:00
const TAB _KEY$1 = 'Tab' ;
2022-05-13 08:07:23 +02:00
const ARROW _UP _KEY$1 = 'ArrowUp' ;
const ARROW _DOWN _KEY$1 = 'ArrowDown' ;
2021-03-23 17:26:54 +01:00
const RIGHT _MOUSE _BUTTON = 2 ; // MouseEvent.button value for the secondary button, usually the right button
2022-05-13 08:07:23 +02:00
const EVENT _HIDE$5 = ` hide ${ EVENT _KEY$6 } ` ;
const EVENT _HIDDEN$5 = ` hidden ${ EVENT _KEY$6 } ` ;
const EVENT _SHOW$5 = ` show ${ EVENT _KEY$6 } ` ;
const EVENT _SHOWN$5 = ` shown ${ EVENT _KEY$6 } ` ;
const EVENT _CLICK _DATA _API$3 = ` click ${ EVENT _KEY$6 } ${ DATA _API _KEY$3 } ` ;
const EVENT _KEYDOWN _DATA _API = ` keydown ${ EVENT _KEY$6 } ${ DATA _API _KEY$3 } ` ;
const EVENT _KEYUP _DATA _API = ` keyup ${ EVENT _KEY$6 } ${ DATA _API _KEY$3 } ` ;
2021-08-04 17:41:51 +02:00
const CLASS _NAME _SHOW$6 = 'show' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _DROPUP = 'dropup' ;
const CLASS _NAME _DROPEND = 'dropend' ;
const CLASS _NAME _DROPSTART = 'dropstart' ;
2022-05-13 08:07:23 +02:00
const CLASS _NAME _DROPUP _CENTER = 'dropup-center' ;
const CLASS _NAME _DROPDOWN _CENTER = 'dropdown-center' ;
const SELECTOR _DATA _TOGGLE$3 = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)' ;
const SELECTOR _DATA _TOGGLE _SHOWN = ` ${ SELECTOR _DATA _TOGGLE$3 } . ${ CLASS _NAME _SHOW$6 } ` ;
2021-03-23 17:26:54 +01:00
const SELECTOR _MENU = '.dropdown-menu' ;
2022-05-13 08:07:23 +02:00
const SELECTOR _NAVBAR = '.navbar' ;
2021-03-23 17:26:54 +01:00
const SELECTOR _NAVBAR _NAV = '.navbar-nav' ;
const SELECTOR _VISIBLE _ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' ;
const PLACEMENT _TOP = isRTL ( ) ? 'top-end' : 'top-start' ;
const PLACEMENT _TOPEND = isRTL ( ) ? 'top-start' : 'top-end' ;
const PLACEMENT _BOTTOM = isRTL ( ) ? 'bottom-end' : 'bottom-start' ;
const PLACEMENT _BOTTOMEND = isRTL ( ) ? 'bottom-start' : 'bottom-end' ;
const PLACEMENT _RIGHT = isRTL ( ) ? 'left-start' : 'right-start' ;
const PLACEMENT _LEFT = isRTL ( ) ? 'right-start' : 'left-start' ;
2022-05-13 08:07:23 +02:00
const PLACEMENT _TOPCENTER = 'top' ;
const PLACEMENT _BOTTOMCENTER = 'bottom' ;
const Default$9 = {
2022-07-19 17:43:58 +02:00
autoClose : true ,
2020-12-07 16:50:24 +01:00
boundary : 'clippingParents' ,
2019-08-27 15:03:21 +02:00
display : 'dynamic' ,
2022-07-19 17:43:58 +02:00
offset : [ 0 , 2 ] ,
2021-05-05 21:32:12 +02:00
popperConfig : null ,
2022-07-19 17:43:58 +02:00
reference : 'toggle'
2018-11-13 07:41:12 +01:00
} ;
2022-05-13 08:07:23 +02:00
const DefaultType$9 = {
2022-07-19 17:43:58 +02:00
autoClose : '(boolean|string)' ,
2018-11-13 07:41:12 +01:00
boundary : '(string|element)' ,
2019-08-27 15:03:21 +02:00
display : 'string' ,
2022-07-19 17:43:58 +02:00
offset : '(array|string|function)' ,
2021-05-05 21:32:12 +02:00
popperConfig : '(null|object|function)' ,
2022-07-19 17:43:58 +02:00
reference : '(string|element|object)'
2018-11-13 07:41:12 +01:00
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
class Dropdown extends BaseComponent {
constructor ( element , config ) {
2022-05-13 08:07:23 +02:00
super ( element , config ) ;
2021-03-23 17:26:54 +01:00
this . _popper = null ;
2022-05-13 08:07:23 +02:00
this . _parent = this . _element . parentNode ; // dropdown wrapper
this . _menu = SelectorEngine . findOne ( SELECTOR _MENU , this . _parent ) ;
2021-03-23 17:26:54 +01:00
this . _inNavbar = this . _detectNavbar ( ) ;
} // Getters
2020-12-03 15:18:59 +01:00
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
static get Default ( ) {
2022-05-13 08:07:23 +02:00
return Default$9 ;
2021-03-23 17:26:54 +01:00
}
2019-03-01 17:31:34 +01:00
2021-03-23 17:26:54 +01:00
static get DefaultType ( ) {
2022-05-13 08:07:23 +02:00
return DefaultType$9 ;
2021-03-23 17:26:54 +01:00
}
2018-03-31 22:59:37 +02:00
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
2022-05-13 08:07:23 +02:00
return NAME$a ;
2021-03-23 17:26:54 +01:00
} // Public
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
toggle ( ) {
2021-08-04 17:41:51 +02:00
return this . _isShown ( ) ? this . hide ( ) : this . show ( ) ;
2021-03-23 17:26:54 +01:00
}
2019-08-27 15:03:21 +02:00
2021-03-23 17:26:54 +01:00
show ( ) {
2022-05-13 08:07:23 +02:00
if ( isDisabled ( this . _element ) || this . _isShown ( ) ) {
2019-08-27 15:03:21 +02:00
return ;
}
2021-03-23 17:26:54 +01:00
const relatedTarget = {
2018-11-13 07:41:12 +01:00
relatedTarget : this . _element
} ;
2022-05-13 08:07:23 +02:00
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$5 , relatedTarget ) ;
2017-09-30 23:28:03 +02:00
2019-03-01 17:31:34 +01:00
if ( showEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
2021-08-04 17:41:51 +02:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
this . _createPopper ( ) ; // If this is a touch-enabled device we add extra
2018-11-13 07:41:12 +01:00
// empty mouseover listeners to the body's immediate children;
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
2017-12-23 01:21:54 +01:00
2017-05-16 09:59:44 +02:00
2022-05-13 08:07:23 +02:00
if ( 'ontouchstart' in document . documentElement && ! this . _parent . closest ( SELECTOR _NAVBAR _NAV ) ) {
for ( const element of [ ] . concat ( ... document . body . children ) ) {
EventHandler . on ( element , 'mouseover' , noop ) ;
}
2018-11-13 07:41:12 +01:00
}
2017-09-30 23:28:03 +02:00
2018-11-13 07:41:12 +01:00
this . _element . focus ( ) ;
2017-10-30 20:48:13 +01:00
2018-11-13 07:41:12 +01:00
this . _element . setAttribute ( 'aria-expanded' , true ) ;
2017-03-20 03:03:32 +01:00
2021-08-04 17:41:51 +02:00
this . _menu . classList . add ( CLASS _NAME _SHOW$6 ) ;
2020-10-28 04:45:48 +01:00
2021-08-04 17:41:51 +02:00
this . _element . classList . add ( CLASS _NAME _SHOW$6 ) ;
2020-10-28 04:45:48 +01:00
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , EVENT _SHOWN$5 , relatedTarget ) ;
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
hide ( ) {
2022-05-13 08:07:23 +02:00
if ( isDisabled ( this . _element ) || ! this . _isShown ( ) ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const relatedTarget = {
2018-11-13 07:41:12 +01:00
relatedTarget : this . _element
} ;
2020-10-28 04:45:48 +01:00
2021-05-05 21:32:12 +02:00
this . _completeHide ( relatedTarget ) ;
2021-03-23 17:26:54 +01:00
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2019-08-27 15:03:21 +02:00
if ( this . _popper ) {
2018-11-13 07:41:12 +01:00
this . _popper . destroy ( ) ;
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
super . dispose ( ) ;
}
update ( ) {
2018-11-13 07:41:12 +01:00
this . _inNavbar = this . _detectNavbar ( ) ;
2017-05-27 05:20:10 +02:00
2019-08-27 15:03:21 +02:00
if ( this . _popper ) {
2020-12-07 16:50:24 +01:00
this . _popper . update ( ) ;
2018-11-13 07:41:12 +01:00
}
2019-01-04 17:29:45 +01:00
} // Private
2017-09-30 23:28:03 +02:00
2017-05-27 05:20:10 +02:00
2021-05-05 21:32:12 +02:00
_completeHide ( relatedTarget ) {
2022-05-13 08:07:23 +02:00
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$5 , relatedTarget ) ;
2021-05-05 21:32:12 +02:00
if ( hideEvent . defaultPrevented ) {
return ;
} // If this is a touch-enabled device we remove the extra
// empty mouseover listeners we added for iOS support
if ( 'ontouchstart' in document . documentElement ) {
2022-05-13 08:07:23 +02:00
for ( const element of [ ] . concat ( ... document . body . children ) ) {
EventHandler . off ( element , 'mouseover' , noop ) ;
}
2021-05-05 21:32:12 +02:00
}
if ( this . _popper ) {
this . _popper . destroy ( ) ;
}
2021-08-04 17:41:51 +02:00
this . _menu . classList . remove ( CLASS _NAME _SHOW$6 ) ;
2021-05-05 21:32:12 +02:00
2021-08-04 17:41:51 +02:00
this . _element . classList . remove ( CLASS _NAME _SHOW$6 ) ;
2021-05-05 21:32:12 +02:00
this . _element . setAttribute ( 'aria-expanded' , 'false' ) ;
Manipulator . removeDataAttribute ( this . _menu , 'popper' ) ;
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , EVENT _HIDDEN$5 , relatedTarget ) ;
2021-05-05 21:32:12 +02:00
}
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
2022-05-13 08:07:23 +02:00
config = super . _getConfig ( config ) ;
2021-02-10 17:14:51 +01:00
if ( typeof config . reference === 'object' && ! isElement ( config . reference ) && typeof config . reference . getBoundingClientRect !== 'function' ) {
// Popper virtual elements require a getBoundingClientRect method
2022-05-13 08:07:23 +02:00
throw new TypeError ( ` ${ NAME$a . toUpperCase ( ) } : Option "reference" provided type "object" without a required "getBoundingClientRect" method. ` ) ;
2021-02-10 17:14:51 +01:00
}
2018-11-13 07:41:12 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2017-10-16 00:51:44 +02:00
2022-05-13 08:07:23 +02:00
_createPopper ( ) {
2021-08-04 17:41:51 +02:00
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' ) {
2022-05-13 08:07:23 +02:00
referenceElement = this . _parent ;
2021-08-04 17:41:51 +02:00
} 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 ( ) ;
this . _popper = Popper _ _namespace . createPopper ( referenceElement , this . _menu , popperConfig ) ;
}
2022-05-13 08:07:23 +02:00
_isShown ( ) {
return this . _menu . classList . contains ( CLASS _NAME _SHOW$6 ) ;
2021-03-23 17:26:54 +01:00
}
2018-02-19 23:50:56 +01:00
2021-03-23 17:26:54 +01:00
_getPlacement ( ) {
2022-05-13 08:07:23 +02:00
const parentDropdown = this . _parent ;
2018-02-19 23:50:56 +01:00
2020-12-07 16:50:24 +01:00
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPEND ) ) {
return PLACEMENT _RIGHT ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2020-12-07 16:50:24 +01:00
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPSTART ) ) {
return PLACEMENT _LEFT ;
2022-05-13 08:07:23 +02:00
}
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPUP _CENTER ) ) {
return PLACEMENT _TOPCENTER ;
}
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPDOWN _CENTER ) ) {
return PLACEMENT _BOTTOMCENTER ;
2020-12-07 16:50:24 +01:00
} // We need to trim the value because custom properties can also include spaces
2017-09-30 23:28:03 +02:00
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
const isEnd = getComputedStyle ( this . _menu ) . getPropertyValue ( '--bs-position' ) . trim ( ) === 'end' ;
2015-08-15 21:19:11 +02:00
2020-12-07 16:50:24 +01:00
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPUP ) ) {
return isEnd ? PLACEMENT _TOPEND : PLACEMENT _TOP ;
2018-11-13 07:41:12 +01:00
}
2018-03-31 22:59:37 +02:00
2020-12-07 16:50:24 +01:00
return isEnd ? PLACEMENT _BOTTOMEND : PLACEMENT _BOTTOM ;
2021-03-23 17:26:54 +01:00
}
2019-02-11 20:15:34 +01:00
2021-03-23 17:26:54 +01:00
_detectNavbar ( ) {
2022-05-13 08:07:23 +02:00
return this . _element . closest ( SELECTOR _NAVBAR ) !== null ;
2021-03-23 17:26:54 +01:00
}
2021-02-10 17:14:51 +01:00
2021-03-23 17:26:54 +01:00
_getOffset ( ) {
const {
offset
} = this . _config ;
2021-02-10 17:14:51 +01:00
if ( typeof offset === 'string' ) {
2022-05-13 08:07:23 +02:00
return offset . split ( ',' ) . map ( value => Number . parseInt ( value , 10 ) ) ;
2021-02-10 17:14:51 +01:00
}
if ( typeof offset === 'function' ) {
2021-03-23 17:26:54 +01:00
return popperData => offset ( popperData , this . _element ) ;
2021-02-10 17:14:51 +01:00
}
return offset ;
2021-03-23 17:26:54 +01:00
}
2021-02-10 17:14:51 +01:00
2021-03-23 17:26:54 +01:00
_getPopperConfig ( ) {
const defaultBsPopperConfig = {
2018-11-13 07:41:12 +01:00
placement : this . _getPlacement ( ) ,
2020-12-07 16:50:24 +01:00
modifiers : [ {
name : 'preventOverflow' ,
options : {
2021-02-10 17:14:51 +01:00
boundary : this . _config . boundary
}
} , {
name : 'offset' ,
options : {
offset : this . _getOffset ( )
2016-10-10 02:26:51 +02:00
}
2020-12-07 16:50:24 +01:00
} ]
2022-05-13 08:07:23 +02:00
} ; // Disable Popper if we have a static display or Dropdown is in Navbar
if ( this . _inNavbar || this . _config . display === 'static' ) {
Manipulator . setDataAttribute ( this . _menu , 'popper' , 'static' ) ; // todo:v6 remove
2015-08-15 21:19:11 +02:00
2021-02-10 17:14:51 +01:00
defaultBsPopperConfig . modifiers = [ {
2020-12-07 16:50:24 +01:00
name : 'applyStyles' ,
2018-11-13 07:41:12 +01:00
enabled : false
2020-12-07 16:50:24 +01:00
} ] ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
return { ... defaultBsPopperConfig ,
... ( typeof this . _config . popperConfig === 'function' ? this . _config . popperConfig ( defaultBsPopperConfig ) : this . _config . popperConfig )
} ;
2021-05-05 21:32:12 +02:00
}
2021-06-22 20:29:16 +02:00
_selectMenuItem ( {
key ,
target
} ) {
2022-05-13 08:07:23 +02:00
const items = SelectorEngine . find ( SELECTOR _VISIBLE _ITEMS , this . _menu ) . filter ( element => isVisible ( element ) ) ;
2021-05-05 21:32:12 +02:00
if ( ! items . length ) {
return ;
2021-06-22 20:29:16 +02:00
} // 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
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
getNextActiveElement ( items , target , key === ARROW _DOWN _KEY$1 , ! items . includes ( target ) ) . focus ( ) ;
2019-01-04 17:29:45 +01:00
} // Static
2017-09-30 23:28:03 +02:00
2018-07-12 06:42:55 +02:00
2021-08-04 17:41:51 +02:00
static jQueryInterface ( config ) {
return this . each ( function ( ) {
const data = Dropdown . getOrCreateInstance ( this , config ) ;
if ( typeof config !== 'string' ) {
return ;
}
2019-03-01 17:31:34 +01:00
if ( typeof data [ config ] === 'undefined' ) {
2021-03-23 17:26:54 +01:00
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2018-11-13 07:41:12 +01:00
}
2017-05-16 09:59:44 +02:00
2019-03-01 17:31:34 +01:00
data [ config ] ( ) ;
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static clearMenus ( event ) {
2022-05-13 08:07:23 +02:00
if ( event . button === RIGHT _MOUSE _BUTTON || event . type === 'keyup' && event . key !== TAB _KEY$1 ) {
2021-05-13 18:22:20 +02:00
return ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const openToggles = SelectorEngine . find ( SELECTOR _DATA _TOGGLE _SHOWN ) ;
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
for ( const toggle of openToggles ) {
const context = Dropdown . getInstance ( toggle ) ;
2017-09-30 23:28:03 +02:00
2021-05-05 21:32:12 +02:00
if ( ! context || context . _config . autoClose === false ) {
2018-11-13 07:41:12 +01:00
continue ;
2018-03-31 22:59:37 +02:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const composedPath = event . composedPath ( ) ;
const isMenuTarget = composedPath . includes ( context . _menu ) ;
if ( composedPath . includes ( context . _element ) || context . _config . autoClose === 'inside' && ! isMenuTarget || context . _config . autoClose === 'outside' && isMenuTarget ) {
continue ;
} // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
if ( context . _menu . contains ( event . target ) && ( event . type === 'keyup' && event . key === TAB _KEY$1 || /input|select|option|textarea|form/i . test ( event . target . tagName ) ) ) {
2018-11-13 07:41:12 +01:00
continue ;
}
2017-12-31 04:41:36 +01:00
2021-05-05 21:32:12 +02:00
const relatedTarget = {
relatedTarget : context . _element
} ;
2022-05-13 08:07:23 +02:00
if ( event . type === 'click' ) {
relatedTarget . clickEvent = event ;
2019-08-27 15:03:21 +02:00
}
2021-05-05 21:32:12 +02:00
context . _completeHide ( relatedTarget ) ;
2018-11-13 07:41:12 +01:00
}
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static dataApiKeydownHandler ( event ) {
2022-05-13 08:07:23 +02:00
// If not an UP | DOWN | ESCAPE key => not a dropdown command
// If input/textarea && if key is other than ESCAPE => not a dropdown command
const isInput = /input|textarea/i . test ( event . target . tagName ) ;
const isEscapeEvent = event . key === ESCAPE _KEY$2 ;
const isUpOrDownEvent = [ ARROW _UP _KEY$1 , ARROW _DOWN _KEY$1 ] . includes ( event . key ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( ! isUpOrDownEvent && ! isEscapeEvent ) {
2021-05-05 21:32:12 +02:00
return ;
}
2022-05-13 08:07:23 +02:00
if ( isInput && ! isEscapeEvent ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-19 04:22:46 +02:00
2022-05-13 08:07:23 +02:00
event . preventDefault ( ) ;
const getToggleButton = SelectorEngine . findOne ( SELECTOR _DATA _TOGGLE$3 , event . delegateTarget . parentNode ) ;
2021-08-04 17:41:51 +02:00
const instance = Dropdown . getOrCreateInstance ( getToggleButton ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( isUpOrDownEvent ) {
event . stopPropagation ( ) ;
instance . show ( ) ;
2021-06-22 20:29:16 +02:00
2021-08-04 17:41:51 +02:00
instance . _selectMenuItem ( event ) ;
2021-06-22 20:29:16 +02:00
2021-02-10 17:14:51 +01:00
return ;
}
2022-05-13 08:07:23 +02:00
if ( instance . _isShown ( ) ) {
// else is escape and we check if it is shown
event . stopPropagation ( ) ;
instance . hide ( ) ;
getToggleButton . focus ( ) ;
2018-11-13 07:41:12 +01:00
}
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2018-11-13 07:41:12 +01:00
* /
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _KEYDOWN _DATA _API , SELECTOR _DATA _TOGGLE$3 , Dropdown . dataApiKeydownHandler ) ;
2020-03-28 11:29:08 +01:00
EventHandler . on ( document , EVENT _KEYDOWN _DATA _API , SELECTOR _MENU , Dropdown . dataApiKeydownHandler ) ;
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$3 , Dropdown . clearMenus ) ;
2020-03-28 11:29:08 +01:00
EventHandler . on ( document , EVENT _KEYUP _DATA _API , Dropdown . clearMenus ) ;
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$3 , SELECTOR _DATA _TOGGLE$3 , function ( event ) {
2018-11-13 07:41:12 +01:00
event . preventDefault ( ) ;
2021-08-04 17:41:51 +02:00
Dropdown . getOrCreateInstance ( this ) . toggle ( ) ;
2018-11-13 07:41:12 +01:00
} ) ;
/ * *
* jQuery
* /
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Dropdown ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / scrollBar . js
2021-05-05 21:32:12 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2022-05-13 08:07:23 +02:00
/ * *
* Constants
* /
2021-05-05 21:32:12 +02:00
const SELECTOR _FIXED _CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top' ;
const SELECTOR _STICKY _CONTENT = '.sticky-top' ;
2022-05-13 08:07:23 +02:00
const PROPERTY _PADDING = 'padding-right' ;
const PROPERTY _MARGIN = 'margin-right' ;
/ * *
* Class definition
* /
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
class ScrollBarHelper {
constructor ( ) {
this . _element = document . body ;
2022-05-13 08:07:23 +02:00
} // Public
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
getWidth ( ) {
// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
const documentWidth = document . documentElement . clientWidth ;
return Math . abs ( window . innerWidth - documentWidth ) ;
}
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
hide ( ) {
const width = this . getWidth ( ) ;
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
this . _disableOverFlow ( ) ; // give padding to element to balance the hidden scrollbar width
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
this . _setElementAttributes ( this . _element , PROPERTY _PADDING , calculatedValue => calculatedValue + width ) ; // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth
this . _setElementAttributes ( SELECTOR _FIXED _CONTENT , PROPERTY _PADDING , calculatedValue => calculatedValue + width ) ;
this . _setElementAttributes ( SELECTOR _STICKY _CONTENT , PROPERTY _MARGIN , calculatedValue => calculatedValue - width ) ;
}
reset ( ) {
this . _resetElementAttributes ( this . _element , 'overflow' ) ;
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
this . _resetElementAttributes ( this . _element , PROPERTY _PADDING ) ;
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
this . _resetElementAttributes ( SELECTOR _FIXED _CONTENT , PROPERTY _PADDING ) ;
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
this . _resetElementAttributes ( SELECTOR _STICKY _CONTENT , PROPERTY _MARGIN ) ;
2021-05-05 21:32:12 +02:00
}
2022-05-13 08:07:23 +02:00
isOverflowing ( ) {
return this . getWidth ( ) > 0 ;
} // Private
2021-06-22 20:29:16 +02:00
_disableOverFlow ( ) {
this . _saveInitialAttribute ( this . _element , 'overflow' ) ;
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
this . _element . style . overflow = 'hidden' ;
}
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
_setElementAttributes ( selector , styleProperty , callback ) {
2021-06-22 20:29:16 +02:00
const scrollbarWidth = this . getWidth ( ) ;
const manipulationCallBack = element => {
if ( element !== this . _element && window . innerWidth > element . clientWidth + scrollbarWidth ) {
return ;
}
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
this . _saveInitialAttribute ( element , styleProperty ) ;
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
const calculatedValue = window . getComputedStyle ( element ) . getPropertyValue ( styleProperty ) ;
element . style . setProperty ( styleProperty , ` ${ callback ( Number . parseFloat ( calculatedValue ) ) } px ` ) ;
2021-06-22 20:29:16 +02:00
} ;
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
this . _applyManipulationCallback ( selector , manipulationCallBack ) ;
}
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
_saveInitialAttribute ( element , styleProperty ) {
const actualValue = element . style . getPropertyValue ( styleProperty ) ;
2021-06-22 20:29:16 +02:00
if ( actualValue ) {
2022-05-13 08:07:23 +02:00
Manipulator . setDataAttribute ( element , styleProperty , actualValue ) ;
2021-06-22 20:29:16 +02:00
}
}
2022-05-13 08:07:23 +02:00
_resetElementAttributes ( selector , styleProperty ) {
2021-06-22 20:29:16 +02:00
const manipulationCallBack = element => {
2022-05-13 08:07:23 +02:00
const value = Manipulator . getDataAttribute ( element , styleProperty ) ; // We only want to remove the property if the value is `null`; the value can also be zero
2021-06-22 20:29:16 +02:00
2022-05-13 08:07:23 +02:00
if ( value === null ) {
element . style . removeProperty ( styleProperty ) ;
return ;
2021-06-22 20:29:16 +02:00
}
2022-05-13 08:07:23 +02:00
Manipulator . removeDataAttribute ( element , styleProperty ) ;
element . style . setProperty ( styleProperty , value ) ;
2021-06-22 20:29:16 +02:00
} ;
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
this . _applyManipulationCallback ( selector , manipulationCallBack ) ;
}
2021-05-05 21:32:12 +02:00
2021-06-22 20:29:16 +02:00
_applyManipulationCallback ( selector , callBack ) {
if ( isElement ( selector ) ) {
callBack ( selector ) ;
2022-05-13 08:07:23 +02:00
return ;
2021-05-05 21:32:12 +02:00
}
2021-06-22 20:29:16 +02:00
2022-05-13 08:07:23 +02:00
for ( const sel of SelectorEngine . find ( selector , this . _element ) ) {
callBack ( sel ) ;
}
2021-06-22 20:29:16 +02:00
}
}
2021-05-05 21:32:12 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / backdrop . js
2021-10-05 17:50:18 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2021-05-05 21:32:12 +02:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2022-05-13 08:07:23 +02:00
/ * *
* Constants
* /
const NAME$9 = 'backdrop' ;
const CLASS _NAME _FADE$4 = 'fade' ;
const CLASS _NAME _SHOW$5 = 'show' ;
const EVENT _MOUSEDOWN = ` mousedown.bs. ${ NAME$9 } ` ;
const Default$8 = {
2021-08-04 17:41:51 +02:00
className : 'modal-backdrop' ,
2022-07-19 17:43:58 +02:00
clickCallback : null ,
isAnimated : false ,
2021-05-05 21:32:12 +02:00
isVisible : true ,
// if false, we use the backdrop helper without adding any element to the dom
2022-07-19 17:43:58 +02:00
rootElement : 'body' // give the choice to place backdrop under different elements
2021-05-05 21:32:12 +02:00
} ;
2022-05-13 08:07:23 +02:00
const DefaultType$8 = {
2021-08-04 17:41:51 +02:00
className : 'string' ,
2022-07-19 17:43:58 +02:00
clickCallback : '(function|null)' ,
2021-05-05 21:32:12 +02:00
isAnimated : 'boolean' ,
2022-07-19 17:43:58 +02:00
isVisible : 'boolean' ,
rootElement : '(element|string)'
2021-05-05 21:32:12 +02:00
} ;
2022-05-13 08:07:23 +02:00
/ * *
* Class definition
* /
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
class Backdrop extends Config {
2021-05-05 21:32:12 +02:00
constructor ( config ) {
2022-05-13 08:07:23 +02:00
super ( ) ;
2021-05-05 21:32:12 +02:00
this . _config = this . _getConfig ( config ) ;
this . _isAppended = false ;
this . _element = null ;
2022-05-13 08:07:23 +02:00
} // Getters
static get Default ( ) {
return Default$8 ;
}
static get DefaultType ( ) {
return DefaultType$8 ;
2021-05-05 21:32:12 +02:00
}
2022-05-13 08:07:23 +02:00
static get NAME ( ) {
return NAME$9 ;
} // Public
2021-05-05 21:32:12 +02:00
show ( callback ) {
if ( ! this . _config . isVisible ) {
execute ( callback ) ;
return ;
}
this . _append ( ) ;
2022-05-13 08:07:23 +02:00
const element = this . _getElement ( ) ;
2021-05-05 21:32:12 +02:00
if ( this . _config . isAnimated ) {
2022-05-13 08:07:23 +02:00
reflow ( element ) ;
2021-05-05 21:32:12 +02:00
}
2022-05-13 08:07:23 +02:00
element . classList . add ( CLASS _NAME _SHOW$5 ) ;
2021-05-05 21:32:12 +02:00
this . _emulateAnimation ( ( ) => {
execute ( callback ) ;
} ) ;
}
hide ( callback ) {
if ( ! this . _config . isVisible ) {
execute ( callback ) ;
return ;
}
2021-08-04 17:41:51 +02:00
this . _getElement ( ) . classList . remove ( CLASS _NAME _SHOW$5 ) ;
2021-05-05 21:32:12 +02:00
this . _emulateAnimation ( ( ) => {
this . dispose ( ) ;
execute ( callback ) ;
} ) ;
2022-05-13 08:07:23 +02:00
}
dispose ( ) {
if ( ! this . _isAppended ) {
return ;
}
EventHandler . off ( this . _element , EVENT _MOUSEDOWN ) ;
this . _element . remove ( ) ;
this . _isAppended = false ;
2021-05-05 21:32:12 +02:00
} // Private
_getElement ( ) {
if ( ! this . _element ) {
const backdrop = document . createElement ( 'div' ) ;
2021-08-04 17:41:51 +02:00
backdrop . className = this . _config . className ;
2021-05-05 21:32:12 +02:00
if ( this . _config . isAnimated ) {
2021-08-04 17:41:51 +02:00
backdrop . classList . add ( CLASS _NAME _FADE$4 ) ;
2021-05-05 21:32:12 +02:00
}
this . _element = backdrop ;
}
return this . _element ;
}
2022-05-13 08:07:23 +02:00
_configAfterMerge ( config ) {
// use getElement() with the default "body" to get a fresh Element on each instantiation
2021-06-22 20:29:16 +02:00
config . rootElement = getElement ( config . rootElement ) ;
2021-05-05 21:32:12 +02:00
return config ;
}
_append ( ) {
if ( this . _isAppended ) {
return ;
}
2022-05-13 08:07:23 +02:00
const element = this . _getElement ( ) ;
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
this . _config . rootElement . append ( element ) ;
EventHandler . on ( element , EVENT _MOUSEDOWN , ( ) => {
2021-05-05 21:32:12 +02:00
execute ( this . _config . clickCallback ) ;
} ) ;
this . _isAppended = true ;
}
_emulateAnimation ( callback ) {
2021-06-22 20:29:16 +02:00
executeAfterTransition ( callback , this . _getElement ( ) , this . _config . isAnimated ) ;
2021-05-05 21:32:12 +02:00
}
}
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / focustrap . js
2021-10-05 17:50:18 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2021-08-04 17:41:51 +02:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2022-05-13 08:07:23 +02:00
/ * *
* Constants
* /
const NAME$8 = 'focustrap' ;
const DATA _KEY$5 = 'bs.focustrap' ;
const EVENT _KEY$5 = ` . ${ DATA _KEY$5 } ` ;
const EVENT _FOCUSIN$2 = ` focusin ${ EVENT _KEY$5 } ` ;
const EVENT _KEYDOWN _TAB = ` keydown.tab ${ EVENT _KEY$5 } ` ;
const TAB _KEY = 'Tab' ;
const TAB _NAV _FORWARD = 'forward' ;
const TAB _NAV _BACKWARD = 'backward' ;
const Default$7 = {
2022-07-19 17:43:58 +02:00
autofocus : true ,
trapElement : null // The element to trap focus inside of
2021-08-04 17:41:51 +02:00
} ;
2022-05-13 08:07:23 +02:00
const DefaultType$7 = {
2022-07-19 17:43:58 +02:00
autofocus : 'boolean' ,
trapElement : 'element'
2021-08-04 17:41:51 +02:00
} ;
2022-05-13 08:07:23 +02:00
/ * *
* Class definition
* /
2021-08-04 17:41:51 +02:00
2022-05-13 08:07:23 +02:00
class FocusTrap extends Config {
2021-08-04 17:41:51 +02:00
constructor ( config ) {
2022-05-13 08:07:23 +02:00
super ( ) ;
2021-08-04 17:41:51 +02:00
this . _config = this . _getConfig ( config ) ;
this . _isActive = false ;
this . _lastTabNavDirection = null ;
2022-05-13 08:07:23 +02:00
} // Getters
static get Default ( ) {
return Default$7 ;
2021-08-04 17:41:51 +02:00
}
2022-05-13 08:07:23 +02:00
static get DefaultType ( ) {
return DefaultType$7 ;
}
static get NAME ( ) {
return NAME$8 ;
} // Public
2021-08-04 17:41:51 +02:00
2022-05-13 08:07:23 +02:00
activate ( ) {
2021-08-04 17:41:51 +02:00
if ( this . _isActive ) {
return ;
}
2022-05-13 08:07:23 +02:00
if ( this . _config . autofocus ) {
this . _config . trapElement . focus ( ) ;
2021-08-04 17:41:51 +02:00
}
2022-05-13 08:07:23 +02:00
EventHandler . off ( document , EVENT _KEY$5 ) ; // guard against infinite focus loop
2021-08-04 17:41:51 +02:00
2022-05-13 08:07:23 +02:00
EventHandler . on ( document , EVENT _FOCUSIN$2 , event => this . _handleFocusin ( event ) ) ;
2021-08-04 17:41:51 +02:00
EventHandler . on ( document , EVENT _KEYDOWN _TAB , event => this . _handleKeydown ( event ) ) ;
this . _isActive = true ;
}
deactivate ( ) {
if ( ! this . _isActive ) {
return ;
}
this . _isActive = false ;
2022-05-13 08:07:23 +02:00
EventHandler . off ( document , EVENT _KEY$5 ) ;
2021-08-04 17:41:51 +02:00
} // Private
_handleFocusin ( event ) {
const {
trapElement
} = this . _config ;
2022-05-13 08:07:23 +02:00
if ( event . target === document || event . target === trapElement || trapElement . contains ( event . target ) ) {
2021-08-04 17:41:51 +02:00
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 ;
}
}
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : modal . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2022-05-13 08:07:23 +02:00
const NAME$7 = 'modal' ;
const DATA _KEY$4 = 'bs.modal' ;
const EVENT _KEY$4 = ` . ${ DATA _KEY$4 } ` ;
const DATA _API _KEY$2 = '.data-api' ;
2021-03-23 17:26:54 +01:00
const ESCAPE _KEY$1 = 'Escape' ;
2022-05-13 08:07:23 +02:00
const EVENT _HIDE$4 = ` hide ${ EVENT _KEY$4 } ` ;
const EVENT _HIDE _PREVENTED$1 = ` hidePrevented ${ EVENT _KEY$4 } ` ;
const EVENT _HIDDEN$4 = ` hidden ${ EVENT _KEY$4 } ` ;
const EVENT _SHOW$4 = ` show ${ EVENT _KEY$4 } ` ;
const EVENT _SHOWN$4 = ` shown ${ EVENT _KEY$4 } ` ;
const EVENT _RESIZE$1 = ` resize ${ EVENT _KEY$4 } ` ;
2022-07-19 17:43:58 +02:00
const EVENT _MOUSEDOWN _DISMISS = ` mousedown.dismiss ${ EVENT _KEY$4 } ` ;
2022-05-13 08:07:23 +02:00
const EVENT _KEYDOWN _DISMISS$1 = ` keydown.dismiss ${ EVENT _KEY$4 } ` ;
const EVENT _CLICK _DATA _API$2 = ` click ${ EVENT _KEY$4 } ${ DATA _API _KEY$2 } ` ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _OPEN = 'modal-open' ;
2021-08-04 17:41:51 +02:00
const CLASS _NAME _FADE$3 = 'fade' ;
const CLASS _NAME _SHOW$4 = 'show' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _STATIC = 'modal-static' ;
2021-09-07 17:37:44 +02:00
const OPEN _SELECTOR$1 = '.modal.show' ;
2021-03-23 17:26:54 +01:00
const SELECTOR _DIALOG = '.modal-dialog' ;
const SELECTOR _MODAL _BODY = '.modal-body' ;
const SELECTOR _DATA _TOGGLE$2 = '[data-bs-toggle="modal"]' ;
2022-05-13 08:07:23 +02:00
const Default$6 = {
backdrop : true ,
2022-07-19 17:43:58 +02:00
focus : true ,
keyboard : true
2022-05-13 08:07:23 +02:00
} ;
const DefaultType$6 = {
backdrop : '(boolean|string)' ,
2022-07-19 17:43:58 +02:00
focus : 'boolean' ,
keyboard : 'boolean'
2022-05-13 08:07:23 +02:00
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
class Modal extends BaseComponent {
constructor ( element , config ) {
2022-05-13 08:07:23 +02:00
super ( element , config ) ;
2021-03-23 17:26:54 +01:00
this . _dialog = SelectorEngine . findOne ( SELECTOR _DIALOG , this . _element ) ;
2021-05-05 21:32:12 +02:00
this . _backdrop = this . _initializeBackDrop ( ) ;
2021-08-04 17:41:51 +02:00
this . _focustrap = this . _initializeFocusTrap ( ) ;
2021-03-23 17:26:54 +01:00
this . _isShown = false ;
this . _isTransitioning = false ;
2021-06-22 20:29:16 +02:00
this . _scrollBar = new ScrollBarHelper ( ) ;
2022-05-13 08:07:23 +02:00
this . _addEventListeners ( ) ;
2018-11-13 07:41:12 +01:00
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
2022-05-13 08:07:23 +02:00
return Default$6 ;
}
static get DefaultType ( ) {
return DefaultType$6 ;
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
2022-05-13 08:07:23 +02:00
return NAME$7 ;
2021-03-23 17:26:54 +01:00
} // Public
2015-08-15 21:19:11 +02:00
2016-12-02 19:13:36 +01:00
2021-03-23 17:26:54 +01:00
toggle ( relatedTarget ) {
return this . _isShown ? this . hide ( ) : this . show ( relatedTarget ) ;
}
show ( relatedTarget ) {
2018-11-13 07:41:12 +01:00
if ( this . _isShown || this . _isTransitioning ) {
return ;
}
2017-04-02 04:18:29 +02:00
2022-05-13 08:07:23 +02:00
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$4 , {
2021-03-23 17:26:54 +01:00
relatedTarget
2018-11-13 07:41:12 +01:00
} ) ;
2015-08-15 21:19:11 +02:00
2021-06-22 20:29:16 +02:00
if ( showEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
this . _isShown = true ;
2022-05-13 08:07:23 +02:00
this . _isTransitioning = true ;
2021-06-22 20:29:16 +02:00
this . _scrollBar . hide ( ) ;
2021-05-05 21:32:12 +02:00
document . body . classList . add ( CLASS _NAME _OPEN ) ;
2017-09-06 06:05:12 +02:00
2022-05-13 08:07:23 +02:00
this . _adjustDialog ( ) ;
this . _backdrop . show ( ( ) => this . _showElement ( relatedTarget ) ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
hide ( ) {
2018-11-13 07:41:12 +01:00
if ( ! this . _isShown || this . _isTransitioning ) {
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$4 ) ;
2015-08-15 21:19:11 +02:00
2019-07-24 08:13:50 +02:00
if ( hideEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
}
2017-10-16 00:51:44 +02:00
2018-11-13 07:41:12 +01:00
this . _isShown = false ;
2022-05-13 08:07:23 +02:00
this . _isTransitioning = true ;
2015-08-15 21:19:11 +02:00
2021-08-04 17:41:51 +02:00
this . _focustrap . deactivate ( ) ;
2019-03-01 17:31:34 +01:00
2021-08-04 17:41:51 +02:00
this . _element . classList . remove ( CLASS _NAME _SHOW$4 ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
this . _queueCallback ( ( ) => this . _hideModal ( ) , this . _element , this . _isAnimated ( ) ) ;
2021-03-23 17:26:54 +01:00
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2022-05-13 08:07:23 +02:00
for ( const htmlElement of [ window , this . _dialog ] ) {
EventHandler . off ( htmlElement , EVENT _KEY$4 ) ;
}
2021-05-13 18:22:20 +02:00
this . _backdrop . dispose ( ) ;
2021-08-04 17:41:51 +02:00
this . _focustrap . deactivate ( ) ;
2017-03-26 20:26:31 +02:00
2021-08-04 17:41:51 +02:00
super . dispose ( ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
handleUpdate ( ) {
2018-11-13 07:41:12 +01:00
this . _adjustDialog ( ) ;
2019-01-04 17:29:45 +01:00
} // Private
2015-08-15 21:19:11 +02:00
2021-05-05 21:32:12 +02:00
_initializeBackDrop ( ) {
return new Backdrop ( {
isVisible : Boolean ( this . _config . backdrop ) ,
2022-05-13 08:07:23 +02:00
// 'static' option will be translated to true, and booleans will keep their value,
2021-05-05 21:32:12 +02:00
isAnimated : this . _isAnimated ( )
} ) ;
}
2021-08-04 17:41:51 +02:00
_initializeFocusTrap ( ) {
return new FocusTrap ( {
trapElement : this . _element
} ) ;
}
2021-03-23 17:26:54 +01:00
_showElement ( relatedTarget ) {
2022-05-13 08:07:23 +02:00
// try to append dynamic modal
if ( ! document . body . contains ( this . _element ) ) {
2021-08-04 17:41:51 +02:00
document . body . append ( this . _element ) ;
2018-11-13 07:41:12 +01:00
}
2017-09-30 23:28:03 +02:00
2018-11-13 07:41:12 +01:00
this . _element . style . display = 'block' ;
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
this . _element . removeAttribute ( 'aria-hidden' ) ;
2016-10-10 02:26:51 +02:00
2018-12-16 00:13:22 +01:00
this . _element . setAttribute ( 'aria-modal' , true ) ;
2020-06-14 00:40:28 +02:00
this . _element . setAttribute ( 'role' , 'dialog' ) ;
2020-05-13 20:53:43 +02:00
this . _element . scrollTop = 0 ;
2022-05-13 08:07:23 +02:00
const modalBody = SelectorEngine . findOne ( SELECTOR _MODAL _BODY , this . _dialog ) ;
2020-05-13 20:53:43 +02:00
if ( modalBody ) {
2019-08-27 15:03:21 +02:00
modalBody . scrollTop = 0 ;
2019-02-11 20:15:34 +01:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
reflow ( this . _element ) ;
2016-10-10 02:26:51 +02:00
2021-08-04 17:41:51 +02:00
this . _element . classList . add ( CLASS _NAME _SHOW$4 ) ;
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
const transitionComplete = ( ) => {
if ( this . _config . focus ) {
2021-08-04 17:41:51 +02:00
this . _focustrap . activate ( ) ;
2015-08-15 21:19:11 +02:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
this . _isTransitioning = false ;
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , EVENT _SHOWN$4 , {
2021-03-23 17:26:54 +01:00
relatedTarget
2019-03-01 17:31:34 +01:00
} ) ;
2016-10-10 02:26:51 +02:00
} ;
2022-05-13 08:07:23 +02:00
this . _queueCallback ( transitionComplete , this . _dialog , this . _isAnimated ( ) ) ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
_addEventListeners ( ) {
EventHandler . on ( this . _element , EVENT _KEYDOWN _DISMISS$1 , event => {
if ( event . key !== ESCAPE _KEY$1 ) {
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( this . _config . keyboard ) {
event . preventDefault ( ) ;
this . hide ( ) ;
return ;
}
this . _triggerBackdropTransition ( ) ;
} ) ;
EventHandler . on ( window , EVENT _RESIZE$1 , ( ) => {
if ( this . _isShown && ! this . _isTransitioning ) {
this . _adjustDialog ( ) ;
}
} ) ;
2022-07-19 17:43:58 +02:00
EventHandler . on ( this . _element , EVENT _MOUSEDOWN _DISMISS , event => {
2022-05-13 08:07:23 +02:00
if ( event . target !== event . currentTarget ) {
// click is inside modal-dialog
return ;
}
if ( this . _config . backdrop === 'static' ) {
this . _triggerBackdropTransition ( ) ;
return ;
}
if ( this . _config . backdrop ) {
this . hide ( ) ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
_hideModal ( ) {
2018-11-13 07:41:12 +01:00
this . _element . style . display = 'none' ;
2018-03-31 22:59:37 +02:00
2018-11-13 07:41:12 +01:00
this . _element . setAttribute ( 'aria-hidden' , true ) ;
2017-09-30 23:28:03 +02:00
2018-12-16 00:13:22 +01:00
this . _element . removeAttribute ( 'aria-modal' ) ;
2020-06-14 00:40:28 +02:00
this . _element . removeAttribute ( 'role' ) ;
2018-11-13 07:41:12 +01:00
this . _isTransitioning = false ;
2017-09-30 23:28:03 +02:00
2021-05-05 21:32:12 +02:00
this . _backdrop . hide ( ( ) => {
2020-03-28 11:29:08 +01:00
document . body . classList . remove ( CLASS _NAME _OPEN ) ;
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
this . _resetAdjustments ( ) ;
2017-09-30 23:28:03 +02:00
2021-06-22 20:29:16 +02:00
this . _scrollBar . reset ( ) ;
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , EVENT _HIDDEN$4 ) ;
2021-05-05 21:32:12 +02:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-11-08 09:11:23 +01:00
2021-03-23 17:26:54 +01:00
_isAnimated ( ) {
2021-08-04 17:41:51 +02:00
return this . _element . classList . contains ( CLASS _NAME _FADE$3 ) ;
2021-03-23 17:26:54 +01:00
}
2019-11-08 09:11:23 +01:00
2021-03-23 17:26:54 +01:00
_triggerBackdropTransition ( ) {
2022-05-13 08:07:23 +02:00
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE _PREVENTED$1 ) ;
2019-11-08 09:11:23 +01:00
2020-11-23 14:17:16 +01:00
if ( hideEvent . defaultPrevented ) {
return ;
}
2019-11-08 09:11:23 +01:00
2022-05-13 08:07:23 +02:00
const isModalOverflowing = this . _element . scrollHeight > document . documentElement . clientHeight ;
const initialOverflowY = this . _element . style . overflowY ; // return if the following background transition hasn't yet completed
2021-06-22 20:29:16 +02:00
2022-05-13 08:07:23 +02:00
if ( initialOverflowY === 'hidden' || this . _element . classList . contains ( CLASS _NAME _STATIC ) ) {
2021-06-22 20:29:16 +02:00
return ;
}
2020-09-14 17:12:06 +02:00
2020-11-23 14:17:16 +01:00
if ( ! isModalOverflowing ) {
2022-05-13 08:07:23 +02:00
this . _element . style . overflowY = 'hidden' ;
2020-11-23 14:17:16 +01:00
}
2020-09-14 17:12:06 +02:00
2022-05-13 08:07:23 +02:00
this . _element . classList . add ( CLASS _NAME _STATIC ) ;
2019-11-08 09:11:23 +01:00
2021-06-22 20:29:16 +02:00
this . _queueCallback ( ( ) => {
2022-05-13 08:07:23 +02:00
this . _element . classList . remove ( CLASS _NAME _STATIC ) ;
2020-09-14 17:12:06 +02:00
2022-05-13 08:07:23 +02:00
this . _queueCallback ( ( ) => {
this . _element . style . overflowY = initialOverflowY ;
} , this . _dialog ) ;
2021-06-22 20:29:16 +02:00
} , this . _dialog ) ;
2019-11-08 09:11:23 +01:00
2020-11-23 14:17:16 +01:00
this . _element . focus ( ) ;
2022-05-13 08:07:23 +02:00
}
/ * *
* The following methods are used to handle overflowing modals
* /
2016-10-10 02:26:51 +02:00
2021-03-23 17:26:54 +01:00
_adjustDialog ( ) {
const isModalOverflowing = this . _element . scrollHeight > document . documentElement . clientHeight ;
2021-06-22 20:29:16 +02:00
const scrollbarWidth = this . _scrollBar . getWidth ( ) ;
2021-05-05 21:32:12 +02:00
const isBodyOverflowing = scrollbarWidth > 0 ;
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
if ( isBodyOverflowing && ! isModalOverflowing ) {
const property = isRTL ( ) ? 'paddingLeft' : 'paddingRight' ;
this . _element . style [ property ] = ` ${ scrollbarWidth } px ` ;
2018-11-13 07:41:12 +01:00
}
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
if ( ! isBodyOverflowing && isModalOverflowing ) {
const property = isRTL ( ) ? 'paddingRight' : 'paddingLeft' ;
this . _element . style [ property ] = ` ${ scrollbarWidth } px ` ;
2018-11-13 07:41:12 +01:00
}
2021-03-23 17:26:54 +01:00
}
2018-06-22 07:55:23 +02:00
2021-03-23 17:26:54 +01:00
_resetAdjustments ( ) {
2018-11-13 07:41:12 +01:00
this . _element . style . paddingLeft = '' ;
this . _element . style . paddingRight = '' ;
2019-01-04 17:29:45 +01:00
} // Static
2017-09-30 23:28:03 +02:00
2016-10-10 02:26:51 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config , relatedTarget ) {
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Modal . getOrCreateInstance ( this , config ) ;
2015-08-15 21:19:11 +02:00
2021-05-05 21:32:12 +02:00
if ( typeof config !== 'string' ) {
return ;
2018-11-13 07:41:12 +01:00
}
2021-05-05 21:32:12 +02:00
if ( typeof data [ config ] === 'undefined' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2018-03-31 22:59:37 +02:00
}
2021-05-05 21:32:12 +02:00
data [ config ] ( relatedTarget ) ;
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2018-11-13 07:41:12 +01:00
* /
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$2 , SELECTOR _DATA _TOGGLE$2 , function ( event ) {
const target = getElementFromSelector ( this ) ;
2018-11-13 07:41:12 +01:00
2021-05-05 21:32:12 +02:00
if ( [ 'A' , 'AREA' ] . includes ( this . tagName ) ) {
2018-11-13 07:41:12 +01:00
event . preventDefault ( ) ;
}
2022-05-13 08:07:23 +02:00
EventHandler . one ( target , EVENT _SHOW$4 , showEvent => {
2019-03-01 17:31:34 +01:00
if ( showEvent . defaultPrevented ) {
// only register focus restorer if modal will actually get shown
2018-11-13 07:41:12 +01:00
return ;
2015-08-15 21:19:11 +02:00
}
2022-05-13 08:07:23 +02:00
EventHandler . one ( target , EVENT _HIDDEN$4 , ( ) => {
2021-03-23 17:26:54 +01:00
if ( isVisible ( this ) ) {
this . focus ( ) ;
2015-08-15 21:19:11 +02:00
}
2018-03-31 22:59:37 +02:00
} ) ;
2022-05-13 08:07:23 +02:00
} ) ; // avoid conflict when clicking modal toggler while another one is open
2021-09-07 17:37:44 +02:00
2022-05-13 08:07:23 +02:00
const alreadyOpen = SelectorEngine . findOne ( OPEN _SELECTOR$1 ) ;
2021-09-07 17:37:44 +02:00
2022-05-13 08:07:23 +02:00
if ( alreadyOpen ) {
Modal . getInstance ( alreadyOpen ) . hide ( ) ;
2021-09-07 17:37:44 +02:00
}
2021-06-22 20:29:16 +02:00
const data = Modal . getOrCreateInstance ( target ) ;
2021-02-10 17:14:51 +01:00
data . toggle ( this ) ;
2018-11-13 07:41:12 +01:00
} ) ;
2021-08-04 17:41:51 +02:00
enableDismissTrigger ( Modal ) ;
2018-11-13 07:41:12 +01:00
/ * *
* jQuery
2021-03-23 17:26:54 +01:00
* /
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Modal ) ;
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : offcanvas . js
2021-10-05 17:50:18 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2021-03-23 17:26:54 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* Constants
* /
2022-05-13 08:07:23 +02:00
const NAME$6 = 'offcanvas' ;
const DATA _KEY$3 = 'bs.offcanvas' ;
const EVENT _KEY$3 = ` . ${ DATA _KEY$3 } ` ;
const DATA _API _KEY$1 = '.data-api' ;
const EVENT _LOAD _DATA _API$2 = ` load ${ EVENT _KEY$3 } ${ DATA _API _KEY$1 } ` ;
2021-03-23 17:26:54 +01:00
const ESCAPE _KEY = 'Escape' ;
2022-05-13 08:07:23 +02:00
const CLASS _NAME _SHOW$3 = 'show' ;
const CLASS _NAME _SHOWING$1 = 'showing' ;
const CLASS _NAME _HIDING = 'hiding' ;
const CLASS _NAME _BACKDROP = 'offcanvas-backdrop' ;
const OPEN _SELECTOR = '.offcanvas.show' ;
const EVENT _SHOW$3 = ` show ${ EVENT _KEY$3 } ` ;
const EVENT _SHOWN$3 = ` shown ${ EVENT _KEY$3 } ` ;
const EVENT _HIDE$3 = ` hide ${ EVENT _KEY$3 } ` ;
const EVENT _HIDE _PREVENTED = ` hidePrevented ${ EVENT _KEY$3 } ` ;
const EVENT _HIDDEN$3 = ` hidden ${ EVENT _KEY$3 } ` ;
const EVENT _RESIZE = ` resize ${ EVENT _KEY$3 } ` ;
const EVENT _CLICK _DATA _API$1 = ` click ${ EVENT _KEY$3 } ${ DATA _API _KEY$1 } ` ;
const EVENT _KEYDOWN _DISMISS = ` keydown.dismiss ${ EVENT _KEY$3 } ` ;
const SELECTOR _DATA _TOGGLE$1 = '[data-bs-toggle="offcanvas"]' ;
const Default$5 = {
2021-03-23 17:26:54 +01:00
backdrop : true ,
keyboard : true ,
scroll : false
} ;
2022-05-13 08:07:23 +02:00
const DefaultType$5 = {
backdrop : '(boolean|string)' ,
2021-03-23 17:26:54 +01:00
keyboard : 'boolean' ,
scroll : 'boolean'
} ;
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2021-03-23 17:26:54 +01:00
* /
class Offcanvas extends BaseComponent {
constructor ( element , config ) {
2022-05-13 08:07:23 +02:00
super ( element , config ) ;
2021-03-23 17:26:54 +01:00
this . _isShown = false ;
2021-05-05 21:32:12 +02:00
this . _backdrop = this . _initializeBackDrop ( ) ;
2021-08-04 17:41:51 +02:00
this . _focustrap = this . _initializeFocusTrap ( ) ;
2021-03-23 17:26:54 +01:00
this . _addEventListeners ( ) ;
} // Getters
2022-05-13 08:07:23 +02:00
static get Default ( ) {
return Default$5 ;
2021-03-23 17:26:54 +01:00
}
2022-05-13 08:07:23 +02:00
static get DefaultType ( ) {
return DefaultType$5 ;
}
static get NAME ( ) {
return NAME$6 ;
2021-03-23 17:26:54 +01:00
} // Public
toggle ( relatedTarget ) {
return this . _isShown ? this . hide ( ) : this . show ( relatedTarget ) ;
}
show ( relatedTarget ) {
if ( this . _isShown ) {
return ;
}
2022-05-13 08:07:23 +02:00
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$3 , {
2021-03-23 17:26:54 +01:00
relatedTarget
} ) ;
if ( showEvent . defaultPrevented ) {
return ;
}
this . _isShown = true ;
2021-05-05 21:32:12 +02:00
this . _backdrop . show ( ) ;
2021-03-23 17:26:54 +01:00
if ( ! this . _config . scroll ) {
2021-06-22 20:29:16 +02:00
new ScrollBarHelper ( ) . hide ( ) ;
2021-05-05 21:32:12 +02:00
}
2021-03-23 17:26:54 +01:00
this . _element . setAttribute ( 'aria-modal' , true ) ;
this . _element . setAttribute ( 'role' , 'dialog' ) ;
2022-05-13 08:07:23 +02:00
this . _element . classList . add ( CLASS _NAME _SHOWING$1 ) ;
2021-03-23 17:26:54 +01:00
const completeCallBack = ( ) => {
2022-07-19 17:43:58 +02:00
if ( ! this . _config . scroll || this . _config . backdrop ) {
2021-08-04 17:41:51 +02:00
this . _focustrap . activate ( ) ;
}
2022-05-13 08:07:23 +02:00
this . _element . classList . add ( CLASS _NAME _SHOW$3 ) ;
this . _element . classList . remove ( CLASS _NAME _SHOWING$1 ) ;
EventHandler . trigger ( this . _element , EVENT _SHOWN$3 , {
2021-03-23 17:26:54 +01:00
relatedTarget
} ) ;
} ;
2021-05-13 18:22:20 +02:00
this . _queueCallback ( completeCallBack , this . _element , true ) ;
2021-03-23 17:26:54 +01:00
}
hide ( ) {
if ( ! this . _isShown ) {
return ;
}
2022-05-13 08:07:23 +02:00
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$3 ) ;
2021-03-23 17:26:54 +01:00
if ( hideEvent . defaultPrevented ) {
return ;
}
2021-08-04 17:41:51 +02:00
this . _focustrap . deactivate ( ) ;
2021-03-23 17:26:54 +01:00
this . _element . blur ( ) ;
this . _isShown = false ;
2022-05-13 08:07:23 +02:00
this . _element . classList . add ( CLASS _NAME _HIDING ) ;
2021-03-23 17:26:54 +01:00
2021-05-05 21:32:12 +02:00
this . _backdrop . hide ( ) ;
2021-03-23 17:26:54 +01:00
const completeCallback = ( ) => {
2022-05-13 08:07:23 +02:00
this . _element . classList . remove ( CLASS _NAME _SHOW$3 , CLASS _NAME _HIDING ) ;
2021-03-23 17:26:54 +01:00
this . _element . removeAttribute ( 'aria-modal' ) ;
this . _element . removeAttribute ( 'role' ) ;
if ( ! this . _config . scroll ) {
2021-06-22 20:29:16 +02:00
new ScrollBarHelper ( ) . reset ( ) ;
2021-03-23 17:26:54 +01:00
}
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , EVENT _HIDDEN$3 ) ;
2021-03-23 17:26:54 +01:00
} ;
2021-05-13 18:22:20 +02:00
this . _queueCallback ( completeCallback , this . _element , true ) ;
2021-05-05 21:32:12 +02:00
}
dispose ( ) {
this . _backdrop . dispose ( ) ;
2021-08-04 17:41:51 +02:00
this . _focustrap . deactivate ( ) ;
2021-05-05 21:32:12 +02:00
super . dispose ( ) ;
2021-03-23 17:26:54 +01:00
} // Private
2021-05-05 21:32:12 +02:00
_initializeBackDrop ( ) {
2022-05-13 08:07:23 +02:00
const clickCallback = ( ) => {
if ( this . _config . backdrop === 'static' ) {
EventHandler . trigger ( this . _element , EVENT _HIDE _PREVENTED ) ;
return ;
}
this . hide ( ) ;
} ; // 'static' option will be translated to true, and booleans will keep their value
const isVisible = Boolean ( this . _config . backdrop ) ;
2021-05-05 21:32:12 +02:00
return new Backdrop ( {
2021-08-04 17:41:51 +02:00
className : CLASS _NAME _BACKDROP ,
2022-05-13 08:07:23 +02:00
isVisible ,
2021-05-05 21:32:12 +02:00
isAnimated : true ,
rootElement : this . _element . parentNode ,
2022-05-13 08:07:23 +02:00
clickCallback : isVisible ? clickCallback : null
2021-05-05 21:32:12 +02:00
} ) ;
}
2021-08-04 17:41:51 +02:00
_initializeFocusTrap ( ) {
return new FocusTrap ( {
trapElement : this . _element
2021-03-23 17:26:54 +01:00
} ) ;
}
_addEventListeners ( ) {
2021-05-05 21:32:12 +02:00
EventHandler . on ( this . _element , EVENT _KEYDOWN _DISMISS , event => {
2022-05-13 08:07:23 +02:00
if ( event . key !== ESCAPE _KEY ) {
return ;
}
if ( ! this . _config . keyboard ) {
EventHandler . trigger ( this . _element , EVENT _HIDE _PREVENTED ) ;
return ;
2021-03-23 17:26:54 +01:00
}
2022-05-13 08:07:23 +02:00
this . hide ( ) ;
2021-03-23 17:26:54 +01:00
} ) ;
} // Static
static jQueryInterface ( config ) {
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Offcanvas . getOrCreateInstance ( this , config ) ;
2021-03-23 17:26:54 +01:00
if ( typeof config !== 'string' ) {
return ;
}
if ( data [ config ] === undefined || config . startsWith ( '_' ) || config === 'constructor' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
}
data [ config ] ( this ) ;
} ) ;
}
}
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2021-03-23 17:26:54 +01:00
* /
EventHandler . on ( document , EVENT _CLICK _DATA _API$1 , SELECTOR _DATA _TOGGLE$1 , function ( event ) {
const target = getElementFromSelector ( this ) ;
if ( [ 'A' , 'AREA' ] . includes ( this . tagName ) ) {
event . preventDefault ( ) ;
}
if ( isDisabled ( this ) ) {
return ;
}
2022-05-13 08:07:23 +02:00
EventHandler . one ( target , EVENT _HIDDEN$3 , ( ) => {
2021-03-23 17:26:54 +01:00
// focus on trigger when it is closed
if ( isVisible ( this ) ) {
this . focus ( ) ;
}
} ) ; // avoid conflict when clicking a toggler of an offcanvas, while another is open
2022-05-13 08:07:23 +02:00
const alreadyOpen = SelectorEngine . findOne ( OPEN _SELECTOR ) ;
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
if ( alreadyOpen && alreadyOpen !== target ) {
Offcanvas . getInstance ( alreadyOpen ) . hide ( ) ;
2021-03-23 17:26:54 +01:00
}
2021-06-22 20:29:16 +02:00
const data = Offcanvas . getOrCreateInstance ( target ) ;
2021-03-23 17:26:54 +01:00
data . toggle ( this ) ;
} ) ;
2022-05-13 08:07:23 +02:00
EventHandler . on ( window , EVENT _LOAD _DATA _API$2 , ( ) => {
for ( const selector of SelectorEngine . find ( OPEN _SELECTOR ) ) {
Offcanvas . getOrCreateInstance ( selector ) . show ( ) ;
}
} ) ;
EventHandler . on ( window , EVENT _RESIZE , ( ) => {
for ( const element of SelectorEngine . find ( '[aria-modal][class*=show][class*=offcanvas-]' ) ) {
if ( getComputedStyle ( element ) . position !== 'fixed' ) {
Offcanvas . getOrCreateInstance ( element ) . hide ( ) ;
}
}
} ) ;
2021-08-04 17:41:51 +02:00
enableDismissTrigger ( Offcanvas ) ;
2021-03-23 17:26:54 +01:00
/ * *
* jQuery
2018-11-13 07:41:12 +01:00
* /
2015-08-15 21:19:11 +02:00
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Offcanvas ) ;
2015-08-15 21:19:11 +02:00
2019-02-13 17:01:40 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / sanitizer . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2019-02-13 17:01:40 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-10-05 17:50:18 +02:00
const uriAttributes = new Set ( [ 'background' , 'cite' , 'href' , 'itemtype' , 'longdesc' , 'poster' , 'src' , 'xlink:href' ] ) ;
2021-03-23 17:26:54 +01:00
const ARIA _ATTRIBUTE _PATTERN = /^aria-[\w-]*$/i ;
2019-03-01 17:31:34 +01:00
/ * *
* A pattern that recognizes a commonly useful subset of URLs that are safe .
*
2022-07-19 17:43:58 +02:00
* Shout - out to Angular https : //github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
2019-03-01 17:31:34 +01:00
* /
2021-10-05 17:50:18 +02:00
const SAFE _URL _PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i ;
2019-03-01 17:31:34 +01:00
/ * *
* A pattern that matches safe data URLs . Only matches image , video and audio types .
*
2022-07-19 17:43:58 +02:00
* Shout - out to Angular https : //github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
2019-03-01 17:31:34 +01:00
* /
2021-03-23 17:26:54 +01:00
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 ;
2019-03-01 17:31:34 +01:00
2021-10-05 17:50:18 +02:00
const allowedAttribute = ( attribute , allowedAttributeList ) => {
const attributeName = attribute . nodeName . toLowerCase ( ) ;
2019-03-01 17:31:34 +01:00
2021-10-05 17:50:18 +02:00
if ( allowedAttributeList . includes ( attributeName ) ) {
if ( uriAttributes . has ( attributeName ) ) {
return Boolean ( SAFE _URL _PATTERN . test ( attribute . nodeValue ) || DATA _URL _PATTERN . test ( attribute . nodeValue ) ) ;
2019-03-01 17:31:34 +01:00
}
return true ;
2022-05-13 08:07:23 +02:00
} // Check if a regular expression validates the attribute.
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
return allowedAttributeList . filter ( attributeRegex => attributeRegex instanceof RegExp ) . some ( regex => regex . test ( attributeName ) ) ;
2019-03-01 17:31:34 +01:00
} ;
2021-03-23 17:26:54 +01:00
const DefaultAllowlist = {
2019-02-13 17:01:40 +01:00
// Global attributes allowed on any supplied element below.
'*' : [ 'class' , 'dir' , 'id' , 'lang' , 'role' , ARIA _ATTRIBUTE _PATTERN ] ,
a : [ 'target' , 'href' , 'title' , 'rel' ] ,
area : [ ] ,
b : [ ] ,
br : [ ] ,
col : [ ] ,
code : [ ] ,
div : [ ] ,
em : [ ] ,
hr : [ ] ,
h1 : [ ] ,
h2 : [ ] ,
h3 : [ ] ,
h4 : [ ] ,
h5 : [ ] ,
h6 : [ ] ,
i : [ ] ,
2020-03-28 11:29:08 +01:00
img : [ 'src' , 'srcset' , 'alt' , 'title' , 'width' , 'height' ] ,
2019-02-13 17:01:40 +01:00
li : [ ] ,
ol : [ ] ,
p : [ ] ,
pre : [ ] ,
s : [ ] ,
small : [ ] ,
span : [ ] ,
sub : [ ] ,
sup : [ ] ,
strong : [ ] ,
u : [ ] ,
ul : [ ]
} ;
2022-05-13 08:07:23 +02:00
function sanitizeHtml ( unsafeHtml , allowList , sanitizeFunction ) {
2019-03-01 17:31:34 +01:00
if ( ! unsafeHtml . length ) {
2019-02-13 17:01:40 +01:00
return unsafeHtml ;
}
2022-05-13 08:07:23 +02:00
if ( sanitizeFunction && typeof sanitizeFunction === 'function' ) {
return sanitizeFunction ( unsafeHtml ) ;
2019-02-13 17:01:40 +01:00
}
2021-03-23 17:26:54 +01:00
const domParser = new window . DOMParser ( ) ;
const createdDocument = domParser . parseFromString ( unsafeHtml , 'text/html' ) ;
const elements = [ ] . concat ( ... createdDocument . body . querySelectorAll ( '*' ) ) ;
2020-03-28 11:29:08 +01:00
2022-05-13 08:07:23 +02:00
for ( const element of elements ) {
2021-10-05 17:50:18 +02:00
const elementName = element . nodeName . toLowerCase ( ) ;
2019-02-13 17:01:40 +01:00
2021-10-05 17:50:18 +02:00
if ( ! Object . keys ( allowList ) . includes ( elementName ) ) {
element . remove ( ) ;
2021-03-23 17:26:54 +01:00
continue ;
2019-02-13 17:01:40 +01:00
}
2021-10-05 17:50:18 +02:00
const attributeList = [ ] . concat ( ... element . attributes ) ;
const allowedAttributes = [ ] . concat ( allowList [ '*' ] || [ ] , allowList [ elementName ] || [ ] ) ;
2022-05-13 08:07:23 +02:00
for ( const attribute of attributeList ) {
2021-10-05 17:50:18 +02:00
if ( ! allowedAttribute ( attribute , allowedAttributes ) ) {
element . removeAttribute ( attribute . nodeName ) ;
2019-02-13 17:01:40 +01:00
}
2022-05-13 08:07:23 +02:00
}
2019-02-13 17:01:40 +01:00
}
return createdDocument . body . innerHTML ;
}
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : util / template - factory . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2022-05-13 08:07:23 +02:00
const NAME$5 = 'TemplateFactory' ;
const Default$4 = {
2022-07-19 17:43:58 +02:00
allowList : DefaultAllowlist ,
2022-05-13 08:07:23 +02:00
content : { } ,
// { selector : text , selector2 : text2 , }
2022-07-19 17:43:58 +02:00
extraClass : '' ,
2022-05-13 08:07:23 +02:00
html : false ,
sanitize : true ,
sanitizeFn : null ,
2022-07-19 17:43:58 +02:00
template : '<div></div>'
2022-05-13 08:07:23 +02:00
} ;
const DefaultType$4 = {
2022-07-19 17:43:58 +02:00
allowList : 'object' ,
2022-05-13 08:07:23 +02:00
content : 'object' ,
2022-07-19 17:43:58 +02:00
extraClass : '(string|function)' ,
2018-11-13 07:41:12 +01:00
html : 'boolean' ,
2019-02-13 17:01:40 +01:00
sanitize : 'boolean' ,
sanitizeFn : '(null|function)' ,
2022-07-19 17:43:58 +02:00
template : 'string'
2018-11-13 07:41:12 +01:00
} ;
2022-05-13 08:07:23 +02:00
const DefaultContentType = {
2022-07-19 17:43:58 +02:00
entry : '(string|element|function|null)' ,
selector : '(string|element)'
2022-05-13 08:07:23 +02:00
} ;
/ * *
* Class definition
* /
class TemplateFactory extends Config {
constructor ( config ) {
super ( ) ;
this . _config = this . _getConfig ( config ) ;
} // Getters
static get Default ( ) {
return Default$4 ;
}
static get DefaultType ( ) {
return DefaultType$4 ;
}
static get NAME ( ) {
return NAME$5 ;
} // Public
getContent ( ) {
return Object . values ( this . _config . content ) . map ( config => this . _resolvePossibleFunction ( config ) ) . filter ( Boolean ) ;
}
hasContent ( ) {
return this . getContent ( ) . length > 0 ;
}
changeContent ( content ) {
this . _checkContent ( content ) ;
this . _config . content = { ... this . _config . content ,
... content
} ;
return this ;
}
toHtml ( ) {
const templateWrapper = document . createElement ( 'div' ) ;
templateWrapper . innerHTML = this . _maybeSanitize ( this . _config . template ) ;
for ( const [ selector , text ] of Object . entries ( this . _config . content ) ) {
this . _setContent ( templateWrapper , text , selector ) ;
}
const template = templateWrapper . children [ 0 ] ;
const extraClass = this . _resolvePossibleFunction ( this . _config . extraClass ) ;
if ( extraClass ) {
template . classList . add ( ... extraClass . split ( ' ' ) ) ;
}
return template ;
} // Private
_typeCheckConfig ( config ) {
super . _typeCheckConfig ( config ) ;
this . _checkContent ( config . content ) ;
}
_checkContent ( arg ) {
for ( const [ selector , content ] of Object . entries ( arg ) ) {
super . _typeCheckConfig ( {
selector ,
entry : content
} , DefaultContentType ) ;
}
}
_setContent ( template , content , selector ) {
const templateElement = SelectorEngine . findOne ( selector , template ) ;
if ( ! templateElement ) {
return ;
}
content = this . _resolvePossibleFunction ( content ) ;
if ( ! content ) {
templateElement . remove ( ) ;
return ;
}
if ( isElement ( content ) ) {
this . _putElementInTemplate ( getElement ( content ) , templateElement ) ;
return ;
}
if ( this . _config . html ) {
templateElement . innerHTML = this . _maybeSanitize ( content ) ;
return ;
}
templateElement . textContent = content ;
}
_maybeSanitize ( arg ) {
return this . _config . sanitize ? sanitizeHtml ( arg , this . _config . allowList , this . _config . sanitizeFn ) : arg ;
}
_resolvePossibleFunction ( arg ) {
return typeof arg === 'function' ? arg ( this ) : arg ;
}
_putElementInTemplate ( element , templateElement ) {
if ( this . _config . html ) {
templateElement . innerHTML = '' ;
templateElement . append ( element ) ;
return ;
}
templateElement . textContent = element . textContent ;
}
}
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : tooltip . js
2022-05-13 08:07:23 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* Constants
* /
const NAME$4 = 'tooltip' ;
const DISALLOWED _ATTRIBUTES = new Set ( [ 'sanitize' , 'allowList' , 'sanitizeFn' ] ) ;
const CLASS _NAME _FADE$2 = 'fade' ;
const CLASS _NAME _MODAL = 'modal' ;
const CLASS _NAME _SHOW$2 = 'show' ;
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 _FOCUS = 'focus' ;
const TRIGGER _CLICK = 'click' ;
const TRIGGER _MANUAL = 'manual' ;
const EVENT _HIDE$2 = 'hide' ;
const EVENT _HIDDEN$2 = 'hidden' ;
const EVENT _SHOW$2 = 'show' ;
const EVENT _SHOWN$2 = 'shown' ;
const EVENT _INSERTED = 'inserted' ;
const EVENT _CLICK$1 = 'click' ;
const EVENT _FOCUSIN$1 = 'focusin' ;
const EVENT _FOCUSOUT$1 = 'focusout' ;
const EVENT _MOUSEENTER = 'mouseenter' ;
const EVENT _MOUSELEAVE = 'mouseleave' ;
2021-03-23 17:26:54 +01:00
const AttachmentMap = {
2018-11-13 07:41:12 +01:00
AUTO : 'auto' ,
TOP : 'top' ,
2021-03-23 17:26:54 +01:00
RIGHT : isRTL ( ) ? 'left' : 'right' ,
2018-11-13 07:41:12 +01:00
BOTTOM : 'bottom' ,
2021-03-23 17:26:54 +01:00
LEFT : isRTL ( ) ? 'right' : 'left'
2018-11-13 07:41:12 +01:00
} ;
2021-03-23 17:26:54 +01:00
const Default$3 = {
2022-07-19 17:43:58 +02:00
allowList : DefaultAllowlist ,
2018-11-13 07:41:12 +01:00
animation : true ,
2022-07-19 17:43:58 +02:00
boundary : 'clippingParents' ,
container : false ,
customClass : '' ,
2018-11-13 07:41:12 +01:00
delay : 0 ,
2022-07-19 17:43:58 +02:00
fallbackPlacements : [ 'top' , 'right' , 'bottom' , 'left' ] ,
2018-11-13 07:41:12 +01:00
html : false ,
2021-02-10 17:14:51 +01:00
offset : [ 0 , 0 ] ,
2022-07-19 17:43:58 +02:00
placement : 'top' ,
popperConfig : null ,
2019-02-13 17:01:40 +01:00
sanitize : true ,
sanitizeFn : null ,
2022-07-19 17:43:58 +02:00
selector : false ,
template : '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>' ,
title : '' ,
trigger : 'hover focus'
2018-11-13 07:41:12 +01:00
} ;
2022-05-13 08:07:23 +02:00
const DefaultType$3 = {
2022-07-19 17:43:58 +02:00
allowList : 'object' ,
2022-05-13 08:07:23 +02:00
animation : 'boolean' ,
2022-07-19 17:43:58 +02:00
boundary : '(string|element)' ,
container : '(string|element|boolean)' ,
customClass : '(string|function)' ,
2022-05-13 08:07:23 +02:00
delay : '(number|object)' ,
2022-07-19 17:43:58 +02:00
fallbackPlacements : 'array' ,
2022-05-13 08:07:23 +02:00
html : 'boolean' ,
offset : '(array|string|function)' ,
2022-07-19 17:43:58 +02:00
placement : '(string|function)' ,
popperConfig : '(null|object|function)' ,
2022-05-13 08:07:23 +02:00
sanitize : 'boolean' ,
sanitizeFn : '(null|function)' ,
2022-07-19 17:43:58 +02:00
selector : '(string|boolean)' ,
template : 'string' ,
title : '(string|element|function)' ,
trigger : 'string'
2018-11-13 07:41:12 +01:00
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
class Tooltip extends BaseComponent {
constructor ( element , config ) {
2020-12-07 16:50:24 +01:00
if ( typeof Popper _ _namespace === 'undefined' ) {
2020-11-23 14:17:16 +01:00
throw new TypeError ( 'Bootstrap\'s tooltips require Popper (https://popper.js.org)' ) ;
2020-12-03 15:18:59 +01:00
}
2017-10-30 00:19:14 +01:00
2022-05-13 08:07:23 +02:00
super ( element , config ) ; // Private
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
this . _isEnabled = true ;
this . _timeout = 0 ;
2022-05-13 08:07:23 +02:00
this . _isHovered = false ;
2021-03-23 17:26:54 +01:00
this . _activeTrigger = { } ;
2022-05-13 08:07:23 +02:00
this . _popper = null ;
2022-07-19 17:43:58 +02:00
this . _templateFactory = null ;
this . _newContent = null ; // Protected
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
this . tip = null ;
2019-03-01 17:31:34 +01:00
2021-03-23 17:26:54 +01:00
this . _setListeners ( ) ;
2018-11-13 07:41:12 +01:00
} // Getters
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static get Default ( ) {
return Default$3 ;
}
static get DefaultType ( ) {
return DefaultType$3 ;
2022-05-13 08:07:23 +02:00
}
static get NAME ( ) {
return NAME$4 ;
2021-03-23 17:26:54 +01:00
} // Public
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
enable ( ) {
2018-11-13 07:41:12 +01:00
this . _isEnabled = true ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
disable ( ) {
2018-11-13 07:41:12 +01:00
this . _isEnabled = false ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
toggleEnabled ( ) {
2018-11-13 07:41:12 +01:00
this . _isEnabled = ! this . _isEnabled ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
toggle ( event ) {
2018-11-13 07:41:12 +01:00
if ( ! this . _isEnabled ) {
return ;
}
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
if ( event ) {
2021-03-23 17:26:54 +01:00
const context = this . _initializeOnDelegatedTarget ( event ) ;
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
context . _activeTrigger . click = ! context . _activeTrigger . click ;
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
if ( context . _isWithActiveTrigger ( ) ) {
2022-05-13 08:07:23 +02:00
context . _enter ( ) ;
2017-09-06 06:05:12 +02:00
} else {
2022-05-13 08:07:23 +02:00
context . _leave ( ) ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
return ;
}
if ( this . _isShown ( ) ) {
this . _leave ( ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
return ;
2018-11-13 07:41:12 +01:00
}
2022-05-13 08:07:23 +02:00
this . _enter ( ) ;
2021-03-23 17:26:54 +01:00
}
2017-09-06 06:05:12 +02:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2018-11-13 07:41:12 +01:00
clearTimeout ( this . _timeout ) ;
2021-08-04 17:41:51 +02:00
EventHandler . off ( this . _element . closest ( SELECTOR _MODAL ) , EVENT _MODAL _HIDE , this . _hideModalHandler ) ;
2015-08-15 21:19:11 +02:00
2021-06-22 20:29:16 +02:00
if ( this . tip ) {
this . tip . remove ( ) ;
2018-11-13 07:41:12 +01:00
}
2017-09-30 23:28:03 +02:00
2021-09-07 17:37:44 +02:00
this . _disposePopper ( ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
super . dispose ( ) ;
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
show ( ) {
2020-12-03 15:18:59 +01:00
if ( this . _element . style . display === 'none' ) {
2018-11-13 07:41:12 +01:00
throw new Error ( 'Please use show on visible elements' ) ;
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
if ( ! ( this . _isWithContent ( ) && this . _isEnabled ) ) {
2021-02-10 17:14:51 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const showEvent = EventHandler . trigger ( this . _element , this . constructor . eventName ( EVENT _SHOW$2 ) ) ;
2021-03-23 17:26:54 +01:00
const shadowRoot = findShadowRoot ( this . _element ) ;
2022-05-13 08:07:23 +02:00
const isInTheDom = ( shadowRoot || this . _element . ownerDocument . documentElement ) . contains ( this . _element ) ;
2017-09-06 06:05:12 +02:00
2021-02-10 17:14:51 +01:00
if ( showEvent . defaultPrevented || ! isInTheDom ) {
return ;
2022-07-19 17:43:58 +02:00
} // todo v6 remove this OR make it optional
if ( this . tip ) {
this . tip . remove ( ) ;
this . tip = null ;
2021-02-10 17:14:51 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const tip = this . _getTipElement ( ) ;
2018-12-16 00:13:22 +01:00
2022-05-13 08:07:23 +02:00
this . _element . setAttribute ( 'aria-describedby' , tip . getAttribute ( 'id' ) ) ;
2018-12-16 00:13:22 +01:00
2021-05-13 18:22:20 +02:00
const {
container
} = this . _config ;
2018-11-13 07:41:12 +01:00
2021-02-10 17:14:51 +01:00
if ( ! this . _element . ownerDocument . documentElement . contains ( this . tip ) ) {
2021-08-04 17:41:51 +02:00
container . append ( tip ) ;
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , this . constructor . eventName ( EVENT _INSERTED ) ) ;
2021-03-23 17:26:54 +01:00
}
if ( this . _popper ) {
this . _popper . update ( ) ;
} else {
2022-07-19 17:43:58 +02:00
this . _popper = this . _createPopper ( tip ) ;
2021-02-10 17:14:51 +01:00
}
2020-12-03 15:18:59 +01:00
2022-05-13 08:07:23 +02:00
tip . classList . add ( CLASS _NAME _SHOW$2 ) ; // If this is a touch-enabled device we add extra
2021-02-10 17:14:51 +01:00
// empty mouseover listeners to the body's immediate children;
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
2020-12-03 15:18:59 +01:00
2021-02-10 17:14:51 +01:00
if ( 'ontouchstart' in document . documentElement ) {
2022-05-13 08:07:23 +02:00
for ( const element of [ ] . concat ( ... document . body . children ) ) {
2021-05-05 21:32:12 +02:00
EventHandler . on ( element , 'mouseover' , noop ) ;
2022-05-13 08:07:23 +02:00
}
2021-02-10 17:14:51 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
2022-05-13 08:07:23 +02:00
const previousHoverState = this . _isHovered ;
this . _isHovered = false ;
EventHandler . trigger ( this . _element , this . constructor . eventName ( EVENT _SHOWN$2 ) ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
if ( previousHoverState ) {
this . _leave ( ) ;
2017-09-06 06:05:12 +02:00
}
2021-02-10 17:14:51 +01:00
} ;
2022-05-13 08:07:23 +02:00
this . _queueCallback ( complete , this . tip , this . _isAnimated ( ) ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
hide ( ) {
2022-05-13 08:07:23 +02:00
if ( ! this . _isShown ( ) ) {
2020-09-29 17:33:00 +02:00
return ;
}
2022-05-13 08:07:23 +02:00
const hideEvent = EventHandler . trigger ( this . _element , this . constructor . eventName ( EVENT _HIDE$2 ) ) ;
2017-09-06 06:05:12 +02:00
2019-03-01 17:31:34 +01:00
if ( hideEvent . defaultPrevented ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const tip = this . _getTipElement ( ) ;
2021-08-04 17:41:51 +02:00
tip . classList . remove ( CLASS _NAME _SHOW$2 ) ; // If this is a touch-enabled device we remove the extra
2018-11-13 07:41:12 +01:00
// empty mouseover listeners we added for iOS support
2017-09-30 23:28:03 +02:00
2018-11-13 07:41:12 +01:00
if ( 'ontouchstart' in document . documentElement ) {
2022-05-13 08:07:23 +02:00
for ( const element of [ ] . concat ( ... document . body . children ) ) {
EventHandler . off ( element , 'mouseover' , noop ) ;
}
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2020-03-28 11:29:08 +01:00
this . _activeTrigger [ TRIGGER _CLICK ] = false ;
this . _activeTrigger [ TRIGGER _FOCUS ] = false ;
this . _activeTrigger [ TRIGGER _HOVER ] = false ;
2022-05-13 08:07:23 +02:00
this . _isHovered = false ;
const complete = ( ) => {
if ( this . _isWithActiveTrigger ( ) ) {
return ;
}
if ( ! this . _isHovered ) {
tip . remove ( ) ;
}
this . _element . removeAttribute ( 'aria-describedby' ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
EventHandler . trigger ( this . _element , this . constructor . eventName ( EVENT _HIDDEN$2 ) ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
this . _disposePopper ( ) ;
} ;
this . _queueCallback ( complete , this . tip , this . _isAnimated ( ) ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
update ( ) {
2022-05-13 08:07:23 +02:00
if ( this . _popper ) {
2020-12-07 16:50:24 +01:00
this . _popper . update ( ) ;
2018-11-13 07:41:12 +01:00
}
2019-01-04 17:29:45 +01:00
} // Protected
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
_isWithContent ( ) {
return Boolean ( this . _getTitle ( ) ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_getTipElement ( ) {
if ( ! this . tip ) {
2022-07-19 17:43:58 +02:00
this . tip = this . _createTipElement ( this . _newContent || this . _getContentForTemplate ( ) ) ;
2019-03-01 17:31:34 +01:00
}
2018-11-13 07:41:12 +01:00
return this . tip ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_createTipElement ( content ) {
const tip = this . _getTemplateFactory ( content ) . toHtml ( ) ; // todo: remove this check on v6
2021-08-04 17:41:51 +02:00
2022-05-13 08:07:23 +02:00
if ( ! tip ) {
return null ;
}
2021-08-04 17:41:51 +02:00
2022-05-13 08:07:23 +02:00
tip . classList . remove ( CLASS _NAME _FADE$2 , CLASS _NAME _SHOW$2 ) ; // todo: on v6 the following can be achieved with CSS only
2021-08-04 17:41:51 +02:00
2022-05-13 08:07:23 +02:00
tip . classList . add ( ` bs- ${ this . constructor . NAME } -auto ` ) ;
const tipId = getUID ( this . constructor . NAME ) . toString ( ) ;
tip . setAttribute ( 'id' , tipId ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( this . _isAnimated ( ) ) {
tip . classList . add ( CLASS _NAME _FADE$2 ) ;
2019-03-01 17:31:34 +01:00
}
2022-05-13 08:07:23 +02:00
return tip ;
}
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
setContent ( content ) {
2022-07-19 17:43:58 +02:00
this . _newContent = content ;
2019-02-13 17:01:40 +01:00
2022-07-19 17:43:58 +02:00
if ( this . _isShown ( ) ) {
this . _disposePopper ( ) ;
2022-05-13 08:07:23 +02:00
this . show ( ) ;
2018-11-13 07:41:12 +01:00
}
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_getTemplateFactory ( content ) {
if ( this . _templateFactory ) {
this . _templateFactory . changeContent ( content ) ;
} else {
this . _templateFactory = new TemplateFactory ( { ... this . _config ,
// the `content` var has to be after `this._config`
// to override config.content in case of popover
content ,
extraClass : this . _resolvePossibleFunction ( this . _config . customClass )
} ) ;
}
return this . _templateFactory ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_getContentForTemplate ( ) {
return {
[ SELECTOR _TOOLTIP _INNER ] : this . _getTitle ( )
} ;
2021-03-23 17:26:54 +01:00
}
2020-12-03 14:08:31 +01:00
2022-05-13 08:07:23 +02:00
_getTitle ( ) {
2022-07-19 17:43:58 +02:00
return this . _resolvePossibleFunction ( this . _config . title ) || this . _config . originalTitle ;
2022-05-13 08:07:23 +02:00
} // Private
2020-12-03 14:08:31 +01:00
2022-05-13 08:07:23 +02:00
_initializeOnDelegatedTarget ( event ) {
return this . constructor . getOrCreateInstance ( event . delegateTarget , this . _getDelegateConfig ( ) ) ;
}
_isAnimated ( ) {
return this . _config . animation || this . tip && this . tip . classList . contains ( CLASS _NAME _FADE$2 ) ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_isShown ( ) {
return this . tip && this . tip . classList . contains ( CLASS _NAME _SHOW$2 ) ;
}
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
_createPopper ( tip ) {
const placement = typeof this . _config . placement === 'function' ? this . _config . placement . call ( this , tip , this . _element ) : this . _config . placement ;
const attachment = AttachmentMap [ placement . toUpperCase ( ) ] ;
2022-07-19 17:43:58 +02:00
return Popper _ _namespace . createPopper ( this . _element , tip , this . _getPopperConfig ( attachment ) ) ;
2021-03-23 17:26:54 +01:00
}
2019-08-27 15:03:21 +02:00
2021-03-23 17:26:54 +01:00
_getOffset ( ) {
const {
offset
2021-05-13 18:22:20 +02:00
} = this . _config ;
2021-02-10 17:14:51 +01:00
if ( typeof offset === 'string' ) {
2022-05-13 08:07:23 +02:00
return offset . split ( ',' ) . map ( value => Number . parseInt ( value , 10 ) ) ;
2021-02-10 17:14:51 +01:00
}
2020-12-07 16:50:24 +01:00
2021-02-10 17:14:51 +01:00
if ( typeof offset === 'function' ) {
2021-03-23 17:26:54 +01:00
return popperData => offset ( popperData , this . _element ) ;
2020-12-07 16:50:24 +01:00
}
2021-02-10 17:14:51 +01:00
return offset ;
2021-03-23 17:26:54 +01:00
}
2021-02-10 17:14:51 +01:00
2022-05-13 08:07:23 +02:00
_resolvePossibleFunction ( arg ) {
return typeof arg === 'function' ? arg . call ( this . _element ) : arg ;
2021-08-04 17:41:51 +02:00
}
2021-03-23 17:26:54 +01:00
_getPopperConfig ( attachment ) {
const defaultBsPopperConfig = {
2019-08-27 15:03:21 +02:00
placement : attachment ,
2021-02-10 17:14:51 +01:00
modifiers : [ {
name : 'flip' ,
options : {
2021-05-13 18:22:20 +02:00
fallbackPlacements : this . _config . fallbackPlacements
2021-02-10 17:14:51 +01:00
}
} , {
name : 'offset' ,
options : {
offset : this . _getOffset ( )
}
} , {
2020-12-07 16:50:24 +01:00
name : 'preventOverflow' ,
options : {
2021-05-13 18:22:20 +02:00
boundary : this . _config . boundary
2020-12-07 16:50:24 +01:00
}
} , {
name : 'arrow' ,
options : {
2021-03-23 17:26:54 +01:00
element : ` . ${ this . constructor . NAME } -arrow `
2019-08-27 15:03:21 +02:00
}
2020-12-07 16:50:24 +01:00
} , {
2022-05-13 08:07:23 +02:00
name : 'preSetPlacement' ,
2020-12-07 16:50:24 +01:00
enabled : true ,
2022-05-13 08:07:23 +02:00
phase : 'beforeMain' ,
fn : data => {
// Pre-set Popper's placement attribute in order to read the arrow sizes properly.
// Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
this . _getTipElement ( ) . setAttribute ( 'data-popper-placement' , data . state . placement ) ;
2019-08-27 15:03:21 +02:00
}
2022-05-13 08:07:23 +02:00
} ]
2019-08-27 15:03:21 +02:00
} ;
2021-03-23 17:26:54 +01:00
return { ... defaultBsPopperConfig ,
2021-05-13 18:22:20 +02:00
... ( typeof this . _config . popperConfig === 'function' ? this . _config . popperConfig ( defaultBsPopperConfig ) : this . _config . popperConfig )
2021-03-23 17:26:54 +01:00
} ;
}
2019-08-27 15:03:21 +02:00
2021-03-23 17:26:54 +01:00
_setListeners ( ) {
2021-05-13 18:22:20 +02:00
const triggers = this . _config . trigger . split ( ' ' ) ;
2022-05-13 08:07:23 +02:00
for ( const trigger of triggers ) {
2018-11-13 07:41:12 +01:00
if ( trigger === 'click' ) {
2022-05-13 08:07:23 +02:00
EventHandler . on ( this . _element , this . constructor . eventName ( EVENT _CLICK$1 ) , this . _config . selector , event => this . toggle ( event ) ) ;
2020-03-28 11:29:08 +01:00
} else if ( trigger !== TRIGGER _MANUAL ) {
2022-05-13 08:07:23 +02:00
const eventIn = trigger === TRIGGER _HOVER ? this . constructor . eventName ( EVENT _MOUSEENTER ) : this . constructor . eventName ( EVENT _FOCUSIN$1 ) ;
const eventOut = trigger === TRIGGER _HOVER ? this . constructor . eventName ( EVENT _MOUSELEAVE ) : this . constructor . eventName ( EVENT _FOCUSOUT$1 ) ;
EventHandler . on ( this . _element , eventIn , this . _config . selector , event => {
const context = this . _initializeOnDelegatedTarget ( event ) ;
context . _activeTrigger [ event . type === 'focusin' ? TRIGGER _FOCUS : TRIGGER _HOVER ] = true ;
context . _enter ( ) ;
} ) ;
EventHandler . on ( this . _element , eventOut , this . _config . selector , event => {
const context = this . _initializeOnDelegatedTarget ( event ) ;
context . _activeTrigger [ event . type === 'focusout' ? TRIGGER _FOCUS : TRIGGER _HOVER ] = context . _element . contains ( event . relatedTarget ) ;
context . _leave ( ) ;
} ) ;
2017-09-06 06:05:12 +02:00
}
2022-05-13 08:07:23 +02:00
}
2019-07-12 23:56:26 +02:00
2021-03-23 17:26:54 +01:00
this . _hideModalHandler = ( ) => {
if ( this . _element ) {
this . hide ( ) ;
2018-11-13 07:41:12 +01:00
}
2019-07-12 23:56:26 +02:00
} ;
2021-08-04 17:41:51 +02:00
EventHandler . on ( this . _element . closest ( SELECTOR _MODAL ) , EVENT _MODAL _HIDE , this . _hideModalHandler ) ;
2015-08-15 21:19:11 +02:00
2021-05-13 18:22:20 +02:00
if ( this . _config . selector ) {
this . _config = { ... this . _config ,
2018-11-13 07:41:12 +01:00
trigger : 'manual' ,
selector : ''
2021-03-23 17:26:54 +01:00
} ;
2018-11-13 07:41:12 +01:00
} else {
this . _fixTitle ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
_fixTitle ( ) {
2022-05-13 08:07:23 +02:00
const title = this . _config . originalTitle ;
2020-12-03 15:18:59 +01:00
2022-05-13 08:07:23 +02:00
if ( ! title ) {
return ;
2018-11-13 07:41:12 +01:00
}
2015-08-15 21:19:11 +02:00
2022-07-19 17:43:58 +02:00
if ( ! this . _element . getAttribute ( 'aria-label' ) && ! this . _element . textContent . trim ( ) ) {
2022-05-13 08:07:23 +02:00
this . _element . setAttribute ( 'aria-label' , title ) ;
2018-11-13 07:41:12 +01:00
}
2022-05-13 08:07:23 +02:00
this . _element . removeAttribute ( 'title' ) ;
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
_enter ( ) {
if ( this . _isShown ( ) || this . _isHovered ) {
this . _isHovered = true ;
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
this . _isHovered = true ;
this . _setTimeout ( ( ) => {
if ( this . _isHovered ) {
this . show ( ) ;
2017-09-06 06:05:12 +02:00
}
2022-05-13 08:07:23 +02:00
} , this . _config . delay . show ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_leave ( ) {
if ( this . _isWithActiveTrigger ( ) ) {
2018-11-13 07:41:12 +01:00
return ;
}
2015-08-19 07:07:45 +02:00
2022-05-13 08:07:23 +02:00
this . _isHovered = false ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
this . _setTimeout ( ( ) => {
if ( ! this . _isHovered ) {
this . hide ( ) ;
2017-09-06 06:05:12 +02:00
}
2022-05-13 08:07:23 +02:00
} , this . _config . delay . hide ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_setTimeout ( handler , timeout ) {
clearTimeout ( this . _timeout ) ;
this . _timeout = setTimeout ( handler , timeout ) ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_isWithActiveTrigger ( ) {
return Object . values ( this . _activeTrigger ) . includes ( true ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
const dataAttributes = Manipulator . getDataAttributes ( this . _element ) ;
2022-05-13 08:07:23 +02:00
for ( const dataAttribute of Object . keys ( dataAttributes ) ) {
if ( DISALLOWED _ATTRIBUTES . has ( dataAttribute ) ) {
delete dataAttributes [ dataAttribute ] ;
2019-02-13 17:01:40 +01:00
}
2022-05-13 08:07:23 +02:00
}
config = { ... dataAttributes ,
2021-03-23 17:26:54 +01:00
... ( typeof config === 'object' && config ? config : { } )
} ;
2022-05-13 08:07:23 +02:00
config = this . _mergeConfigObj ( config ) ;
config = this . _configAfterMerge ( config ) ;
this . _typeCheckConfig ( config ) ;
return config ;
}
_configAfterMerge ( config ) {
2021-05-13 18:22:20 +02:00
config . container = config . container === false ? document . body : getElement ( config . container ) ;
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
if ( typeof config . delay === 'number' ) {
config . delay = {
show : config . delay ,
hide : config . delay
} ;
}
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
config . originalTitle = this . _element . getAttribute ( 'title' ) || '' ;
2018-11-13 07:41:12 +01:00
if ( typeof config . title === 'number' ) {
config . title = config . title . toString ( ) ;
}
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
if ( typeof config . content === 'number' ) {
config . content = config . content . toString ( ) ;
}
2015-08-15 21:19:11 +02:00
2018-11-13 07:41:12 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2017-09-06 06:05:12 +02:00
2021-03-23 17:26:54 +01:00
_getDelegateConfig ( ) {
const config = { } ;
2017-09-06 06:05:12 +02:00
2021-08-04 17:41:51 +02:00
for ( const key in this . _config ) {
if ( this . constructor . Default [ key ] !== this . _config [ key ] ) {
config [ key ] = this . _config [ key ] ;
2017-09-06 06:05:12 +02:00
}
2021-08-04 17:41:51 +02:00
} // 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)`
2017-09-06 06:05:12 +02:00
2018-11-13 07:41:12 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-09-07 17:37:44 +02:00
_disposePopper ( ) {
if ( this . _popper ) {
this . _popper . destroy ( ) ;
this . _popper = null ;
}
2019-01-04 17:29:45 +01:00
} // Static
2016-10-10 02:26:51 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2018-11-13 07:41:12 +01:00
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Tooltip . getOrCreateInstance ( this , config ) ;
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
if ( typeof config !== 'string' ) {
return ;
}
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
if ( typeof data [ config ] === 'undefined' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2018-03-31 22:59:37 +02:00
}
2022-05-13 08:07:23 +02:00
data [ config ] ( ) ;
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
* jQuery
* /
2017-09-30 23:28:03 +02:00
2019-07-24 08:13:50 +02:00
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Tooltip ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : popover . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2021-03-23 17:26:54 +01:00
const NAME$3 = 'popover' ;
2022-05-13 08:07:23 +02:00
const SELECTOR _TITLE = '.popover-header' ;
const SELECTOR _CONTENT = '.popover-body' ;
2021-03-23 17:26:54 +01:00
const Default$2 = { ... Tooltip . Default ,
2018-11-13 07:41:12 +01:00
content : '' ,
2022-07-19 17:43:58 +02:00
offset : [ 0 , 8 ] ,
placement : 'right' ,
template : '<div class="popover" role="tooltip">' + '<div class="popover-arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div>' + '</div>' ,
trigger : 'click'
2021-03-23 17:26:54 +01:00
} ;
const DefaultType$2 = { ... Tooltip . DefaultType ,
2022-05-13 08:07:23 +02:00
content : '(null|string|element|function)'
2021-03-23 17:26:54 +01:00
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
class Popover extends Tooltip {
// Getters
2022-05-13 08:07:23 +02:00
static get Default ( ) {
return Default$2 ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static get DefaultType ( ) {
return DefaultType$2 ;
}
2017-11-08 05:45:26 +01:00
2022-05-13 08:07:23 +02:00
static get NAME ( ) {
return NAME$3 ;
} // Overrides
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
_isWithContent ( ) {
return this . _getTitle ( ) || this . _getContent ( ) ;
2020-09-14 17:12:06 +02:00
} // Private
2019-08-27 15:03:21 +02:00
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
_getContentForTemplate ( ) {
return {
[ SELECTOR _TITLE ] : this . _getTitle ( ) ,
[ SELECTOR _CONTENT ] : this . _getContent ( )
} ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_getContent ( ) {
return this . _resolvePossibleFunction ( this . _config . content ) ;
2019-01-04 17:29:45 +01:00
} // Static
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2018-11-13 07:41:12 +01:00
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Popover . getOrCreateInstance ( this , config ) ;
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
if ( typeof config !== 'string' ) {
return ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( typeof data [ config ] === 'undefined' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2018-03-31 22:59:37 +02:00
}
2022-05-13 08:07:23 +02:00
data [ config ] ( ) ;
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
* jQuery
* /
2017-09-30 23:28:03 +02:00
2019-07-24 08:13:50 +02:00
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Popover ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : scrollspy . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2021-03-23 17:26:54 +01:00
const NAME$2 = 'scrollspy' ;
const DATA _KEY$2 = 'bs.scrollspy' ;
const EVENT _KEY$2 = ` . ${ DATA _KEY$2 } ` ;
2022-05-13 08:07:23 +02:00
const DATA _API _KEY = '.data-api' ;
2021-03-23 17:26:54 +01:00
const EVENT _ACTIVATE = ` activate ${ EVENT _KEY$2 } ` ;
2022-05-13 08:07:23 +02:00
const EVENT _CLICK = ` click ${ EVENT _KEY$2 } ` ;
const EVENT _LOAD _DATA _API$1 = ` load ${ EVENT _KEY$2 } ${ DATA _API _KEY } ` ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _DROPDOWN _ITEM = 'dropdown-item' ;
const CLASS _NAME _ACTIVE$1 = 'active' ;
const SELECTOR _DATA _SPY = '[data-bs-spy="scroll"]' ;
2022-05-13 08:07:23 +02:00
const SELECTOR _TARGET _LINKS = '[href]' ;
const SELECTOR _NAV _LIST _GROUP = '.nav, .list-group' ;
2021-03-23 17:26:54 +01:00
const SELECTOR _NAV _LINKS = '.nav-link' ;
const SELECTOR _NAV _ITEMS = '.nav-item' ;
const SELECTOR _LIST _ITEMS = '.list-group-item' ;
2022-05-13 08:07:23 +02:00
const SELECTOR _LINK _ITEMS = ` ${ SELECTOR _NAV _LINKS } , ${ SELECTOR _NAV _ITEMS } > ${ SELECTOR _NAV _LINKS } , ${ SELECTOR _LIST _ITEMS } ` ;
const SELECTOR _DROPDOWN = '.dropdown' ;
2021-03-23 17:26:54 +01:00
const SELECTOR _DROPDOWN _TOGGLE$1 = '.dropdown-toggle' ;
2022-05-13 08:07:23 +02:00
const Default$1 = {
offset : null ,
// TODO: v6 @deprecated, keep it for backwards compatibility reasons
rootMargin : '0px 0px -25%' ,
smoothScroll : false ,
target : null
} ;
const DefaultType$1 = {
offset : '(number|null)' ,
// TODO v6 @deprecated, keep it for backwards compatibility reasons
rootMargin : 'string' ,
smoothScroll : 'boolean' ,
target : 'element'
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
class ScrollSpy extends BaseComponent {
constructor ( element , config ) {
2022-05-13 08:07:23 +02:00
super ( element , config ) ; // this._element is the observablesContainer and config.target the menu links wrapper
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
this . _targetLinks = new Map ( ) ;
this . _observableSections = new Map ( ) ;
this . _rootElement = getComputedStyle ( this . _element ) . overflowY === 'visible' ? null : this . _element ;
this . _activeTarget = null ;
this . _observer = null ;
this . _previousScrollData = {
visibleEntryTop : 0 ,
parentScrollTop : 0
} ;
this . refresh ( ) ; // initialize
2018-11-13 07:41:12 +01:00
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
return Default$1 ;
}
2022-05-13 08:07:23 +02:00
static get DefaultType ( ) {
return DefaultType$1 ;
}
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
return NAME$2 ;
2021-03-23 17:26:54 +01:00
} // Public
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
refresh ( ) {
2022-05-13 08:07:23 +02:00
this . _initializeTargetsAndObservables ( ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
this . _maybeEnableSmoothScroll ( ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
if ( this . _observer ) {
this . _observer . disconnect ( ) ;
} else {
this . _observer = this . _getNewObserver ( ) ;
}
for ( const section of this . _observableSections . values ( ) ) {
this . _observer . observe ( section ) ;
}
2021-03-23 17:26:54 +01:00
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2022-05-13 08:07:23 +02:00
this . _observer . disconnect ( ) ;
2021-05-13 18:22:20 +02:00
super . dispose ( ) ;
2019-01-04 17:29:45 +01:00
} // Private
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
2022-05-13 08:07:23 +02:00
_configAfterMerge ( config ) {
// TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case
config . target = getElement ( config . target ) || document . body ;
2018-11-13 07:41:12 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
_maybeEnableSmoothScroll ( ) {
if ( ! this . _config . smoothScroll ) {
return ;
} // unregister any previous listeners
2018-11-13 07:41:12 +01:00
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
EventHandler . off ( this . _config . target , EVENT _CLICK ) ;
EventHandler . on ( this . _config . target , EVENT _CLICK , SELECTOR _TARGET _LINKS , event => {
const observableSection = this . _observableSections . get ( event . target . hash ) ;
if ( observableSection ) {
event . preventDefault ( ) ;
const root = this . _rootElement || window ;
const height = observableSection . offsetTop - this . _element . offsetTop ;
if ( root . scrollTo ) {
root . scrollTo ( {
2022-07-19 17:43:58 +02:00
top : height ,
behavior : 'smooth'
2022-05-13 08:07:23 +02:00
} ) ;
return ;
} // Chrome 60 doesn't support `scrollTo`
root . scrollTop = height ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
_getNewObserver ( ) {
const options = {
root : this . _rootElement ,
threshold : [ 0.1 , 0.5 , 1 ] ,
rootMargin : this . _getRootMargin ( )
} ;
return new IntersectionObserver ( entries => this . _observerCallback ( entries ) , options ) ;
} // The logic of selection
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
_observerCallback ( entries ) {
const targetElement = entry => this . _targetLinks . get ( ` # ${ entry . target . id } ` ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
const activate = entry => {
this . _previousScrollData . visibleEntryTop = entry . target . offsetTop ;
this . _process ( targetElement ( entry ) ) ;
} ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
const parentScrollTop = ( this . _rootElement || document . documentElement ) . scrollTop ;
const userScrollsDown = parentScrollTop >= this . _previousScrollData . parentScrollTop ;
this . _previousScrollData . parentScrollTop = parentScrollTop ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
for ( const entry of entries ) {
if ( ! entry . isIntersecting ) {
this . _activeTarget = null ;
this . _clearActiveClass ( targetElement ( entry ) ) ;
continue ;
2018-11-13 07:41:12 +01:00
}
2022-05-13 08:07:23 +02:00
const entryIsLowerThanPrevious = entry . target . offsetTop >= this . _previousScrollData . visibleEntryTop ; // if we are scrolling down, pick the bigger offsetTop
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
if ( userScrollsDown && entryIsLowerThanPrevious ) {
activate ( entry ) ; // if parent isn't scrolled, let's keep the first visible item, breaking the iteration
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
if ( ! parentScrollTop ) {
return ;
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
continue ;
} // if we are scrolling up, pick the smallest offsetTop
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
if ( ! userScrollsDown && ! entryIsLowerThanPrevious ) {
activate ( entry ) ;
2018-11-13 07:41:12 +01:00
}
}
2022-05-13 08:07:23 +02:00
} // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only
_getRootMargin ( ) {
return this . _config . offset ? ` ${ this . _config . offset } px 0px -30% ` : this . _config . rootMargin ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_initializeTargetsAndObservables ( ) {
this . _targetLinks = new Map ( ) ;
this . _observableSections = new Map ( ) ;
const targetLinks = SelectorEngine . find ( SELECTOR _TARGET _LINKS , this . _config . target ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
for ( const anchor of targetLinks ) {
// ensure that the anchor has an id and is not disabled
if ( ! anchor . hash || isDisabled ( anchor ) ) {
continue ;
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
const observableSection = SelectorEngine . findOne ( anchor . hash , this . _element ) ; // ensure that the observableSection exists & is visible
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
if ( isVisible ( observableSection ) ) {
this . _targetLinks . set ( anchor . hash , anchor ) ;
2019-03-01 17:31:34 +01:00
2022-05-13 08:07:23 +02:00
this . _observableSections . set ( anchor . hash , observableSection ) ;
}
}
}
_process ( target ) {
if ( this . _activeTarget === target ) {
return ;
2018-11-13 07:41:12 +01:00
}
2018-03-31 22:59:37 +02:00
2022-05-13 08:07:23 +02:00
this . _clearActiveClass ( this . _config . target ) ;
this . _activeTarget = target ;
target . classList . add ( CLASS _NAME _ACTIVE$1 ) ;
this . _activateParents ( target ) ;
EventHandler . trigger ( this . _element , EVENT _ACTIVATE , {
2018-11-13 07:41:12 +01:00
relatedTarget : target
} ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_activateParents ( target ) {
// Activate dropdown parents
if ( target . classList . contains ( CLASS _NAME _DROPDOWN _ITEM ) ) {
SelectorEngine . findOne ( SELECTOR _DROPDOWN _TOGGLE$1 , target . closest ( SELECTOR _DROPDOWN ) ) . classList . add ( CLASS _NAME _ACTIVE$1 ) ;
return ;
}
for ( const listGroup of SelectorEngine . parents ( target , SELECTOR _NAV _LIST _GROUP ) ) {
// Set triggered links parents as active
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
for ( const item of SelectorEngine . prev ( listGroup , SELECTOR _LINK _ITEMS ) ) {
item . classList . add ( CLASS _NAME _ACTIVE$1 ) ;
}
}
}
_clearActiveClass ( parent ) {
parent . classList . remove ( CLASS _NAME _ACTIVE$1 ) ;
const activeNodes = SelectorEngine . find ( ` ${ SELECTOR _TARGET _LINKS } . ${ CLASS _NAME _ACTIVE$1 } ` , parent ) ;
for ( const node of activeNodes ) {
node . classList . remove ( CLASS _NAME _ACTIVE$1 ) ;
}
2019-01-04 17:29:45 +01:00
} // Static
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2018-11-13 07:41:12 +01:00
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = ScrollSpy . getOrCreateInstance ( this , config ) ;
2017-09-30 23:28:03 +02:00
2021-05-05 21:32:12 +02:00
if ( typeof config !== 'string' ) {
return ;
2017-09-06 06:05:12 +02:00
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
if ( data [ config ] === undefined || config . startsWith ( '_' ) || config === 'constructor' ) {
2021-05-05 21:32:12 +02:00
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2018-11-13 07:41:12 +01:00
}
2021-05-05 21:32:12 +02:00
data [ config ] ( ) ;
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2016-10-10 02:26:51 +02:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2018-11-13 07:41:12 +01:00
* /
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
EventHandler . on ( window , EVENT _LOAD _DATA _API$1 , ( ) => {
for ( const spy of SelectorEngine . find ( SELECTOR _DATA _SPY ) ) {
ScrollSpy . getOrCreateInstance ( spy ) ;
}
2018-11-13 07:41:12 +01:00
} ) ;
/ * *
* jQuery
* /
2015-08-15 21:19:11 +02:00
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( ScrollSpy ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : tab . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2018-11-13 07:41:12 +01:00
/ * *
* Constants
* /
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
const NAME$1 = 'tab' ;
const DATA _KEY$1 = 'bs.tab' ;
const EVENT _KEY$1 = ` . ${ DATA _KEY$1 } ` ;
const EVENT _HIDE$1 = ` hide ${ EVENT _KEY$1 } ` ;
const EVENT _HIDDEN$1 = ` hidden ${ EVENT _KEY$1 } ` ;
const EVENT _SHOW$1 = ` show ${ EVENT _KEY$1 } ` ;
const EVENT _SHOWN$1 = ` shown ${ EVENT _KEY$1 } ` ;
2022-05-13 08:07:23 +02:00
const EVENT _CLICK _DATA _API = ` click ${ EVENT _KEY$1 } ` ;
const EVENT _KEYDOWN = ` keydown ${ EVENT _KEY$1 } ` ;
const EVENT _LOAD _DATA _API = ` load ${ EVENT _KEY$1 } ` ;
const ARROW _LEFT _KEY = 'ArrowLeft' ;
const ARROW _RIGHT _KEY = 'ArrowRight' ;
const ARROW _UP _KEY = 'ArrowUp' ;
const ARROW _DOWN _KEY = 'ArrowDown' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _ACTIVE = 'active' ;
const CLASS _NAME _FADE$1 = 'fade' ;
const CLASS _NAME _SHOW$1 = 'show' ;
2022-05-13 08:07:23 +02:00
const CLASS _DROPDOWN = 'dropdown' ;
2021-03-23 17:26:54 +01:00
const SELECTOR _DROPDOWN _TOGGLE = '.dropdown-toggle' ;
2022-05-13 08:07:23 +02:00
const SELECTOR _DROPDOWN _MENU = '.dropdown-menu' ;
const SELECTOR _DROPDOWN _ITEM = '.dropdown-item' ;
const NOT _SELECTOR _DROPDOWN _TOGGLE = ':not(.dropdown-toggle)' ;
const SELECTOR _TAB _PANEL = '.list-group, .nav, [role="tablist"]' ;
const SELECTOR _OUTER = '.nav-item, .list-group-item' ;
const SELECTOR _INNER = ` .nav-link ${ NOT _SELECTOR _DROPDOWN _TOGGLE } , .list-group-item ${ NOT _SELECTOR _DROPDOWN _TOGGLE } , [role="tab"] ${ NOT _SELECTOR _DROPDOWN _TOGGLE } ` ;
const SELECTOR _DATA _TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]' ; // todo:v6: could be only `tab`
const SELECTOR _INNER _ELEM = ` ${ SELECTOR _INNER } , ${ SELECTOR _DATA _TOGGLE } ` ;
const SELECTOR _DATA _TOGGLE _ACTIVE = ` . ${ CLASS _NAME _ACTIVE } [data-bs-toggle="tab"], . ${ CLASS _NAME _ACTIVE } [data-bs-toggle="pill"], . ${ CLASS _NAME _ACTIVE } [data-bs-toggle="list"] ` ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2017-09-30 23:28:03 +02:00
2021-03-23 17:26:54 +01:00
class Tab extends BaseComponent {
2022-05-13 08:07:23 +02:00
constructor ( element ) {
super ( element ) ;
this . _parent = this . _element . closest ( SELECTOR _TAB _PANEL ) ;
if ( ! this . _parent ) {
return ; // todo: should Throw exception on v6
// throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`)
} // Set up initial aria attributes
this . _setInitialAttributes ( this . _parent , this . _getChildren ( ) ) ;
EventHandler . on ( this . _element , EVENT _KEYDOWN , event => this . _keydown ( event ) ) ;
} // Getters
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
return NAME$1 ;
2021-03-23 17:26:54 +01:00
} // Public
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
show ( ) {
2022-05-13 08:07:23 +02:00
// Shows this elem and deactivate the active sibling if exists
const innerElem = this . _element ;
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
if ( this . _elemIsActive ( innerElem ) ) {
return ;
} // Search for active tab on same parent to deactivate it
2020-05-13 20:53:43 +02:00
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
const active = this . _getActiveElem ( ) ;
2016-10-10 02:26:51 +02:00
2022-05-13 08:07:23 +02:00
const hideEvent = active ? EventHandler . trigger ( active , EVENT _HIDE$1 , {
relatedTarget : innerElem
2021-02-10 17:14:51 +01:00
} ) : null ;
2022-05-13 08:07:23 +02:00
const showEvent = EventHandler . trigger ( innerElem , EVENT _SHOW$1 , {
relatedTarget : active
2019-03-01 17:31:34 +01:00
} ) ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
if ( showEvent . defaultPrevented || hideEvent && hideEvent . defaultPrevented ) {
return ;
}
this . _deactivate ( active , innerElem ) ;
this . _activate ( innerElem , active ) ;
} // Private
_activate ( element , relatedElem ) {
if ( ! element ) {
2018-11-13 07:41:12 +01:00
return ;
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
element . classList . add ( CLASS _NAME _ACTIVE ) ;
this . _activate ( getElementFromSelector ( element ) ) ; // Search and activate/show the proper section
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
2022-05-13 08:07:23 +02:00
if ( element . getAttribute ( 'role' ) !== 'tab' ) {
2022-07-19 17:43:58 +02:00
element . classList . add ( CLASS _NAME _SHOW$1 ) ;
2022-05-13 08:07:23 +02:00
return ;
}
element . focus ( ) ;
element . removeAttribute ( 'tabindex' ) ;
element . setAttribute ( 'aria-selected' , true ) ;
this . _toggleDropDown ( element , true ) ;
EventHandler . trigger ( element , EVENT _SHOWN$1 , {
relatedTarget : relatedElem
2018-03-31 22:59:37 +02:00
} ) ;
2022-05-13 08:07:23 +02:00
} ;
2022-07-19 17:43:58 +02:00
this . _queueCallback ( complete , element , element . classList . contains ( CLASS _NAME _FADE$1 ) ) ;
2022-05-13 08:07:23 +02:00
}
_deactivate ( element , relatedElem ) {
if ( ! element ) {
return ;
}
element . classList . remove ( CLASS _NAME _ACTIVE ) ;
element . blur ( ) ;
this . _deactivate ( getElementFromSelector ( element ) ) ; // Search and deactivate the shown section too
const complete = ( ) => {
if ( element . getAttribute ( 'role' ) !== 'tab' ) {
2022-07-19 17:43:58 +02:00
element . classList . remove ( CLASS _NAME _SHOW$1 ) ;
2022-05-13 08:07:23 +02:00
return ;
}
element . setAttribute ( 'aria-selected' , false ) ;
element . setAttribute ( 'tabindex' , '-1' ) ;
this . _toggleDropDown ( element , false ) ;
EventHandler . trigger ( element , EVENT _HIDDEN$1 , {
relatedTarget : relatedElem
2018-11-13 07:41:12 +01:00
} ) ;
2018-03-31 22:59:37 +02:00
} ;
2017-05-16 09:59:44 +02:00
2022-07-19 17:43:58 +02:00
this . _queueCallback ( complete , element , element . classList . contains ( CLASS _NAME _FADE$1 ) ) ;
2022-05-13 08:07:23 +02:00
}
_keydown ( event ) {
if ( ! [ ARROW _LEFT _KEY , ARROW _RIGHT _KEY , ARROW _UP _KEY , ARROW _DOWN _KEY ] . includes ( event . key ) ) {
return ;
2018-11-13 07:41:12 +01:00
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
event . stopPropagation ( ) ; // stopPropagation/preventDefault both added to support up/down keys without scrolling the page
event . preventDefault ( ) ;
const isNext = [ ARROW _RIGHT _KEY , ARROW _DOWN _KEY ] . includes ( event . key ) ;
const nextActiveElement = getNextActiveElement ( this . _getChildren ( ) . filter ( element => ! isDisabled ( element ) ) , event . target , isNext , true ) ;
if ( nextActiveElement ) {
Tab . getOrCreateInstance ( nextActiveElement ) . show ( ) ;
}
}
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
_getChildren ( ) {
// collection of inner elements
return SelectorEngine . find ( SELECTOR _INNER _ELEM , this . _parent ) ;
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
_getActiveElem ( ) {
return this . _getChildren ( ) . find ( child => this . _elemIsActive ( child ) ) || null ;
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
_setInitialAttributes ( parent , children ) {
this . _setAttributeIfNotExists ( parent , 'role' , 'tablist' ) ;
2021-05-13 18:22:20 +02:00
2022-05-13 08:07:23 +02:00
for ( const child of children ) {
this . _setInitialAttributesOnChild ( child ) ;
2018-11-13 07:41:12 +01:00
}
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
_setInitialAttributesOnChild ( child ) {
child = this . _getInnerElement ( child ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
const isActive = this . _elemIsActive ( child ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
const outerElem = this . _getOuterElement ( child ) ;
child . setAttribute ( 'aria-selected' , isActive ) ;
if ( outerElem !== child ) {
this . _setAttributeIfNotExists ( outerElem , 'role' , 'presentation' ) ;
2018-11-13 07:41:12 +01:00
}
2017-09-06 06:05:12 +02:00
2022-05-13 08:07:23 +02:00
if ( ! isActive ) {
child . setAttribute ( 'tabindex' , '-1' ) ;
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
this . _setAttributeIfNotExists ( child , 'role' , 'tab' ) ; // set attributes to the related panel too
this . _setInitialAttributesOnTargetPanel ( child ) ;
}
_setInitialAttributesOnTargetPanel ( child ) {
const target = getElementFromSelector ( child ) ;
if ( ! target ) {
return ;
2018-11-13 07:41:12 +01:00
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
this . _setAttributeIfNotExists ( target , 'role' , 'tabpanel' ) ;
2019-02-11 20:15:34 +01:00
2022-05-13 08:07:23 +02:00
if ( child . id ) {
this . _setAttributeIfNotExists ( target , 'aria-labelledby' , ` # ${ child . id } ` ) ;
2019-02-11 20:15:34 +01:00
}
2022-05-13 08:07:23 +02:00
}
2017-09-06 06:05:12 +02:00
2022-05-13 08:07:23 +02:00
_toggleDropDown ( element , open ) {
const outerElem = this . _getOuterElement ( element ) ;
2021-05-05 21:32:12 +02:00
2022-05-13 08:07:23 +02:00
if ( ! outerElem . classList . contains ( CLASS _DROPDOWN ) ) {
return ;
2021-05-05 21:32:12 +02:00
}
2022-05-13 08:07:23 +02:00
const toggle = ( selector , className ) => {
const element = SelectorEngine . findOne ( selector , outerElem ) ;
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
if ( element ) {
element . classList . toggle ( className , open ) ;
2018-11-13 07:41:12 +01:00
}
2022-05-13 08:07:23 +02:00
} ;
2015-08-15 21:19:11 +02:00
2022-05-13 08:07:23 +02:00
toggle ( SELECTOR _DROPDOWN _TOGGLE , CLASS _NAME _ACTIVE ) ;
toggle ( SELECTOR _DROPDOWN _MENU , CLASS _NAME _SHOW$1 ) ;
toggle ( SELECTOR _DROPDOWN _ITEM , CLASS _NAME _ACTIVE ) ;
outerElem . setAttribute ( 'aria-expanded' , open ) ;
}
2017-09-30 23:28:03 +02:00
2022-05-13 08:07:23 +02:00
_setAttributeIfNotExists ( element , attribute , value ) {
if ( ! element . hasAttribute ( attribute ) ) {
element . setAttribute ( attribute , value ) ;
2018-11-13 07:41:12 +01:00
}
2022-05-13 08:07:23 +02:00
}
_elemIsActive ( elem ) {
return elem . classList . contains ( CLASS _NAME _ACTIVE ) ;
} // Try to get the inner element (usually the .nav-link)
_getInnerElement ( elem ) {
return elem . matches ( SELECTOR _INNER _ELEM ) ? elem : SelectorEngine . findOne ( SELECTOR _INNER _ELEM , elem ) ;
} // Try to get the outer element (usually the .nav-item)
_getOuterElement ( elem ) {
return elem . closest ( SELECTOR _OUTER ) || elem ;
2019-01-04 17:29:45 +01:00
} // Static
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2018-11-13 07:41:12 +01:00
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Tab . getOrCreateInstance ( this ) ;
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
if ( typeof config !== 'string' ) {
return ;
}
2018-11-13 07:41:12 +01:00
2022-05-13 08:07:23 +02:00
if ( data [ config ] === undefined || config . startsWith ( '_' ) || config === 'constructor' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2018-11-13 07:41:12 +01:00
}
2022-05-13 08:07:23 +02:00
data [ config ] ( ) ;
2018-11-13 07:41:12 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
/ * *
2022-05-13 08:07:23 +02:00
* Data API implementation
2018-11-13 07:41:12 +01:00
* /
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API , SELECTOR _DATA _TOGGLE , function ( event ) {
2021-05-05 21:32:12 +02:00
if ( [ 'A' , 'AREA' ] . includes ( this . tagName ) ) {
event . preventDefault ( ) ;
}
if ( isDisabled ( this ) ) {
return ;
}
2022-05-13 08:07:23 +02:00
Tab . getOrCreateInstance ( this ) . show ( ) ;
} ) ;
/ * *
* Initialize on focus
* /
EventHandler . on ( window , EVENT _LOAD _DATA _API , ( ) => {
for ( const element of SelectorEngine . find ( SELECTOR _DATA _TOGGLE _ACTIVE ) ) {
Tab . getOrCreateInstance ( element ) ;
}
2018-11-13 07:41:12 +01:00
} ) ;
/ * *
* jQuery
* /
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Tab ) ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : toast . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2015-08-15 21:19:11 +02:00
/ * *
2018-11-24 17:22:59 +01:00
* Constants
2015-08-15 21:19:11 +02:00
* /
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
const NAME = 'toast' ;
const DATA _KEY = 'bs.toast' ;
const EVENT _KEY = ` . ${ DATA _KEY } ` ;
2021-05-13 18:22:20 +02:00
const EVENT _MOUSEOVER = ` mouseover ${ EVENT _KEY } ` ;
const EVENT _MOUSEOUT = ` mouseout ${ EVENT _KEY } ` ;
const EVENT _FOCUSIN = ` focusin ${ EVENT _KEY } ` ;
const EVENT _FOCUSOUT = ` focusout ${ EVENT _KEY } ` ;
2021-03-23 17:26:54 +01:00
const EVENT _HIDE = ` hide ${ EVENT _KEY } ` ;
const EVENT _HIDDEN = ` hidden ${ EVENT _KEY } ` ;
const EVENT _SHOW = ` show ${ EVENT _KEY } ` ;
const EVENT _SHOWN = ` shown ${ EVENT _KEY } ` ;
const CLASS _NAME _FADE = 'fade' ;
2021-08-04 17:41:51 +02:00
const CLASS _NAME _HIDE = 'hide' ; // @deprecated - kept here only for backwards compatibility
2021-03-23 17:26:54 +01:00
const CLASS _NAME _SHOW = 'show' ;
const CLASS _NAME _SHOWING = 'showing' ;
const DefaultType = {
2018-11-24 17:22:59 +01:00
animation : 'boolean' ,
autohide : 'boolean' ,
delay : 'number'
} ;
2021-03-23 17:26:54 +01:00
const Default = {
2018-11-24 17:22:59 +01:00
animation : true ,
autohide : true ,
2020-09-14 17:12:06 +02:00
delay : 5000
2018-11-24 17:22:59 +01:00
} ;
2019-10-08 08:39:10 +02:00
/ * *
2022-05-13 08:07:23 +02:00
* Class definition
2019-10-08 08:39:10 +02:00
* /
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
class Toast extends BaseComponent {
constructor ( element , config ) {
2022-05-13 08:07:23 +02:00
super ( element , config ) ;
2021-03-23 17:26:54 +01:00
this . _timeout = null ;
2021-05-13 18:22:20 +02:00
this . _hasMouseInteraction = false ;
this . _hasKeyboardInteraction = false ;
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
this . _setListeners ( ) ;
} // Getters
2019-03-01 17:31:34 +01:00
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
static get Default ( ) {
return Default ;
}
2017-05-16 09:59:44 +02:00
2022-05-13 08:07:23 +02:00
static get DefaultType ( ) {
return DefaultType ;
}
2021-05-13 18:22:20 +02:00
static get NAME ( ) {
return NAME ;
2021-03-23 17:26:54 +01:00
} // Public
2018-11-13 07:41:12 +01:00
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
show ( ) {
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW ) ;
2019-07-12 23:56:26 +02:00
if ( showEvent . defaultPrevented ) {
return ;
}
2015-08-15 21:19:11 +02:00
2020-09-14 17:12:06 +02:00
this . _clearTimeout ( ) ;
2018-11-24 17:22:59 +01:00
if ( this . _config . animation ) {
2021-03-23 17:26:54 +01:00
this . _element . classList . add ( CLASS _NAME _FADE ) ;
2018-11-24 17:22:59 +01:00
}
2017-09-06 06:05:12 +02:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
this . _element . classList . remove ( CLASS _NAME _SHOWING ) ;
2018-12-16 00:13:22 +01:00
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , EVENT _SHOWN ) ;
2017-09-06 06:05:12 +02:00
2021-05-13 18:22:20 +02:00
this . _maybeScheduleHide ( ) ;
2018-11-13 07:41:12 +01:00
} ;
2017-09-06 06:05:12 +02:00
2021-08-04 17:41:51 +02:00
this . _element . classList . remove ( CLASS _NAME _HIDE ) ; // @deprecated
2018-12-16 00:13:22 +01:00
2019-07-24 08:13:50 +02:00
reflow ( this . _element ) ;
2022-05-13 08:07:23 +02:00
this . _element . classList . add ( CLASS _NAME _SHOW , CLASS _NAME _SHOWING ) ;
2017-09-06 06:05:12 +02:00
2021-05-13 18:22:20 +02:00
this . _queueCallback ( complete , this . _element , this . _config . animation ) ;
2021-03-23 17:26:54 +01:00
}
2018-03-31 22:59:37 +02:00
2021-03-23 17:26:54 +01:00
hide ( ) {
2022-05-13 08:07:23 +02:00
if ( ! this . isShown ( ) ) {
2018-11-24 17:22:59 +01:00
return ;
}
2017-09-06 06:05:12 +02:00
2021-03-23 17:26:54 +01:00
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE ) ;
2019-07-12 23:56:26 +02:00
if ( hideEvent . defaultPrevented ) {
return ;
}
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
2021-08-04 17:41:51 +02:00
this . _element . classList . add ( CLASS _NAME _HIDE ) ; // @deprecated
2022-05-13 08:07:23 +02:00
this . _element . classList . remove ( CLASS _NAME _SHOWING , CLASS _NAME _SHOW ) ;
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , EVENT _HIDDEN ) ;
2019-04-18 13:47:52 +02:00
} ;
2021-08-04 17:41:51 +02:00
this . _element . classList . add ( CLASS _NAME _SHOWING ) ;
2019-04-18 13:47:52 +02:00
2021-05-13 18:22:20 +02:00
this . _queueCallback ( complete , this . _element , this . _config . animation ) ;
2021-03-23 17:26:54 +01:00
}
2018-11-13 07:41:12 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2020-09-14 17:12:06 +02:00
this . _clearTimeout ( ) ;
2017-09-06 06:05:12 +02:00
2022-05-13 08:07:23 +02:00
if ( this . isShown ( ) ) {
2021-03-23 17:26:54 +01:00
this . _element . classList . remove ( CLASS _NAME _SHOW ) ;
2018-11-24 17:22:59 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
super . dispose ( ) ;
2022-05-13 08:07:23 +02:00
}
2017-09-06 06:05:12 +02:00
2022-05-13 08:07:23 +02:00
isShown ( ) {
return this . _element . classList . contains ( CLASS _NAME _SHOW ) ;
} // Private
2017-09-30 23:28:03 +02:00
2017-09-06 06:05:12 +02:00
2021-05-13 18:22:20 +02:00
_maybeScheduleHide ( ) {
if ( ! this . _config . autohide ) {
return ;
}
if ( this . _hasMouseInteraction || this . _hasKeyboardInteraction ) {
return ;
}
this . _timeout = setTimeout ( ( ) => {
this . hide ( ) ;
} , this . _config . delay ) ;
}
_onInteraction ( event , isInteracting ) {
switch ( event . type ) {
case 'mouseover' :
case 'mouseout' :
this . _hasMouseInteraction = isInteracting ;
break ;
case 'focusin' :
case 'focusout' :
this . _hasKeyboardInteraction = isInteracting ;
break ;
}
if ( isInteracting ) {
this . _clearTimeout ( ) ;
return ;
}
const nextElement = event . relatedTarget ;
if ( this . _element === nextElement || this . _element . contains ( nextElement ) ) {
return ;
}
this . _maybeScheduleHide ( ) ;
}
2021-03-23 17:26:54 +01:00
_setListeners ( ) {
2021-05-13 18:22:20 +02:00
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 _FOCUSIN , event => this . _onInteraction ( event , true ) ) ;
EventHandler . on ( this . _element , EVENT _FOCUSOUT , event => this . _onInteraction ( event , false ) ) ;
2021-03-23 17:26:54 +01:00
}
2020-09-14 17:12:06 +02:00
2021-03-23 17:26:54 +01:00
_clearTimeout ( ) {
2020-09-14 17:12:06 +02:00
clearTimeout ( this . _timeout ) ;
this . _timeout = null ;
2019-01-04 17:29:45 +01:00
} // Static
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2018-11-24 17:22:59 +01:00
return this . each ( function ( ) {
2021-06-22 20:29:16 +02:00
const data = Toast . getOrCreateInstance ( this , config ) ;
2015-08-15 21:19:11 +02:00
2018-11-24 17:22:59 +01:00
if ( typeof config === 'string' ) {
if ( typeof data [ config ] === 'undefined' ) {
2021-03-23 17:26:54 +01:00
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2015-06-19 00:48:54 +02:00
}
2017-09-30 23:28:03 +02:00
2018-11-24 17:22:59 +01:00
data [ config ] ( this ) ;
2018-11-13 07:41:12 +01:00
}
2018-11-24 17:22:59 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2015-08-15 21:19:11 +02:00
2021-03-23 17:26:54 +01:00
}
2022-05-13 08:07:23 +02:00
/ * *
* Data API implementation
* /
2021-08-04 17:41:51 +02:00
enableDismissTrigger ( Toast ) ;
2018-11-24 17:22:59 +01:00
/ * *
* jQuery
* /
2018-11-13 07:41:12 +01:00
2021-05-13 18:22:20 +02:00
defineJQueryPlugin ( Toast ) ;
2016-10-10 02:26:51 +02:00
2018-03-31 22:59:37 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-07-19 17:43:58 +02:00
* Bootstrap ( v5 . 2.0 ) : index . umd . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2018-03-31 22:59:37 +02:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-10-05 17:50:18 +02:00
const index _umd = {
2021-03-23 17:26:54 +01:00
Alert ,
Button ,
Carousel ,
Collapse ,
Dropdown ,
Modal ,
Offcanvas ,
Popover ,
ScrollSpy ,
Tab ,
Toast ,
Tooltip
2019-03-11 16:13:30 +01:00
} ;
2017-09-06 06:05:12 +02:00
2019-03-11 16:13:30 +01:00
return index _umd ;
2017-09-06 06:05:12 +02:00
2021-10-05 17:50:18 +02:00
} ) ) ;
2017-10-19 09:17:08 +02:00
//# sourceMappingURL=bootstrap.js.map