2019-03-11 16:13:30 +01:00
/ * !
2021-05-05 21:32:12 +02:00
* Bootstrap v5 . 0.0 ( https : //getbootstrap.com/)
2021-02-10 17:14:51 +01:00
* Copyright 2011 - 2021 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)
2019-03-11 16:13:30 +01:00
* /
2020-12-07 16:50:24 +01:00
import * as Popper from '@popperjs/core' ;
2019-04-18 13:47:52 +02:00
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : util / index . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2019-03-11 16:13:30 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const MAX _UID = 1000000 ;
const MILLISECONDS _MULTIPLIER = 1000 ;
const TRANSITION _END = 'transitionend' ; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
const toType = obj => {
2020-03-28 11:29:08 +01:00
if ( obj === null || obj === undefined ) {
2021-03-23 17:26:54 +01:00
return ` ${ obj } ` ;
2020-03-28 11:29:08 +01:00
}
2019-04-18 13:47:52 +02:00
return { } . toString . call ( obj ) . match ( /\s([a-z]+)/i ) [ 1 ] . toLowerCase ( ) ;
} ;
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Public Util Api
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const getUID = prefix => {
2019-03-11 16:13:30 +01:00
do {
2020-06-14 00:40:28 +02:00
prefix += Math . floor ( Math . random ( ) * MAX _UID ) ;
2019-03-11 16:13:30 +01:00
} while ( document . getElementById ( prefix ) ) ;
return prefix ;
} ;
2021-03-23 17:26:54 +01:00
const getSelector = element => {
let selector = element . getAttribute ( 'data-bs-target' ) ;
2019-03-11 16:13:30 +01:00
if ( ! selector || selector === '#' ) {
2021-03-23 17:26:54 +01:00
let hrefAttr = 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
if ( ! hrefAttr || ! hrefAttr . includes ( '#' ) && ! hrefAttr . startsWith ( '.' ) ) {
return null ;
} // Just in case some CMS puts out a full URL with the anchor appended
if ( hrefAttr . includes ( '#' ) && ! hrefAttr . startsWith ( '#' ) ) {
2021-05-05 21:32:12 +02:00
hrefAttr = ` # ${ hrefAttr . split ( '#' ) [ 1 ] } ` ;
2021-02-10 17:14:51 +01:00
}
2019-08-27 15:03:21 +02:00
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr . trim ( ) : null ;
2019-03-11 16:13:30 +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-11 16:13:30 +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-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const getTransitionDurationFromElement = element => {
2019-03-11 16:13:30 +01:00
if ( ! element ) {
return 0 ;
} // Get transition-duration of the element
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-11 16:13:30 +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-11 16:13:30 +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-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const isElement = obj => ( obj [ 0 ] || obj ) . nodeType ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const emulateTransitionEnd = ( element , duration ) => {
let called = false ;
const durationPadding = 5 ;
const emulatedDuration = duration + durationPadding ;
2019-03-11 16:13:30 +01:00
function listener ( ) {
called = true ;
element . removeEventListener ( TRANSITION _END , listener ) ;
}
element . addEventListener ( TRANSITION _END , listener ) ;
2021-03-23 17:26:54 +01:00
setTimeout ( ( ) => {
2019-03-11 16:13:30 +01:00
if ( ! called ) {
triggerTransitionEnd ( element ) ;
}
} , emulatedDuration ) ;
} ;
2021-03-23 17:26:54 +01:00
const typeCheckConfig = ( componentName , config , configTypes ) => {
Object . keys ( configTypes ) . forEach ( property => {
const expectedTypes = configTypes [ property ] ;
const value = config [ property ] ;
const valueType = value && isElement ( value ) ? 'element' : toType ( value ) ;
2019-03-11 16:13:30 +01:00
if ( ! new RegExp ( expectedTypes ) . test ( valueType ) ) {
2021-05-05 21:32:12 +02:00
throw new TypeError ( ` ${ componentName . toUpperCase ( ) } : Option " ${ property } " provided type " ${ valueType } " but expected type " ${ expectedTypes } ". ` ) ;
2019-03-11 16:13:30 +01:00
}
} ) ;
} ;
2021-03-23 17:26:54 +01:00
const isVisible = element => {
2019-03-11 16:13:30 +01:00
if ( ! element ) {
return false ;
}
if ( element . style && element . parentNode && element . parentNode . style ) {
2021-03-23 17:26:54 +01:00
const elementStyle = getComputedStyle ( element ) ;
const parentNodeStyle = getComputedStyle ( element . parentNode ) ;
2019-11-08 09:11:23 +01:00
return elementStyle . display !== 'none' && parentNodeStyle . display !== 'none' && elementStyle . visibility !== 'hidden' ;
2019-03-11 16:13:30 +01:00
}
return false ;
} ;
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-11 16:13:30 +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-11 16:13:30 +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-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
const noop = ( ) => { } ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const reflow = element => element . offsetHeight ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const getjQuery = ( ) => {
const {
jQuery
} = window ;
2019-08-27 15:03:21 +02:00
2020-11-23 14:17:16 +01:00
if ( jQuery && ! document . body . hasAttribute ( 'data-bs-no-jquery' ) ) {
2019-08-27 15:03:21 +02:00
return jQuery ;
}
return null ;
} ;
2021-03-23 17:26:54 +01:00
const onDOMContentLoaded = callback => {
2020-11-11 18:07:37 +01:00
if ( document . readyState === 'loading' ) {
document . addEventListener ( 'DOMContentLoaded' , callback ) ;
} 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-03-23 17:26:54 +01:00
const defineJQueryPlugin = ( name , plugin ) => {
onDOMContentLoaded ( ( ) => {
const $ = getjQuery ( ) ;
2021-02-10 17:14:51 +01:00
/* istanbul ignore if */
if ( $ ) {
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 ( ) ;
}
} ;
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : dom / data . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2019-03-11 16:13:30 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const elementMap = new Map ( ) ;
var Data = {
set ( element , key , instance ) {
if ( ! elementMap . has ( element ) ) {
elementMap . set ( element , new Map ( ) ) ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
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
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01: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 ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
instanceMap . set ( key , instance ) ;
} ,
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
get ( element , key ) {
if ( elementMap . has ( element ) ) {
return elementMap . get ( element ) . get ( key ) || null ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
return null ;
} ,
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
remove ( element , key ) {
if ( ! elementMap . has ( element ) ) {
return ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
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 ) ;
}
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
2019-04-18 13:47:52 +02:00
} ;
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.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-11 16:13:30 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const namespaceRegex = /[^.]*(?=\..*)\.|.*/ ;
const stripNameRegex = /\..*/ ;
const stripUidRegex = /::\d+$/ ;
const eventRegistry = { } ; // Events storage
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
let uidEvent = 1 ;
const customEvents = {
2019-03-11 16:13:30 +01:00
mouseenter : 'mouseover' ,
mouseleave : 'mouseout'
} ;
2021-05-05 21:32:12 +02:00
const customEventsRegex = /^(mouseenter|mouseleave)/i ;
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-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Private methods
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
function getUidEvent ( element , uid ) {
2021-03-23 17:26:54 +01:00
return uid && ` ${ uid } :: ${ uidEvent ++ } ` || element . uidEvent || uidEvent ++ ;
2019-03-11 16:13:30 +01:00
}
function getEvent ( element ) {
2021-03-23 17:26:54 +01:00
const uid = getUidEvent ( element ) ;
2019-03-11 16:13:30 +01:00
element . uidEvent = uid ;
eventRegistry [ uid ] = eventRegistry [ uid ] || { } ;
return eventRegistry [ uid ] ;
}
function bootstrapHandler ( element , fn ) {
return function handler ( event ) {
2020-09-14 17:12:06 +02:00
event . delegateTarget = element ;
2019-03-11 16:13:30 +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-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
for ( let {
target
} = event ; target && target !== this ; target = target . parentNode ) {
for ( let i = domElements . length ; i -- ; ) {
2019-03-11 16:13:30 +01:00
if ( domElements [ i ] === target ) {
2020-09-14 17:12:06 +02:00
event . delegateTarget = target ;
2019-03-11 16:13:30 +01:00
if ( handler . oneOff ) {
2021-02-10 17:14:51 +01:00
// eslint-disable-next-line unicorn/consistent-destructuring
2021-05-05 21:32:12 +02:00
EventHandler . off ( element , event . type , selector , fn ) ;
2019-03-11 16:13:30 +01:00
}
return fn . apply ( target , [ event ] ) ;
}
}
} // To please ESLint
return null ;
} ;
}
2021-03-23 17:26:54 +01:00
function findHandler ( events , handler , delegationSelector = null ) {
const uidEventList = Object . keys ( events ) ;
2019-07-12 23:56:26 +02:00
2021-03-23 17:26:54 +01:00
for ( let i = 0 , len = uidEventList . length ; i < len ; i ++ ) {
const event = events [ uidEventList [ i ] ] ;
2019-03-11 16:13:30 +01:00
if ( event . originalHandler === handler && event . delegationSelector === delegationSelector ) {
2019-07-12 23:56:26 +02:00
return event ;
2019-03-11 16:13:30 +01:00
}
}
return null ;
}
function normalizeParams ( originalTypeEvent , handler , delegationFn ) {
2021-03-23 17:26:54 +01:00
const delegation = typeof handler === 'string' ;
2021-05-05 21:32:12 +02:00
const originalHandler = delegation ? delegationFn : handler ;
let typeEvent = getTypeEvent ( originalTypeEvent ) ;
2021-03-23 17:26:54 +01:00
const isNative = nativeEvents . has ( typeEvent ) ;
2019-03-11 16:13:30 +01:00
if ( ! isNative ) {
typeEvent = originalTypeEvent ;
}
return [ delegation , originalHandler , typeEvent ] ;
}
function addHandler ( element , originalTypeEvent , handler , delegationFn , oneOff ) {
if ( typeof originalTypeEvent !== 'string' || ! element ) {
return ;
}
if ( ! handler ) {
handler = delegationFn ;
delegationFn = null ;
2021-05-05 21:32:12 +02:00
} // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position
// this prevents the handler from being dispatched the same way as mouseover or mouseout does
if ( customEventsRegex . test ( originalTypeEvent ) ) {
const wrapFn = fn => {
return function ( event ) {
if ( ! event . relatedTarget || event . relatedTarget !== event . delegateTarget && ! event . delegateTarget . contains ( event . relatedTarget ) ) {
return fn . call ( this , event ) ;
}
} ;
} ;
if ( delegationFn ) {
delegationFn = wrapFn ( delegationFn ) ;
} else {
handler = wrapFn ( handler ) ;
}
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
const [ delegation , originalHandler , typeEvent ] = normalizeParams ( originalTypeEvent , handler , delegationFn ) ;
const events = getEvent ( element ) ;
const handlers = events [ typeEvent ] || ( events [ typeEvent ] = { } ) ;
const previousFn = findHandler ( handlers , originalHandler , delegation ? handler : null ) ;
2019-03-11 16:13:30 +01:00
if ( previousFn ) {
previousFn . oneOff = previousFn . oneOff && oneOff ;
return ;
}
2021-03-23 17:26:54 +01:00
const uid = getUidEvent ( originalHandler , originalTypeEvent . replace ( namespaceRegex , '' ) ) ;
const fn = delegation ? bootstrapDelegationHandler ( element , handler , delegationFn ) : bootstrapHandler ( element , handler ) ;
2019-03-11 16:13:30 +01:00
fn . delegationSelector = delegation ? handler : null ;
fn . originalHandler = originalHandler ;
fn . oneOff = oneOff ;
fn . uidEvent = uid ;
handlers [ uid ] = fn ;
element . addEventListener ( typeEvent , fn , delegation ) ;
}
function removeHandler ( element , events , typeEvent , handler , delegationSelector ) {
2021-03-23 17:26:54 +01:00
const fn = findHandler ( events [ typeEvent ] , handler , delegationSelector ) ;
2019-03-11 16:13:30 +01:00
2019-07-12 23:56:26 +02:00
if ( ! fn ) {
2019-03-11 16:13:30 +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 ] || { } ;
Object . keys ( storeElementEvent ) . forEach ( handlerKey => {
2020-11-23 14:17:16 +01:00
if ( handlerKey . includes ( namespace ) ) {
2021-03-23 17:26:54 +01:00
const event = storeElementEvent [ handlerKey ] ;
2019-03-11 16:13:30 +01:00
removeHandler ( element , events , typeEvent , event . originalHandler , event . delegationSelector ) ;
}
} ) ;
}
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 = {
on ( element , event , handler , delegationFn ) {
2019-03-11 16:13:30 +01:00
addHandler ( element , event , handler , delegationFn , false ) ;
} ,
2021-03-23 17:26:54 +01:00
one ( element , event , handler , delegationFn ) {
2019-03-11 16:13:30 +01:00
addHandler ( element , event , handler , delegationFn , true ) ;
} ,
2021-03-23 17:26:54 +01:00
off ( element , originalTypeEvent , handler , delegationFn ) {
2019-03-11 16:13:30 +01:00
if ( typeof originalTypeEvent !== 'string' || ! element ) {
return ;
}
2021-03-23 17:26:54 +01:00
const [ delegation , originalHandler , typeEvent ] = normalizeParams ( originalTypeEvent , handler , delegationFn ) ;
const inNamespace = typeEvent !== originalTypeEvent ;
const events = getEvent ( element ) ;
const isNamespace = originalTypeEvent . startsWith ( '.' ) ;
2019-03-11 16:13:30 +01:00
if ( typeof originalHandler !== 'undefined' ) {
// Simplest case: handler is passed, remove that listener ONLY.
if ( ! events || ! events [ typeEvent ] ) {
return ;
}
removeHandler ( element , events , typeEvent , originalHandler , delegation ? handler : null ) ;
return ;
}
if ( isNamespace ) {
2021-03-23 17:26:54 +01:00
Object . keys ( events ) . forEach ( elementEvent => {
2019-10-08 08:39:10 +02:00
removeNamespacedHandlers ( element , events , elementEvent , originalTypeEvent . slice ( 1 ) ) ;
2019-03-11 16:13:30 +01:00
} ) ;
}
2021-03-23 17:26:54 +01:00
const storeElementEvent = events [ typeEvent ] || { } ;
Object . keys ( storeElementEvent ) . forEach ( keyHandlers => {
const handlerKey = keyHandlers . replace ( stripUidRegex , '' ) ;
2019-03-11 16:13:30 +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 ] ;
2019-03-11 16:13:30 +01:00
removeHandler ( element , events , typeEvent , event . originalHandler , event . delegationSelector ) ;
}
} ) ;
} ,
2021-03-23 17:26:54 +01:00
trigger ( element , event , args ) {
2019-03-11 16:13:30 +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 ;
const isNative = nativeEvents . has ( typeEvent ) ;
let jQueryEvent ;
let bubbles = true ;
let nativeDispatch = true ;
let defaultPrevented = false ;
let evt = null ;
2019-03-11 16:13:30 +01:00
2019-08-27 15:03:21 +02:00
if ( inNamespace && $ ) {
jQueryEvent = $ . Event ( event , args ) ;
$ ( element ) . trigger ( jQueryEvent ) ;
2019-03-11 16:13:30 +01:00
bubbles = ! jQueryEvent . isPropagationStopped ( ) ;
nativeDispatch = ! jQueryEvent . isImmediatePropagationStopped ( ) ;
defaultPrevented = jQueryEvent . isDefaultPrevented ( ) ;
}
if ( isNative ) {
evt = document . createEvent ( 'HTMLEvents' ) ;
evt . initEvent ( typeEvent , bubbles , true ) ;
} else {
2020-03-28 11:29:08 +01:00
evt = new CustomEvent ( event , {
2021-03-23 17:26:54 +01:00
bubbles ,
2019-03-11 16:13:30 +01:00
cancelable : true
} ) ;
2020-09-14 17:12:06 +02:00
} // merge custom information in our event
2019-03-11 16:13:30 +01:00
if ( typeof args !== 'undefined' ) {
2021-03-23 17:26:54 +01:00
Object . keys ( args ) . forEach ( key => {
2019-03-11 16:13:30 +01:00
Object . defineProperty ( evt , key , {
2021-03-23 17:26:54 +01:00
get ( ) {
2019-03-11 16:13:30 +01:00
return args [ key ] ;
}
2021-03-23 17:26:54 +01:00
2019-03-11 16:13:30 +01:00
} ) ;
} ) ;
}
if ( defaultPrevented ) {
evt . preventDefault ( ) ;
}
if ( nativeDispatch ) {
element . dispatchEvent ( evt ) ;
}
if ( evt . defaultPrevented && typeof jQueryEvent !== 'undefined' ) {
jQueryEvent . preventDefault ( ) ;
}
return evt ;
}
2021-03-23 17:26:54 +01:00
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : base - component . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-05-05 21:32:12 +02:00
const VERSION = '5.0.0' ;
2021-03-23 17:26:54 +01:00
class BaseComponent {
constructor ( element ) {
element = typeof element === 'string' ? document . querySelector ( element ) : element ;
2020-12-03 15:18:59 +01:00
if ( ! element ) {
return ;
}
this . _element = element ;
2021-03-23 17:26:54 +01:00
Data . set ( this . _element , this . constructor . DATA _KEY , this ) ;
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-05 21:32:12 +02:00
EventHandler . off ( this . _element , ` . ${ this . constructor . DATA _KEY } ` ) ;
2020-12-03 15:18:59 +01:00
this . _element = null ;
}
/** Static */
2021-03-23 17:26:54 +01:00
static getInstance ( element ) {
return Data . get ( element , this . DATA _KEY ) ;
}
static get VERSION ( ) {
return VERSION ;
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.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
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-05-05 21:32:12 +02:00
const NAME$c = 'alert' ;
2021-03-23 17:26:54 +01:00
const DATA _KEY$b = 'bs.alert' ;
const EVENT _KEY$b = ` . ${ DATA _KEY$b } ` ;
const DATA _API _KEY$8 = '.data-api' ;
const SELECTOR _DISMISS = '[data-bs-dismiss="alert"]' ;
const EVENT _CLOSE = ` close ${ EVENT _KEY$b } ` ;
const EVENT _CLOSED = ` closed ${ EVENT _KEY$b } ` ;
const EVENT _CLICK _DATA _API$7 = ` click ${ EVENT _KEY$b } ${ DATA _API _KEY$8 } ` ;
const CLASS _NAME _ALERT = 'alert' ;
2021-05-05 21:32:12 +02:00
const CLASS _NAME _FADE$6 = 'fade' ;
const CLASS _NAME _SHOW$9 = 'show' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Alert extends BaseComponent {
// Getters
static get DATA _KEY ( ) {
return DATA _KEY$b ;
} // Public
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
close ( element ) {
const rootElement = element ? this . _getRootElement ( element ) : this . _element ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const customEvent = this . _triggerCloseEvent ( rootElement ) ;
2019-03-11 16:13:30 +01:00
if ( customEvent === null || customEvent . defaultPrevented ) {
return ;
}
this . _removeElement ( rootElement ) ;
} // Private
2021-03-23 17:26:54 +01:00
_getRootElement ( element ) {
return getElementFromSelector ( element ) || element . closest ( ` . ${ CLASS _NAME _ALERT } ` ) ;
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
_triggerCloseEvent ( element ) {
return EventHandler . trigger ( element , EVENT _CLOSE ) ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_removeElement ( element ) {
2021-05-05 21:32:12 +02:00
element . classList . remove ( CLASS _NAME _SHOW$9 ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
if ( ! element . classList . contains ( CLASS _NAME _FADE$6 ) ) {
2019-03-11 16:13:30 +01:00
this . _destroyElement ( element ) ;
return ;
}
2021-03-23 17:26:54 +01:00
const transitionDuration = getTransitionDurationFromElement ( element ) ;
EventHandler . one ( element , 'transitionend' , ( ) => this . _destroyElement ( element ) ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( element , transitionDuration ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_destroyElement ( element ) {
2019-03-11 16:13:30 +01:00
if ( element . parentNode ) {
element . parentNode . removeChild ( element ) ;
}
2020-03-28 11:29:08 +01:00
EventHandler . trigger ( element , EVENT _CLOSED ) ;
2019-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2021-03-23 17:26:54 +01:00
let data = Data . get ( this , DATA _KEY$b ) ;
2019-03-11 16:13:30 +01:00
if ( ! data ) {
data = new Alert ( this ) ;
}
if ( config === 'close' ) {
data [ config ] ( this ) ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static handleDismiss ( alertInstance ) {
2019-03-11 16:13:30 +01:00
return function ( event ) {
if ( event ) {
event . preventDefault ( ) ;
}
alertInstance . close ( this ) ;
} ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$7 , SELECTOR _DISMISS , Alert . handleDismiss ( new Alert ( ) ) ) ;
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Alert to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2021-05-05 21:32:12 +02:00
defineJQueryPlugin ( NAME$c , Alert ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : button . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-05-05 21:32:12 +02:00
const NAME$b = 'button' ;
2021-03-23 17:26:54 +01:00
const DATA _KEY$a = 'bs.button' ;
const EVENT _KEY$a = ` . ${ DATA _KEY$a } ` ;
const DATA _API _KEY$7 = '.data-api' ;
const CLASS _NAME _ACTIVE$3 = 'active' ;
const SELECTOR _DATA _TOGGLE$5 = '[data-bs-toggle="button"]' ;
const EVENT _CLICK _DATA _API$6 = ` click ${ EVENT _KEY$a } ${ DATA _API _KEY$7 } ` ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Button extends BaseComponent {
// Getters
static get DATA _KEY ( ) {
return DATA _KEY$a ;
} // Public
2019-03-11 16:13:30 +01: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-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2021-03-23 17:26:54 +01:00
let data = Data . get ( this , DATA _KEY$a ) ;
2019-03-11 16:13:30 +01:00
if ( ! data ) {
data = new Button ( this ) ;
}
if ( config === 'toggle' ) {
data [ config ] ( ) ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$6 , SELECTOR _DATA _TOGGLE$5 , event => {
2019-03-11 16:13:30 +01:00
event . preventDefault ( ) ;
2021-03-23 17:26:54 +01:00
const button = event . target . closest ( SELECTOR _DATA _TOGGLE$5 ) ;
let data = Data . get ( button , DATA _KEY$a ) ;
2019-03-11 16:13:30 +01:00
if ( ! data ) {
data = new Button ( button ) ;
}
data . toggle ( ) ;
} ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Button to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2021-05-05 21:32:12 +02:00
defineJQueryPlugin ( NAME$b , Button ) ;
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : dom / manipulator . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2019-03-11 16:13:30 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
function normalizeData ( val ) {
if ( val === 'true' ) {
return true ;
}
if ( val === 'false' ) {
return false ;
}
if ( val === Number ( val ) . toString ( ) ) {
return Number ( val ) ;
}
if ( val === '' || val === 'null' ) {
return null ;
}
return val ;
}
function normalizeDataKey ( key ) {
2021-03-23 17:26:54 +01:00
return key . replace ( /[A-Z]/g , chr => ` - ${ chr . toLowerCase ( ) } ` ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
const Manipulator = {
setDataAttribute ( element , key , value ) {
element . setAttribute ( ` data-bs- ${ normalizeDataKey ( key ) } ` , value ) ;
2019-03-11 16:13:30 +01:00
} ,
2021-03-23 17:26:54 +01:00
removeDataAttribute ( element , key ) {
element . removeAttribute ( ` data-bs- ${ normalizeDataKey ( key ) } ` ) ;
2019-03-11 16:13:30 +01:00
} ,
2021-03-23 17:26:54 +01:00
getDataAttributes ( element ) {
2019-03-11 16:13:30 +01:00
if ( ! element ) {
return { } ;
}
2021-03-23 17:26:54 +01:00
const attributes = { } ;
Object . keys ( element . dataset ) . filter ( key => key . startsWith ( 'bs' ) ) . forEach ( key => {
let pureKey = key . replace ( /^bs/ , '' ) ;
2020-11-23 14:17:16 +01:00
pureKey = pureKey . charAt ( 0 ) . toLowerCase ( ) + pureKey . slice ( 1 , pureKey . length ) ;
attributes [ pureKey ] = normalizeData ( element . dataset [ key ] ) ;
2019-03-11 16:13:30 +01:00
} ) ;
return attributes ;
} ,
2021-03-23 17:26:54 +01:00
getDataAttribute ( element , key ) {
return normalizeData ( element . getAttribute ( ` data-bs- ${ normalizeDataKey ( key ) } ` ) ) ;
2019-03-11 16:13:30 +01:00
} ,
2021-03-23 17:26:54 +01:00
offset ( element ) {
const rect = element . getBoundingClientRect ( ) ;
2019-03-11 16:13:30 +01:00
return {
top : rect . top + document . body . scrollTop ,
left : rect . left + document . body . scrollLeft
} ;
} ,
2021-03-23 17:26:54 +01:00
position ( element ) {
2019-03-11 16:13:30 +01:00
return {
top : element . offsetTop ,
left : element . offsetLeft
} ;
}
2021-03-23 17:26:54 +01:00
2019-03-11 16:13:30 +01:00
} ;
2020-06-16 20:50:01 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : dom / selector - engine . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2020-11-11 18:07:37 +01:00
2020-06-16 20:50:01 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const NODE _TEXT = 3 ;
const SelectorEngine = {
find ( selector , element = document . documentElement ) {
return [ ] . concat ( ... Element . prototype . querySelectorAll . call ( element , selector ) ) ;
2020-06-16 20:50:01 +02:00
} ,
2021-03-23 17:26:54 +01:00
findOne ( selector , element = document . documentElement ) {
2020-11-11 18:07:37 +01:00
return Element . prototype . querySelector . call ( element , selector ) ;
2020-06-16 20:50:01 +02:00
} ,
2021-03-23 17:26:54 +01:00
children ( element , selector ) {
return [ ] . concat ( ... element . children ) . filter ( child => child . matches ( selector ) ) ;
2020-06-16 20:50:01 +02:00
} ,
2021-03-23 17:26:54 +01:00
parents ( element , selector ) {
const parents = [ ] ;
let ancestor = element . parentNode ;
2020-06-16 20:50:01 +02:00
while ( ancestor && ancestor . nodeType === Node . ELEMENT _NODE && ancestor . nodeType !== NODE _TEXT ) {
2021-02-10 17:14:51 +01:00
if ( ancestor . matches ( selector ) ) {
2020-06-16 20:50:01 +02:00
parents . push ( ancestor ) ;
}
ancestor = ancestor . parentNode ;
}
return parents ;
} ,
2021-03-23 17:26:54 +01:00
prev ( element , selector ) {
let previous = element . previousElementSibling ;
2020-06-16 20:50:01 +02:00
while ( previous ) {
if ( previous . matches ( selector ) ) {
return [ previous ] ;
}
previous = previous . previousElementSibling ;
}
return [ ] ;
} ,
2021-03-23 17:26:54 +01:00
next ( element , selector ) {
let next = element . nextElementSibling ;
2020-06-16 20:50:01 +02:00
while ( next ) {
2021-02-10 17:14:51 +01:00
if ( next . matches ( selector ) ) {
2020-06-16 20:50:01 +02:00
return [ next ] ;
}
next = next . nextElementSibling ;
}
return [ ] ;
}
2021-03-23 17:26:54 +01:00
2020-06-16 20:50:01 +02:00
} ;
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : carousel . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-05-05 21:32:12 +02:00
const NAME$a = 'carousel' ;
2021-03-23 17:26:54 +01:00
const DATA _KEY$9 = 'bs.carousel' ;
const EVENT _KEY$9 = ` . ${ DATA _KEY$9 } ` ;
const DATA _API _KEY$6 = '.data-api' ;
const ARROW _LEFT _KEY = 'ArrowLeft' ;
const ARROW _RIGHT _KEY = 'ArrowRight' ;
const TOUCHEVENT _COMPAT _WAIT = 500 ; // Time for mouse compat events to fire after touch
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const SWIPE _THRESHOLD = 40 ;
2021-05-05 21:32:12 +02:00
const Default$9 = {
2019-03-11 16:13:30 +01:00
interval : 5000 ,
keyboard : true ,
slide : false ,
pause : 'hover' ,
wrap : true ,
touch : true
} ;
2021-05-05 21:32:12 +02:00
const DefaultType$9 = {
2019-03-11 16:13:30 +01:00
interval : '(number|boolean)' ,
keyboard : 'boolean' ,
slide : '(boolean|string)' ,
pause : '(string|boolean)' ,
wrap : 'boolean' ,
touch : 'boolean'
} ;
2021-03-23 17:26:54 +01:00
const ORDER _NEXT = 'next' ;
const ORDER _PREV = 'prev' ;
const DIRECTION _LEFT = 'left' ;
const DIRECTION _RIGHT = 'right' ;
const EVENT _SLIDE = ` slide ${ EVENT _KEY$9 } ` ;
const EVENT _SLID = ` slid ${ EVENT _KEY$9 } ` ;
const EVENT _KEYDOWN = ` keydown ${ EVENT _KEY$9 } ` ;
const EVENT _MOUSEENTER = ` mouseenter ${ EVENT _KEY$9 } ` ;
const EVENT _MOUSELEAVE = ` mouseleave ${ EVENT _KEY$9 } ` ;
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 EVENT _DRAG _START = ` dragstart ${ EVENT _KEY$9 } ` ;
const EVENT _LOAD _DATA _API$2 = ` load ${ EVENT _KEY$9 } ${ DATA _API _KEY$6 } ` ;
const EVENT _CLICK _DATA _API$5 = ` click ${ EVENT _KEY$9 } ${ DATA _API _KEY$6 } ` ;
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' ;
const CLASS _NAME _NEXT = 'carousel-item-next' ;
const CLASS _NAME _PREV = 'carousel-item-prev' ;
const CLASS _NAME _POINTER _EVENT = 'pointer-event' ;
const SELECTOR _ACTIVE$1 = '.active' ;
const SELECTOR _ACTIVE _ITEM = '.active.carousel-item' ;
const SELECTOR _ITEM = '.carousel-item' ;
const SELECTOR _ITEM _IMG = '.carousel-item img' ;
const SELECTOR _NEXT _PREV = '.carousel-item-next, .carousel-item-prev' ;
const SELECTOR _INDICATORS = '.carousel-indicators' ;
const SELECTOR _INDICATOR = '[data-bs-target]' ;
const SELECTOR _DATA _SLIDE = '[data-bs-slide], [data-bs-slide-to]' ;
const SELECTOR _DATA _RIDE = '[data-bs-ride="carousel"]' ;
const POINTER _TYPE _TOUCH = 'touch' ;
const POINTER _TYPE _PEN = 'pen' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Carousel extends BaseComponent {
constructor ( element , config ) {
super ( element ) ;
this . _items = null ;
this . _interval = null ;
this . _activeElement = null ;
this . _isPaused = false ;
this . _isSliding = false ;
this . touchTimeout = null ;
this . touchStartX = 0 ;
this . touchDeltaX = 0 ;
this . _config = this . _getConfig ( config ) ;
this . _indicatorsElement = SelectorEngine . findOne ( SELECTOR _INDICATORS , this . _element ) ;
this . _touchSupported = 'ontouchstart' in document . documentElement || navigator . maxTouchPoints > 0 ;
this . _pointerEvent = Boolean ( window . PointerEvent ) ;
this . _addEventListeners ( ) ;
2019-03-11 16:13:30 +01:00
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
2021-05-05 21:32:12 +02:00
return Default$9 ;
2021-03-23 17:26:54 +01:00
}
static get DATA _KEY ( ) {
return DATA _KEY$9 ;
} // Public
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
next ( ) {
2019-03-11 16:13:30 +01:00
if ( ! this . _isSliding ) {
2021-03-23 17:26:54 +01:00
this . _slide ( ORDER _NEXT ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
nextWhenVisible ( ) {
2019-03-11 16:13:30 +01:00
// Don't call next when the page isn't visible
// or the carousel or its parent isn't visible
if ( ! document . hidden && isVisible ( this . _element ) ) {
this . next ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
prev ( ) {
2019-03-11 16:13:30 +01:00
if ( ! this . _isSliding ) {
2021-03-23 17:26:54 +01:00
this . _slide ( ORDER _PREV ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
pause ( event ) {
2019-03-11 16:13:30 +01:00
if ( ! event ) {
this . _isPaused = true ;
}
2020-03-28 11:29:08 +01:00
if ( SelectorEngine . findOne ( SELECTOR _NEXT _PREV , this . _element ) ) {
2019-03-11 16:13:30 +01:00
triggerTransitionEnd ( this . _element ) ;
this . cycle ( true ) ;
}
clearInterval ( this . _interval ) ;
this . _interval = null ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
cycle ( event ) {
2019-03-11 16:13:30 +01:00
if ( ! event ) {
this . _isPaused = false ;
}
if ( this . _interval ) {
clearInterval ( this . _interval ) ;
this . _interval = null ;
}
if ( this . _config && this . _config . interval && ! this . _isPaused ) {
2020-11-11 18:07:37 +01:00
this . _updateInterval ( ) ;
2019-03-11 16:13:30 +01:00
this . _interval = setInterval ( ( document . visibilityState ? this . nextWhenVisible : this . next ) . bind ( this ) , this . _config . interval ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
to ( index ) {
2020-03-28 11:29:08 +01:00
this . _activeElement = SelectorEngine . findOne ( SELECTOR _ACTIVE _ITEM , this . _element ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const activeIndex = this . _getItemIndex ( this . _activeElement ) ;
2019-03-11 16:13:30 +01:00
if ( index > this . _items . length - 1 || index < 0 ) {
return ;
}
if ( this . _isSliding ) {
2021-03-23 17:26:54 +01:00
EventHandler . one ( this . _element , EVENT _SLID , ( ) => this . to ( index ) ) ;
2019-03-11 16:13:30 +01:00
return ;
}
if ( activeIndex === index ) {
this . pause ( ) ;
this . cycle ( ) ;
return ;
}
2021-03-23 17:26:54 +01:00
const order = index > activeIndex ? ORDER _NEXT : ORDER _PREV ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _slide ( order , this . _items [ index ] ) ;
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2019-03-11 16:13:30 +01:00
this . _items = null ;
this . _config = null ;
this . _interval = null ;
this . _isPaused = null ;
this . _isSliding = null ;
this . _activeElement = null ;
this . _indicatorsElement = null ;
2021-03-23 17:26:54 +01:00
super . dispose ( ) ;
2019-03-11 16:13:30 +01:00
} // Private
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
2021-05-05 21:32:12 +02:00
config = { ... Default$9 ,
2021-03-23 17:26:54 +01:00
... config
} ;
2021-05-05 21:32:12 +02:00
typeCheckConfig ( NAME$a , config , DefaultType$9 ) ;
2019-03-11 16:13:30 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_handleSwipe ( ) {
const absDeltax = Math . abs ( this . touchDeltaX ) ;
2019-03-11 16:13:30 +01:00
if ( absDeltax <= SWIPE _THRESHOLD ) {
return ;
}
2021-03-23 17:26:54 +01:00
const direction = absDeltax / this . touchDeltaX ;
this . touchDeltaX = 0 ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( ! direction ) {
return ;
2019-03-11 16:13:30 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
this . _slide ( direction > 0 ? DIRECTION _RIGHT : DIRECTION _LEFT ) ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_addEventListeners ( ) {
2019-03-11 16:13:30 +01:00
if ( this . _config . keyboard ) {
2021-03-23 17:26:54 +01:00
EventHandler . on ( this . _element , EVENT _KEYDOWN , event => this . _keydown ( event ) ) ;
2019-03-11 16:13:30 +01:00
}
if ( this . _config . pause === 'hover' ) {
2021-03-23 17:26:54 +01:00
EventHandler . on ( this . _element , EVENT _MOUSEENTER , event => this . pause ( event ) ) ;
EventHandler . on ( this . _element , EVENT _MOUSELEAVE , event => this . cycle ( event ) ) ;
2019-03-11 16:13:30 +01:00
}
2019-07-24 08:13:50 +02:00
if ( this . _config . touch && this . _touchSupported ) {
2019-03-11 16:13:30 +01:00
this . _addTouchEventListeners ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_addTouchEventListeners ( ) {
const start = event => {
if ( this . _pointerEvent && ( event . pointerType === POINTER _TYPE _PEN || event . pointerType === POINTER _TYPE _TOUCH ) ) {
this . touchStartX = event . clientX ;
} else if ( ! this . _pointerEvent ) {
this . touchStartX = event . touches [ 0 ] . clientX ;
2019-03-11 16:13:30 +01:00
}
} ;
2021-03-23 17:26:54 +01:00
const move = event => {
2019-03-11 16:13:30 +01:00
// ensure swiping with one touch and not pinching
2021-03-23 17:26:54 +01:00
this . touchDeltaX = event . touches && event . touches . length > 1 ? 0 : event . touches [ 0 ] . clientX - this . touchStartX ;
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const end = event => {
if ( this . _pointerEvent && ( event . pointerType === POINTER _TYPE _PEN || event . pointerType === POINTER _TYPE _TOUCH ) ) {
this . touchDeltaX = event . clientX - this . touchStartX ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
this . _handleSwipe ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( this . _config . pause === 'hover' ) {
2019-03-11 16:13:30 +01:00
// 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
2021-03-23 17:26:54 +01:00
this . pause ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( this . touchTimeout ) {
clearTimeout ( this . touchTimeout ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
this . touchTimeout = setTimeout ( event => this . cycle ( event ) , TOUCHEVENT _COMPAT _WAIT + this . _config . interval ) ;
2019-03-11 16:13:30 +01:00
}
} ;
2021-03-23 17:26:54 +01:00
SelectorEngine . find ( SELECTOR _ITEM _IMG , this . _element ) . forEach ( itemImg => {
EventHandler . on ( itemImg , EVENT _DRAG _START , e => e . preventDefault ( ) ) ;
2019-03-11 16:13:30 +01:00
} ) ;
if ( this . _pointerEvent ) {
2021-03-23 17:26:54 +01:00
EventHandler . on ( this . _element , EVENT _POINTERDOWN , event => start ( event ) ) ;
EventHandler . on ( this . _element , EVENT _POINTERUP , event => end ( event ) ) ;
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
this . _element . classList . add ( CLASS _NAME _POINTER _EVENT ) ;
2019-03-11 16:13:30 +01:00
} else {
2021-03-23 17:26:54 +01:00
EventHandler . on ( this . _element , EVENT _TOUCHSTART , event => start ( event ) ) ;
EventHandler . on ( this . _element , EVENT _TOUCHMOVE , event => move ( event ) ) ;
EventHandler . on ( this . _element , EVENT _TOUCHEND , event => end ( event ) ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_keydown ( event ) {
2019-03-11 16:13:30 +01:00
if ( /input|textarea/i . test ( event . target . tagName ) ) {
return ;
}
2021-02-10 17:14:51 +01:00
if ( event . key === ARROW _LEFT _KEY ) {
event . preventDefault ( ) ;
2021-05-05 21:32:12 +02:00
this . _slide ( DIRECTION _RIGHT ) ;
2021-02-10 17:14:51 +01:00
} else if ( event . key === ARROW _RIGHT _KEY ) {
event . preventDefault ( ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
this . _slide ( DIRECTION _LEFT ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getItemIndex ( element ) {
2020-03-28 11:29:08 +01:00
this . _items = element && element . parentNode ? SelectorEngine . find ( SELECTOR _ITEM , element . parentNode ) : [ ] ;
2019-03-11 16:13:30 +01:00
return this . _items . indexOf ( element ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getItemByOrder ( order , activeElement ) {
const isNext = order === ORDER _NEXT ;
const isPrev = order === ORDER _PREV ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const activeIndex = this . _getItemIndex ( activeElement ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const lastItemIndex = this . _items . length - 1 ;
const isGoingToWrap = isPrev && activeIndex === 0 || isNext && activeIndex === lastItemIndex ;
2019-03-11 16:13:30 +01:00
if ( isGoingToWrap && ! this . _config . wrap ) {
return activeElement ;
}
2021-03-23 17:26:54 +01:00
const delta = isPrev ? - 1 : 1 ;
const itemIndex = ( activeIndex + delta ) % this . _items . length ;
2019-03-11 16:13:30 +01:00
return itemIndex === - 1 ? this . _items [ this . _items . length - 1 ] : this . _items [ itemIndex ] ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_triggerSlideEvent ( relatedTarget , eventDirectionName ) {
const targetIndex = this . _getItemIndex ( relatedTarget ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const fromIndex = this . _getItemIndex ( SelectorEngine . findOne ( SELECTOR _ACTIVE _ITEM , this . _element ) ) ;
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
return EventHandler . trigger ( this . _element , EVENT _SLIDE , {
2021-03-23 17:26:54 +01:00
relatedTarget ,
2019-03-11 16:13:30 +01:00
direction : eventDirectionName ,
from : fromIndex ,
to : targetIndex
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_setActiveIndicatorElement ( element ) {
2019-03-11 16:13:30 +01:00
if ( this . _indicatorsElement ) {
2021-03-23 17:26:54 +01:00
const activeIndicator = SelectorEngine . findOne ( SELECTOR _ACTIVE$1 , this . _indicatorsElement ) ;
activeIndicator . classList . remove ( CLASS _NAME _ACTIVE$2 ) ;
2021-02-10 17:14:51 +01:00
activeIndicator . removeAttribute ( 'aria-current' ) ;
2021-03-23 17:26:54 +01:00
const indicators = SelectorEngine . find ( SELECTOR _INDICATOR , this . _indicatorsElement ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
for ( let i = 0 ; i < indicators . length ; i ++ ) {
2021-02-10 17:14:51 +01:00
if ( Number . parseInt ( indicators [ i ] . getAttribute ( 'data-bs-slide-to' ) , 10 ) === this . _getItemIndex ( element ) ) {
2021-03-23 17:26:54 +01:00
indicators [ i ] . classList . add ( CLASS _NAME _ACTIVE$2 ) ;
2021-02-10 17:14:51 +01:00
indicators [ i ] . setAttribute ( 'aria-current' , 'true' ) ;
break ;
}
2019-03-11 16:13:30 +01:00
}
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_updateInterval ( ) {
const element = this . _activeElement || SelectorEngine . findOne ( SELECTOR _ACTIVE _ITEM , this . _element ) ;
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 ) ;
2020-11-11 18:07:37 +01:00
if ( elementInterval ) {
this . _config . defaultInterval = this . _config . defaultInterval || this . _config . interval ;
this . _config . interval = elementInterval ;
} else {
this . _config . interval = this . _config . defaultInterval || this . _config . interval ;
}
2021-03-23 17:26:54 +01:00
}
2020-11-11 18:07:37 +01:00
2021-03-23 17:26:54 +01:00
_slide ( directionOrOrder , element ) {
const order = this . _directionToOrder ( directionOrOrder ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const activeElement = SelectorEngine . findOne ( SELECTOR _ACTIVE _ITEM , this . _element ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const activeElementIndex = this . _getItemIndex ( activeElement ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const nextElement = element || this . _getItemByOrder ( order , activeElement ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const nextElementIndex = this . _getItemIndex ( nextElement ) ;
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
const isCycling = Boolean ( this . _interval ) ;
const isNext = order === ORDER _NEXT ;
const directionalClassName = isNext ? CLASS _NAME _START : CLASS _NAME _END ;
const orderClassName = isNext ? CLASS _NAME _NEXT : CLASS _NAME _PREV ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const eventDirectionName = this . _orderToDirection ( order ) ;
if ( nextElement && nextElement . classList . contains ( CLASS _NAME _ACTIVE$2 ) ) {
2019-03-11 16:13:30 +01:00
this . _isSliding = false ;
return ;
}
2021-03-23 17:26:54 +01:00
const slideEvent = this . _triggerSlideEvent ( nextElement , eventDirectionName ) ;
2019-03-11 16:13:30 +01:00
if ( slideEvent . defaultPrevented ) {
return ;
}
if ( ! activeElement || ! nextElement ) {
// Some weirdness is happening, so we bail
return ;
}
this . _isSliding = true ;
if ( isCycling ) {
this . pause ( ) ;
}
this . _setActiveIndicatorElement ( nextElement ) ;
2020-11-11 18:07:37 +01:00
this . _activeElement = nextElement ;
2020-03-28 11:29:08 +01:00
if ( this . _element . classList . contains ( CLASS _NAME _SLIDE ) ) {
2019-03-11 16:13:30 +01:00
nextElement . classList . add ( orderClassName ) ;
reflow ( nextElement ) ;
activeElement . classList . add ( directionalClassName ) ;
nextElement . classList . add ( directionalClassName ) ;
2021-03-23 17:26:54 +01:00
const transitionDuration = getTransitionDurationFromElement ( activeElement ) ;
EventHandler . one ( activeElement , 'transitionend' , ( ) => {
2020-05-13 20:53:43 +02:00
nextElement . classList . remove ( directionalClassName , orderClassName ) ;
2021-03-23 17:26:54 +01:00
nextElement . classList . add ( CLASS _NAME _ACTIVE$2 ) ;
activeElement . classList . remove ( CLASS _NAME _ACTIVE$2 , orderClassName , directionalClassName ) ;
this . _isSliding = false ;
setTimeout ( ( ) => {
EventHandler . trigger ( this . _element , EVENT _SLID , {
2019-03-11 16:13:30 +01:00
relatedTarget : nextElement ,
direction : eventDirectionName ,
from : activeElementIndex ,
to : nextElementIndex
} ) ;
} , 0 ) ;
} ) ;
emulateTransitionEnd ( activeElement , transitionDuration ) ;
} else {
2021-03-23 17:26:54 +01:00
activeElement . classList . remove ( CLASS _NAME _ACTIVE$2 ) ;
nextElement . classList . add ( CLASS _NAME _ACTIVE$2 ) ;
2019-03-11 16:13:30 +01:00
this . _isSliding = false ;
2020-03-28 11:29:08 +01:00
EventHandler . trigger ( this . _element , EVENT _SLID , {
2019-03-11 16:13:30 +01:00
relatedTarget : nextElement ,
direction : eventDirectionName ,
from : activeElementIndex ,
to : nextElementIndex
} ) ;
}
if ( isCycling ) {
this . cycle ( ) ;
}
2021-03-23 17:26:54 +01:00
}
_directionToOrder ( direction ) {
if ( ! [ DIRECTION _RIGHT , DIRECTION _LEFT ] . includes ( direction ) ) {
return direction ;
}
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 ( ! [ ORDER _NEXT , ORDER _PREV ] . includes ( order ) ) {
return 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-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static carouselInterface ( element , config ) {
let data = Data . get ( element , DATA _KEY$9 ) ;
2021-05-05 21:32:12 +02:00
let _config = { ... Default$9 ,
2021-03-23 17:26:54 +01:00
... Manipulator . getDataAttributes ( element )
} ;
2019-03-11 16:13:30 +01:00
if ( typeof config === 'object' ) {
2021-03-23 17:26:54 +01:00
_config = { ... _config ,
... config
} ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
const action = typeof config === 'string' ? config : _config . slide ;
2019-03-11 16:13:30 +01:00
if ( ! data ) {
data = new Carousel ( element , _config ) ;
}
if ( typeof config === 'number' ) {
data . to ( config ) ;
} else if ( typeof action === 'string' ) {
if ( typeof data [ action ] === 'undefined' ) {
2021-03-23 17:26:54 +01:00
throw new TypeError ( ` No method named " ${ action } " ` ) ;
2019-03-11 16:13:30 +01:00
}
data [ action ] ( ) ;
} else if ( _config . interval && _config . ride ) {
data . pause ( ) ;
data . cycle ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2019-08-27 15:03:21 +02:00
Carousel . carouselInterface ( this , config ) ;
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static dataApiClickHandler ( event ) {
const target = getElementFromSelector ( this ) ;
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
if ( ! target || ! target . classList . contains ( CLASS _NAME _CAROUSEL ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-03-23 17:26:54 +01:00
const config = { ... Manipulator . getDataAttributes ( target ) ,
... Manipulator . getDataAttributes ( this )
} ;
const slideIndex = this . getAttribute ( 'data-bs-slide-to' ) ;
2019-03-11 16:13:30 +01:00
if ( slideIndex ) {
config . interval = false ;
}
2019-08-27 15:03:21 +02:00
Carousel . carouselInterface ( target , config ) ;
2019-03-11 16:13:30 +01:00
if ( slideIndex ) {
2021-03-23 17:26:54 +01:00
Data . get ( target , DATA _KEY$9 ) . to ( slideIndex ) ;
2019-03-11 16:13:30 +01:00
}
event . preventDefault ( ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$5 , SELECTOR _DATA _SLIDE , Carousel . dataApiClickHandler ) ;
EventHandler . on ( window , EVENT _LOAD _DATA _API$2 , ( ) => {
const carousels = SelectorEngine . find ( SELECTOR _DATA _RIDE ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
for ( let i = 0 , len = carousels . length ; i < len ; i ++ ) {
Carousel . carouselInterface ( carousels [ i ] , Data . get ( carousels [ i ] , DATA _KEY$9 ) ) ;
2019-03-11 16:13:30 +01:00
}
} ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Carousel to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2021-05-05 21:32:12 +02:00
defineJQueryPlugin ( NAME$a , Carousel ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : collapse . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-05-05 21:32:12 +02:00
const NAME$9 = 'collapse' ;
2021-03-23 17:26:54 +01:00
const DATA _KEY$8 = 'bs.collapse' ;
const EVENT _KEY$8 = ` . ${ DATA _KEY$8 } ` ;
const DATA _API _KEY$5 = '.data-api' ;
2021-05-05 21:32:12 +02:00
const Default$8 = {
2019-03-11 16:13:30 +01:00
toggle : true ,
parent : ''
} ;
2021-05-05 21:32:12 +02:00
const DefaultType$8 = {
2019-03-11 16:13:30 +01:00
toggle : 'boolean' ,
parent : '(string|element)'
} ;
2021-03-23 17:26:54 +01:00
const EVENT _SHOW$5 = ` show ${ EVENT _KEY$8 } ` ;
const EVENT _SHOWN$5 = ` shown ${ EVENT _KEY$8 } ` ;
const EVENT _HIDE$5 = ` hide ${ EVENT _KEY$8 } ` ;
const EVENT _HIDDEN$5 = ` hidden ${ EVENT _KEY$8 } ` ;
const EVENT _CLICK _DATA _API$4 = ` click ${ EVENT _KEY$8 } ${ DATA _API _KEY$5 } ` ;
2021-05-05 21:32:12 +02:00
const CLASS _NAME _SHOW$8 = 'show' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _COLLAPSE = 'collapse' ;
const CLASS _NAME _COLLAPSING = 'collapsing' ;
const CLASS _NAME _COLLAPSED = 'collapsed' ;
const WIDTH = 'width' ;
const HEIGHT = 'height' ;
const SELECTOR _ACTIVES = '.show, .collapsing' ;
const SELECTOR _DATA _TOGGLE$4 = '[data-bs-toggle="collapse"]' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Collapse extends BaseComponent {
constructor ( element , config ) {
super ( element ) ;
this . _isTransitioning = false ;
this . _config = this . _getConfig ( config ) ;
this . _triggerArray = SelectorEngine . find ( ` ${ SELECTOR _DATA _TOGGLE$4 } [href="# ${ this . _element . id } "], ` + ` ${ SELECTOR _DATA _TOGGLE$4 } [data-bs-target="# ${ this . _element . id } "] ` ) ;
const toggleList = SelectorEngine . find ( SELECTOR _DATA _TOGGLE$4 ) ;
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
for ( let i = 0 , len = toggleList . length ; i < len ; i ++ ) {
const elem = toggleList [ i ] ;
const selector = getSelectorFromElement ( elem ) ;
const filterElement = SelectorEngine . find ( selector ) . filter ( foundElem => foundElem === this . _element ) ;
2019-03-11 16:13:30 +01:00
if ( selector !== null && filterElement . length ) {
2021-03-23 17:26:54 +01:00
this . _selector = selector ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _triggerArray . push ( elem ) ;
2019-03-11 16:13:30 +01:00
}
}
2021-03-23 17:26:54 +01:00
this . _parent = this . _config . parent ? this . _getParent ( ) : null ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( ! this . _config . parent ) {
this . _addAriaAndCollapsedClass ( this . _element , this . _triggerArray ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
if ( this . _config . toggle ) {
this . toggle ( ) ;
2019-03-11 16:13:30 +01:00
}
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
2021-05-05 21:32:12 +02:00
return Default$8 ;
2021-03-23 17:26:54 +01:00
}
static get DATA _KEY ( ) {
return DATA _KEY$8 ;
} // Public
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
toggle ( ) {
2021-05-05 21:32:12 +02:00
if ( this . _element . classList . contains ( CLASS _NAME _SHOW$8 ) ) {
2019-03-11 16:13:30 +01:00
this . hide ( ) ;
} else {
this . show ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
show ( ) {
2021-05-05 21:32:12 +02:00
if ( this . _isTransitioning || this . _element . classList . contains ( CLASS _NAME _SHOW$8 ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-03-23 17:26:54 +01:00
let actives ;
let activesData ;
2019-03-11 16:13:30 +01:00
if ( this . _parent ) {
2021-03-23 17:26:54 +01:00
actives = SelectorEngine . find ( SELECTOR _ACTIVES , this . _parent ) . filter ( elem => {
if ( typeof this . _config . parent === 'string' ) {
return elem . getAttribute ( 'data-bs-parent' ) === this . _config . parent ;
2019-03-11 16:13:30 +01:00
}
2020-03-28 11:29:08 +01:00
return elem . classList . contains ( CLASS _NAME _COLLAPSE ) ;
2019-03-11 16:13:30 +01:00
} ) ;
if ( actives . length === 0 ) {
actives = null ;
}
}
2021-03-23 17:26:54 +01:00
const container = SelectorEngine . findOne ( this . _selector ) ;
2019-03-11 16:13:30 +01:00
if ( actives ) {
2021-03-23 17:26:54 +01:00
const tempActiveData = actives . find ( elem => container !== elem ) ;
activesData = tempActiveData ? Data . get ( tempActiveData , DATA _KEY$8 ) : null ;
2019-03-11 16:13:30 +01:00
if ( activesData && activesData . _isTransitioning ) {
return ;
}
}
2021-03-23 17:26:54 +01:00
const startEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$5 ) ;
2019-03-11 16:13:30 +01:00
if ( startEvent . defaultPrevented ) {
return ;
}
if ( actives ) {
2021-03-23 17:26:54 +01:00
actives . forEach ( elemActive => {
2019-03-11 16:13:30 +01:00
if ( container !== elemActive ) {
2019-08-27 15:03:21 +02:00
Collapse . collapseInterface ( elemActive , 'hide' ) ;
2019-03-11 16:13:30 +01:00
}
if ( ! activesData ) {
2021-03-23 17:26:54 +01:00
Data . set ( elemActive , DATA _KEY$8 , null ) ;
2019-03-11 16:13:30 +01:00
}
} ) ;
}
2021-03-23 17:26:54 +01:00
const dimension = this . _getDimension ( ) ;
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
this . _element . classList . remove ( CLASS _NAME _COLLAPSE ) ;
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
this . _element . classList . add ( CLASS _NAME _COLLAPSING ) ;
2019-03-11 16:13:30 +01:00
this . _element . style [ dimension ] = 0 ;
if ( this . _triggerArray . length ) {
2021-03-23 17:26:54 +01:00
this . _triggerArray . forEach ( element => {
2020-03-28 11:29:08 +01:00
element . classList . remove ( CLASS _NAME _COLLAPSED ) ;
2019-03-11 16:13:30 +01:00
element . setAttribute ( 'aria-expanded' , true ) ;
} ) ;
}
this . setTransitioning ( true ) ;
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
this . _element . classList . remove ( CLASS _NAME _COLLAPSING ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
this . _element . classList . add ( CLASS _NAME _COLLAPSE , CLASS _NAME _SHOW$8 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _element . style [ dimension ] = '' ;
this . setTransitioning ( false ) ;
EventHandler . trigger ( this . _element , EVENT _SHOWN$5 ) ;
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const capitalizedDimension = dimension [ 0 ] . toUpperCase ( ) + dimension . slice ( 1 ) ;
const scrollSize = ` scroll ${ capitalizedDimension } ` ;
const transitionDuration = getTransitionDurationFromElement ( this . _element ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( this . _element , 'transitionend' , complete ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( this . _element , transitionDuration ) ;
2021-03-23 17:26:54 +01:00
this . _element . style [ dimension ] = ` ${ this . _element [ scrollSize ] } px ` ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
hide ( ) {
2021-05-05 21:32:12 +02:00
if ( this . _isTransitioning || ! this . _element . classList . contains ( CLASS _NAME _SHOW$8 ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-03-23 17:26:54 +01:00
const startEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$5 ) ;
2019-03-11 16:13:30 +01:00
if ( startEvent . defaultPrevented ) {
return ;
}
2021-03-23 17:26:54 +01:00
const dimension = this . _getDimension ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _element . style [ dimension ] = ` ${ this . _element . getBoundingClientRect ( ) [ dimension ] } px ` ;
2019-03-11 16:13:30 +01:00
reflow ( this . _element ) ;
2020-03-28 11:29:08 +01:00
this . _element . classList . add ( CLASS _NAME _COLLAPSING ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
this . _element . classList . remove ( CLASS _NAME _COLLAPSE , CLASS _NAME _SHOW$8 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const triggerArrayLength = this . _triggerArray . length ;
2019-03-11 16:13:30 +01:00
if ( triggerArrayLength > 0 ) {
2021-03-23 17:26:54 +01:00
for ( let i = 0 ; i < triggerArrayLength ; i ++ ) {
const trigger = this . _triggerArray [ i ] ;
const elem = getElementFromSelector ( trigger ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
if ( elem && ! elem . classList . contains ( CLASS _NAME _SHOW$8 ) ) {
2020-03-28 11:29:08 +01:00
trigger . classList . add ( CLASS _NAME _COLLAPSED ) ;
2019-08-27 15:03:21 +02:00
trigger . setAttribute ( 'aria-expanded' , false ) ;
2019-03-11 16:13:30 +01:00
}
}
}
this . setTransitioning ( true ) ;
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
this . setTransitioning ( false ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _element . classList . remove ( CLASS _NAME _COLLAPSING ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _element . classList . add ( CLASS _NAME _COLLAPSE ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , EVENT _HIDDEN$5 ) ;
2019-03-11 16:13:30 +01:00
} ;
this . _element . style [ dimension ] = '' ;
2021-03-23 17:26:54 +01:00
const transitionDuration = getTransitionDurationFromElement ( this . _element ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( this . _element , 'transitionend' , complete ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( this . _element , transitionDuration ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
setTransitioning ( isTransitioning ) {
2019-03-11 16:13:30 +01:00
this . _isTransitioning = isTransitioning ;
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 ( ) {
super . dispose ( ) ;
2019-03-11 16:13:30 +01:00
this . _config = null ;
this . _parent = null ;
this . _triggerArray = null ;
this . _isTransitioning = null ;
} // Private
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
2021-05-05 21:32:12 +02:00
config = { ... Default$8 ,
2021-03-23 17:26:54 +01:00
... config
} ;
2019-03-11 16:13:30 +01:00
config . toggle = Boolean ( config . toggle ) ; // Coerce string values
2021-05-05 21:32:12 +02:00
typeCheckConfig ( NAME$9 , config , DefaultType$8 ) ;
2019-03-11 16:13:30 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getDimension ( ) {
2020-09-14 17:12:06 +02:00
return this . _element . classList . contains ( WIDTH ) ? WIDTH : HEIGHT ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getParent ( ) {
let {
parent
} = this . _config ;
2019-03-11 16:13:30 +01:00
if ( isElement ( parent ) ) {
// it's a jQuery object
if ( typeof parent . jquery !== 'undefined' || typeof parent [ 0 ] !== 'undefined' ) {
parent = parent [ 0 ] ;
}
} else {
parent = SelectorEngine . findOne ( parent ) ;
}
2021-03-23 17:26:54 +01:00
const selector = ` ${ SELECTOR _DATA _TOGGLE$4 } [data-bs-parent=" ${ parent } "] ` ;
SelectorEngine . find ( selector , parent ) . forEach ( element => {
const selected = getElementFromSelector ( element ) ;
2019-07-24 08:13:50 +02:00
2021-03-23 17:26:54 +01:00
this . _addAriaAndCollapsedClass ( selected , [ element ] ) ;
2019-03-11 16:13:30 +01:00
} ) ;
return parent ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_addAriaAndCollapsedClass ( element , triggerArray ) {
2020-09-14 17:12:06 +02:00
if ( ! element || ! triggerArray . length ) {
return ;
}
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
const isOpen = element . classList . contains ( CLASS _NAME _SHOW$8 ) ;
2021-03-23 17:26:54 +01:00
triggerArray . forEach ( elem => {
2020-09-14 17:12:06 +02:00
if ( isOpen ) {
elem . classList . remove ( CLASS _NAME _COLLAPSED ) ;
} else {
elem . classList . add ( CLASS _NAME _COLLAPSED ) ;
2019-03-11 16:13:30 +01:00
}
2020-09-14 17:12:06 +02:00
elem . setAttribute ( 'aria-expanded' , isOpen ) ;
} ) ;
2019-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static collapseInterface ( element , config ) {
let data = Data . get ( element , DATA _KEY$8 ) ;
2021-05-05 21:32:12 +02:00
const _config = { ... Default$8 ,
2021-03-23 17:26:54 +01:00
... Manipulator . getDataAttributes ( element ) ,
... ( typeof config === 'object' && config ? config : { } )
} ;
2019-03-11 16:13:30 +01:00
2020-05-13 20:53:43 +02:00
if ( ! data && _config . toggle && typeof config === 'string' && /show|hide/ . test ( config ) ) {
2019-03-11 16:13:30 +01:00
_config . toggle = false ;
}
if ( ! data ) {
data = new Collapse ( element , _config ) ;
}
if ( typeof config === 'string' ) {
if ( typeof data [ config ] === 'undefined' ) {
2021-03-23 17:26:54 +01:00
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2019-03-11 16:13:30 +01:00
}
data [ config ] ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2019-08-27 15:03:21 +02:00
Collapse . collapseInterface ( this , config ) ;
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _CLICK _DATA _API$4 , SELECTOR _DATA _TOGGLE$4 , function ( event ) {
2019-03-11 16:13:30 +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' ) {
2019-03-11 16:13:30 +01:00
event . preventDefault ( ) ;
}
2021-03-23 17:26:54 +01:00
const triggerData = Manipulator . getDataAttributes ( this ) ;
const selector = getSelectorFromElement ( this ) ;
const selectorElements = SelectorEngine . find ( selector ) ;
selectorElements . forEach ( element => {
const data = Data . get ( element , DATA _KEY$8 ) ;
let config ;
2019-03-11 16:13:30 +01:00
if ( data ) {
// update parent attribute
if ( data . _parent === null && typeof triggerData . parent === 'string' ) {
data . _config . parent = triggerData . parent ;
data . _parent = data . _getParent ( ) ;
}
config = 'toggle' ;
} else {
config = triggerData ;
}
2019-08-27 15:03:21 +02:00
Collapse . collapseInterface ( element , config ) ;
2019-03-11 16:13:30 +01:00
} ) ;
} ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Collapse to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2021-05-05 21:32:12 +02:00
defineJQueryPlugin ( NAME$9 , Collapse ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : dropdown . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-05-05 21:32:12 +02:00
const NAME$8 = 'dropdown' ;
2021-03-23 17:26:54 +01:00
const DATA _KEY$7 = 'bs.dropdown' ;
const EVENT _KEY$7 = ` . ${ DATA _KEY$7 } ` ;
const DATA _API _KEY$4 = '.data-api' ;
const ESCAPE _KEY$2 = 'Escape' ;
const SPACE _KEY = 'Space' ;
const TAB _KEY = 'Tab' ;
const ARROW _UP _KEY = 'ArrowUp' ;
const ARROW _DOWN _KEY = 'ArrowDown' ;
const RIGHT _MOUSE _BUTTON = 2 ; // MouseEvent.button value for the secondary button, usually the right button
const REGEXP _KEYDOWN = new RegExp ( ` ${ ARROW _UP _KEY } | ${ ARROW _DOWN _KEY } | ${ ESCAPE _KEY$2 } ` ) ;
const EVENT _HIDE$4 = ` hide ${ EVENT _KEY$7 } ` ;
const EVENT _HIDDEN$4 = ` hidden ${ EVENT _KEY$7 } ` ;
const EVENT _SHOW$4 = ` show ${ EVENT _KEY$7 } ` ;
const EVENT _SHOWN$4 = ` shown ${ EVENT _KEY$7 } ` ;
const EVENT _CLICK = ` click ${ EVENT _KEY$7 } ` ;
const EVENT _CLICK _DATA _API$3 = ` click ${ EVENT _KEY$7 } ${ DATA _API _KEY$4 } ` ;
const EVENT _KEYDOWN _DATA _API = ` keydown ${ EVENT _KEY$7 } ${ DATA _API _KEY$4 } ` ;
const EVENT _KEYUP _DATA _API = ` keyup ${ EVENT _KEY$7 } ${ DATA _API _KEY$4 } ` ;
2021-05-05 21:32:12 +02:00
const CLASS _NAME _SHOW$7 = 'show' ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _DROPUP = 'dropup' ;
const CLASS _NAME _DROPEND = 'dropend' ;
const CLASS _NAME _DROPSTART = 'dropstart' ;
const CLASS _NAME _NAVBAR = 'navbar' ;
const SELECTOR _DATA _TOGGLE$3 = '[data-bs-toggle="dropdown"]' ;
const SELECTOR _MENU = '.dropdown-menu' ;
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' ;
2021-05-05 21:32:12 +02:00
const Default$7 = {
2021-02-10 17:14:51 +01:00
offset : [ 0 , 2 ] ,
2020-12-07 16:50:24 +01:00
boundary : 'clippingParents' ,
2019-03-11 16:13:30 +01:00
reference : 'toggle' ,
2019-08-27 15:03:21 +02:00
display : 'dynamic' ,
2021-05-05 21:32:12 +02:00
popperConfig : null ,
autoClose : true
2019-03-11 16:13:30 +01:00
} ;
2021-05-05 21:32:12 +02:00
const DefaultType$7 = {
2021-02-10 17:14:51 +01:00
offset : '(array|string|function)' ,
2019-03-11 16:13:30 +01:00
boundary : '(string|element)' ,
2021-02-10 17:14:51 +01:00
reference : '(string|element|object)' ,
2019-08-27 15:03:21 +02:00
display : 'string' ,
2021-05-05 21:32:12 +02:00
popperConfig : '(null|object|function)' ,
autoClose : '(boolean|string)'
2019-03-11 16:13:30 +01:00
} ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Dropdown extends BaseComponent {
constructor ( element , config ) {
super ( element ) ;
this . _popper = null ;
this . _config = this . _getConfig ( config ) ;
this . _menu = this . _getMenuElement ( ) ;
this . _inNavbar = this . _detectNavbar ( ) ;
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
this . _addEventListeners ( ) ;
} // Getters
2020-12-03 15:18:59 +01:00
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static get Default ( ) {
2021-05-05 21:32:12 +02:00
return Default$7 ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static get DefaultType ( ) {
2021-05-05 21:32:12 +02:00
return DefaultType$7 ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static get DATA _KEY ( ) {
return DATA _KEY$7 ;
} // Public
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
toggle ( ) {
2021-05-05 21:32:12 +02:00
if ( isDisabled ( this . _element ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-05-05 21:32:12 +02:00
const isActive = this . _element . classList . contains ( CLASS _NAME _SHOW$7 ) ;
2019-03-11 16:13:30 +01:00
if ( isActive ) {
2021-05-05 21:32:12 +02:00
this . hide ( ) ;
2019-03-11 16:13:30 +01:00
return ;
}
2019-08-27 15:03:21 +02:00
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 ( ) {
2021-05-05 21:32:12 +02:00
if ( isDisabled ( this . _element ) || this . _menu . classList . contains ( CLASS _NAME _SHOW$7 ) ) {
2019-08-27 15:03:21 +02:00
return ;
}
2021-03-23 17:26:54 +01:00
const parent = Dropdown . getParentFromElement ( this . _element ) ;
const relatedTarget = {
2019-03-11 16:13:30 +01:00
relatedTarget : this . _element
} ;
2021-03-23 17:26:54 +01:00
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$4 , relatedTarget ) ;
2019-03-11 16:13:30 +01:00
if ( showEvent . defaultPrevented ) {
return ;
2020-11-23 14:17:16 +01:00
} // Totally disable Popper for Dropdowns in Navbar
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
if ( this . _inNavbar ) {
Manipulator . setDataAttribute ( this . _menu , 'popper' , 'none' ) ;
} else {
2019-03-11 16:13:30 +01:00
if ( typeof Popper === 'undefined' ) {
2020-11-23 14:17:16 +01:00
throw new TypeError ( 'Bootstrap\'s dropdowns require Popper (https://popper.js.org)' ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
let referenceElement = this . _element ;
2019-03-11 16:13:30 +01:00
if ( this . _config . reference === 'parent' ) {
referenceElement = parent ;
} else if ( isElement ( this . _config . reference ) ) {
referenceElement = this . _config . reference ; // Check if it's jQuery element
if ( typeof this . _config . reference . jquery !== 'undefined' ) {
referenceElement = this . _config . reference [ 0 ] ;
}
2021-02-10 17:14:51 +01:00
} else if ( typeof this . _config . reference === 'object' ) {
referenceElement = this . _config . reference ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
const popperConfig = this . _getPopperConfig ( ) ;
2021-02-10 17:14:51 +01:00
2021-03-23 17:26:54 +01:00
const isDisplayStatic = popperConfig . modifiers . find ( modifier => modifier . name === 'applyStyles' && modifier . enabled === false ) ;
this . _popper = Popper . createPopper ( referenceElement , this . _menu , popperConfig ) ;
2021-02-10 17:14:51 +01:00
if ( isDisplayStatic ) {
Manipulator . setDataAttribute ( this . _menu , 'popper' , 'static' ) ;
}
2019-03-11 16:13:30 +01:00
} // If this is a touch-enabled device we add extra
// 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-05-13 20:53:43 +02:00
if ( 'ontouchstart' in document . documentElement && ! parent . closest ( SELECTOR _NAVBAR _NAV ) ) {
2021-05-05 21:32:12 +02:00
[ ] . concat ( ... document . body . children ) . forEach ( elem => EventHandler . on ( elem , 'mouseover' , noop ) ) ;
2019-03-11 16:13:30 +01:00
}
this . _element . focus ( ) ;
this . _element . setAttribute ( 'aria-expanded' , true ) ;
2021-05-05 21:32:12 +02:00
this . _menu . classList . toggle ( CLASS _NAME _SHOW$7 ) ;
2020-10-28 04:45:48 +01:00
2021-05-05 21:32:12 +02:00
this . _element . classList . toggle ( CLASS _NAME _SHOW$7 ) ;
2020-10-28 04:45:48 +01:00
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , EVENT _SHOWN$4 , relatedTarget ) ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
hide ( ) {
2021-05-05 21:32:12 +02:00
if ( isDisabled ( this . _element ) || ! this . _menu . classList . contains ( CLASS _NAME _SHOW$7 ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-03-23 17:26:54 +01:00
const relatedTarget = {
2019-03-11 16:13:30 +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-03-11 16:13:30 +01:00
this . _menu = null ;
2019-08-27 15:03:21 +02:00
if ( this . _popper ) {
2019-03-11 16:13:30 +01:00
this . _popper . destroy ( ) ;
this . _popper = null ;
}
2021-03-23 17:26:54 +01:00
super . dispose ( ) ;
}
update ( ) {
2019-03-11 16:13:30 +01:00
this . _inNavbar = this . _detectNavbar ( ) ;
2019-08-27 15:03:21 +02:00
if ( this . _popper ) {
2020-12-07 16:50:24 +01:00
this . _popper . update ( ) ;
2019-03-11 16:13:30 +01:00
}
} // Private
2021-03-23 17:26:54 +01:00
_addEventListeners ( ) {
EventHandler . on ( this . _element , EVENT _CLICK , event => {
2019-03-11 16:13:30 +01:00
event . preventDefault ( ) ;
2021-03-23 17:26:54 +01:00
this . toggle ( ) ;
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
_completeHide ( relatedTarget ) {
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$4 , relatedTarget ) ;
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 ) {
[ ] . concat ( ... document . body . children ) . forEach ( elem => EventHandler . off ( elem , 'mouseover' , noop ) ) ;
}
if ( this . _popper ) {
this . _popper . destroy ( ) ;
}
this . _menu . classList . remove ( CLASS _NAME _SHOW$7 ) ;
this . _element . classList . remove ( CLASS _NAME _SHOW$7 ) ;
this . _element . setAttribute ( 'aria-expanded' , 'false' ) ;
Manipulator . removeDataAttribute ( this . _menu , 'popper' ) ;
EventHandler . trigger ( this . _element , EVENT _HIDDEN$4 , relatedTarget ) ;
}
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
config = { ... this . constructor . Default ,
... Manipulator . getDataAttributes ( this . _element ) ,
... config
} ;
2021-05-05 21:32:12 +02:00
typeCheckConfig ( NAME$8 , config , this . constructor . DefaultType ) ;
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
2021-05-05 21:32:12 +02:00
throw new TypeError ( ` ${ NAME$8 . toUpperCase ( ) } : Option "reference" provided type "object" without a required "getBoundingClientRect" method. ` ) ;
2021-02-10 17:14:51 +01:00
}
2019-03-11 16:13:30 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getMenuElement ( ) {
2020-03-28 11:29:08 +01:00
return SelectorEngine . next ( this . _element , SELECTOR _MENU ) [ 0 ] ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getPlacement ( ) {
const parentDropdown = this . _element . parentNode ;
2019-03-11 16:13:30 +01:00
2020-12-07 16:50:24 +01:00
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPEND ) ) {
return PLACEMENT _RIGHT ;
2019-03-11 16:13:30 +01:00
}
2020-12-07 16:50:24 +01:00
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPSTART ) ) {
return PLACEMENT _LEFT ;
} // We need to trim the value because custom properties can also include spaces
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const isEnd = getComputedStyle ( this . _menu ) . getPropertyValue ( '--bs-position' ) . trim ( ) === 'end' ;
2019-04-18 13:47:52 +02:00
2020-12-07 16:50:24 +01:00
if ( parentDropdown . classList . contains ( CLASS _NAME _DROPUP ) ) {
return isEnd ? PLACEMENT _TOPEND : PLACEMENT _TOP ;
2019-03-11 16:13:30 +01:00
}
2020-12-07 16:50:24 +01:00
return isEnd ? PLACEMENT _BOTTOMEND : PLACEMENT _BOTTOM ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_detectNavbar ( ) {
return this . _element . closest ( ` . ${ CLASS _NAME _NAVBAR } ` ) !== null ;
}
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' ) {
2021-03-23 17:26:54 +01:00
return offset . split ( ',' ) . map ( val => Number . parseInt ( val , 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 = {
2019-03-11 16:13:30 +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 ( )
2019-03-11 16:13:30 +01:00
}
2020-12-07 16:50:24 +01:00
} ]
2020-11-23 14:17:16 +01:00
} ; // Disable Popper if we have a static display
2019-03-11 16:13:30 +01:00
if ( this . _config . display === 'static' ) {
2021-02-10 17:14:51 +01:00
defaultBsPopperConfig . modifiers = [ {
2020-12-07 16:50:24 +01:00
name : 'applyStyles' ,
2019-03-11 16:13:30 +01:00
enabled : false
2020-12-07 16:50:24 +01:00
} ] ;
2019-03-11 16:13:30 +01: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
}
_selectMenuItem ( event ) {
const items = SelectorEngine . find ( SELECTOR _VISIBLE _ITEMS , this . _menu ) . filter ( isVisible ) ;
if ( ! items . length ) {
return ;
}
let index = items . indexOf ( event . target ) ; // Up
if ( event . key === ARROW _UP _KEY && index > 0 ) {
index -- ;
} // Down
if ( event . key === ARROW _DOWN _KEY && index < items . length - 1 ) {
index ++ ;
} // index is -1 if the first keydown is an ArrowUp
index = index === - 1 ? 0 : index ;
items [ index ] . focus ( ) ;
2019-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static dropdownInterface ( element , config ) {
let data = Data . get ( element , DATA _KEY$7 ) ;
const _config = typeof config === 'object' ? config : null ;
2019-03-11 16:13:30 +01:00
if ( ! data ) {
data = new Dropdown ( element , _config ) ;
}
if ( typeof config === 'string' ) {
if ( typeof data [ config ] === 'undefined' ) {
2021-03-23 17:26:54 +01:00
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2019-03-11 16:13:30 +01:00
}
data [ config ] ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2019-08-27 15:03:21 +02:00
Dropdown . dropdownInterface ( this , config ) ;
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static clearMenus ( event ) {
if ( event ) {
if ( event . button === RIGHT _MOUSE _BUTTON || event . type === 'keyup' && event . key !== TAB _KEY ) {
return ;
}
2021-05-05 21:32:12 +02:00
if ( /input|select|option|textarea|form/i . test ( event . target . tagName ) ) {
2021-03-23 17:26:54 +01:00
return ;
}
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
const toggles = SelectorEngine . find ( SELECTOR _DATA _TOGGLE$3 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
for ( let i = 0 , len = toggles . length ; i < len ; i ++ ) {
const context = Data . get ( toggles [ i ] , DATA _KEY$7 ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
if ( ! context || context . _config . autoClose === false ) {
2019-03-11 16:13:30 +01:00
continue ;
}
2021-05-05 21:32:12 +02:00
if ( ! context . _element . classList . contains ( CLASS _NAME _SHOW$7 ) ) {
2019-03-11 16:13:30 +01:00
continue ;
}
2021-05-05 21:32:12 +02:00
const relatedTarget = {
relatedTarget : context . _element
} ;
2021-03-23 17:26:54 +01:00
if ( event ) {
2021-05-05 21:32:12 +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 ) {
2021-03-23 17:26:54 +01:00
continue ;
} // Tab navigation through the dropdown menu shouldn't close the menu
2021-05-05 21:32:12 +02:00
if ( event . type === 'keyup' && event . key === TAB _KEY && context . _menu . contains ( event . target ) ) {
2021-03-23 17:26:54 +01:00
continue ;
}
2019-08-27 15:03:21 +02:00
2021-05-05 21:32:12 +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 ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static getParentFromElement ( element ) {
2019-08-27 15:03:21 +02:00
return getElementFromSelector ( element ) || element . parentNode ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static dataApiKeydownHandler ( event ) {
2019-03-11 16:13:30 +01:00
// If not input/textarea:
// - And not a key in REGEXP_KEYDOWN => not a dropdown command
// If input/textarea:
// - If space key => not a dropdown command
// - If key is other than escape
// - If key is not up or down => not a dropdown command
// - If trigger inside the menu => not a dropdown command
2021-03-23 17:26:54 +01:00
if ( /input|textarea/i . test ( event . target . tagName ) ? event . key === SPACE _KEY || event . key !== ESCAPE _KEY$2 && ( event . key !== ARROW _DOWN _KEY && event . key !== ARROW _UP _KEY || event . target . closest ( SELECTOR _MENU ) ) : ! REGEXP _KEYDOWN . test ( event . key ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-05-05 21:32:12 +02:00
const isActive = this . classList . contains ( CLASS _NAME _SHOW$7 ) ;
if ( ! isActive && event . key === ESCAPE _KEY$2 ) {
return ;
}
2019-03-11 16:13:30 +01:00
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
2021-05-05 21:32:12 +02:00
if ( isDisabled ( this ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-05-05 21:32:12 +02:00
const getToggleButton = ( ) => this . matches ( SELECTOR _DATA _TOGGLE$3 ) ? this : SelectorEngine . prev ( this , SELECTOR _DATA _TOGGLE$3 ) [ 0 ] ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( event . key === ESCAPE _KEY$2 ) {
2021-05-05 21:32:12 +02:00
getToggleButton ( ) . focus ( ) ;
2020-03-28 11:29:08 +01:00
Dropdown . clearMenus ( ) ;
return ;
}
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
if ( ! isActive && ( event . key === ARROW _UP _KEY || event . key === ARROW _DOWN _KEY ) ) {
2021-05-05 21:32:12 +02:00
getToggleButton ( ) . click ( ) ;
2021-02-10 17:14:51 +01:00
return ;
}
2020-05-13 20:53:43 +02:00
if ( ! isActive || event . key === SPACE _KEY ) {
2019-08-27 15:03:21 +02:00
Dropdown . clearMenus ( ) ;
2019-03-11 16:13:30 +01:00
return ;
}
2021-05-05 21:32:12 +02:00
Dropdown . getInstance ( getToggleButton ( ) ) . _selectMenuItem ( event ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
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 ) {
2019-03-11 16:13:30 +01:00
event . preventDefault ( ) ;
2021-03-23 17:26:54 +01:00
Dropdown . dropdownInterface ( this ) ;
2019-04-18 13:47:52 +02:00
} ) ;
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Dropdown to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2021-05-05 21:32:12 +02:00
defineJQueryPlugin ( NAME$8 , Dropdown ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : util / scrollBar . js
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
const SELECTOR _FIXED _CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top' ;
const SELECTOR _STICKY _CONTENT = '.sticky-top' ;
const 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 ) ;
} ;
const hide = ( width = getWidth ( ) ) => {
_disableOverFlow ( ) ; // give padding to element to balances the hidden scrollbar width
_setElementAttributes ( 'body' , 'paddingRight' , calculatedValue => calculatedValue + width ) ; // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements, to keep shown fullwidth
_setElementAttributes ( SELECTOR _FIXED _CONTENT , 'paddingRight' , calculatedValue => calculatedValue + width ) ;
_setElementAttributes ( SELECTOR _STICKY _CONTENT , 'marginRight' , calculatedValue => calculatedValue - width ) ;
} ;
const _disableOverFlow = ( ) => {
const actualValue = document . body . style . overflow ;
if ( actualValue ) {
Manipulator . setDataAttribute ( document . body , 'overflow' , actualValue ) ;
}
document . body . style . overflow = 'hidden' ;
} ;
const _setElementAttributes = ( selector , styleProp , callback ) => {
const scrollbarWidth = getWidth ( ) ;
SelectorEngine . find ( selector ) . forEach ( element => {
if ( element !== document . body && window . innerWidth > element . clientWidth + scrollbarWidth ) {
return ;
}
const actualValue = element . style [ styleProp ] ;
const calculatedValue = window . getComputedStyle ( element ) [ styleProp ] ;
Manipulator . setDataAttribute ( element , styleProp , actualValue ) ;
element . style [ styleProp ] = ` ${ callback ( Number . parseFloat ( calculatedValue ) ) } px ` ;
} ) ;
} ;
const reset = ( ) => {
_resetElementAttributes ( 'body' , 'overflow' ) ;
_resetElementAttributes ( 'body' , 'paddingRight' ) ;
_resetElementAttributes ( SELECTOR _FIXED _CONTENT , 'paddingRight' ) ;
_resetElementAttributes ( SELECTOR _STICKY _CONTENT , 'marginRight' ) ;
} ;
const _resetElementAttributes = ( selector , styleProp ) => {
SelectorEngine . find ( selector ) . forEach ( element => {
const value = Manipulator . getDataAttribute ( element , styleProp ) ;
if ( typeof value === 'undefined' ) {
element . style . removeProperty ( styleProp ) ;
} else {
Manipulator . removeDataAttribute ( element , styleProp ) ;
element . style [ styleProp ] = value ;
}
} ) ;
} ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Bootstrap ( v5 . 0.0 ) : util / backdrop . js
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/master/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
const Default$6 = {
isVisible : true ,
// if false, we use the backdrop helper without adding any element to the dom
isAnimated : false ,
rootElement : document . body ,
// give the choice to place backdrop under different elements
clickCallback : null
} ;
const DefaultType$6 = {
isVisible : 'boolean' ,
isAnimated : 'boolean' ,
rootElement : 'element' ,
clickCallback : '(function|null)'
} ;
const NAME$7 = 'backdrop' ;
const CLASS _NAME _BACKDROP = 'modal-backdrop' ;
const CLASS _NAME _FADE$5 = 'fade' ;
const CLASS _NAME _SHOW$6 = 'show' ;
const EVENT _MOUSEDOWN = ` mousedown.bs. ${ NAME$7 } ` ;
class Backdrop {
constructor ( config ) {
this . _config = this . _getConfig ( config ) ;
this . _isAppended = false ;
this . _element = null ;
}
show ( callback ) {
if ( ! this . _config . isVisible ) {
execute ( callback ) ;
return ;
}
this . _append ( ) ;
if ( this . _config . isAnimated ) {
reflow ( this . _getElement ( ) ) ;
}
this . _getElement ( ) . classList . add ( CLASS _NAME _SHOW$6 ) ;
this . _emulateAnimation ( ( ) => {
execute ( callback ) ;
} ) ;
}
hide ( callback ) {
if ( ! this . _config . isVisible ) {
execute ( callback ) ;
return ;
}
this . _getElement ( ) . classList . remove ( CLASS _NAME _SHOW$6 ) ;
this . _emulateAnimation ( ( ) => {
this . dispose ( ) ;
execute ( callback ) ;
} ) ;
} // Private
_getElement ( ) {
if ( ! this . _element ) {
const backdrop = document . createElement ( 'div' ) ;
backdrop . className = CLASS _NAME _BACKDROP ;
if ( this . _config . isAnimated ) {
backdrop . classList . add ( CLASS _NAME _FADE$5 ) ;
}
this . _element = backdrop ;
}
return this . _element ;
}
_getConfig ( config ) {
config = { ... Default$6 ,
... ( typeof config === 'object' ? config : { } )
} ;
typeCheckConfig ( NAME$7 , config , DefaultType$6 ) ;
return config ;
}
_append ( ) {
if ( this . _isAppended ) {
return ;
}
this . _config . rootElement . appendChild ( this . _getElement ( ) ) ;
EventHandler . on ( this . _getElement ( ) , EVENT _MOUSEDOWN , ( ) => {
execute ( this . _config . clickCallback ) ;
} ) ;
this . _isAppended = true ;
}
dispose ( ) {
if ( ! this . _isAppended ) {
return ;
}
EventHandler . off ( this . _element , EVENT _MOUSEDOWN ) ;
this . _getElement ( ) . parentNode . removeChild ( this . _element ) ;
this . _isAppended = false ;
}
_emulateAnimation ( callback ) {
if ( ! this . _config . isAnimated ) {
execute ( callback ) ;
return ;
}
const backdropTransitionDuration = getTransitionDurationFromElement ( this . _getElement ( ) ) ;
EventHandler . one ( this . _getElement ( ) , 'transitionend' , ( ) => execute ( callback ) ) ;
emulateTransitionEnd ( this . _getElement ( ) , backdropTransitionDuration ) ;
}
}
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Bootstrap ( v5 . 0.0 ) : modal . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const NAME$6 = 'modal' ;
const DATA _KEY$6 = 'bs.modal' ;
const EVENT _KEY$6 = ` . ${ DATA _KEY$6 } ` ;
const DATA _API _KEY$3 = '.data-api' ;
const ESCAPE _KEY$1 = 'Escape' ;
const Default$5 = {
2019-03-11 16:13:30 +01:00
backdrop : true ,
keyboard : true ,
2020-12-03 15:18:59 +01:00
focus : true
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const DefaultType$5 = {
2019-03-11 16:13:30 +01:00
backdrop : '(boolean|string)' ,
keyboard : 'boolean' ,
2020-12-03 15:18:59 +01:00
focus : 'boolean'
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const EVENT _HIDE$3 = ` hide ${ EVENT _KEY$6 } ` ;
const EVENT _HIDE _PREVENTED = ` hidePrevented ${ EVENT _KEY$6 } ` ;
const EVENT _HIDDEN$3 = ` hidden ${ EVENT _KEY$6 } ` ;
const EVENT _SHOW$3 = ` show ${ EVENT _KEY$6 } ` ;
const EVENT _SHOWN$3 = ` shown ${ EVENT _KEY$6 } ` ;
const EVENT _FOCUSIN$1 = ` focusin ${ EVENT _KEY$6 } ` ;
const EVENT _RESIZE = ` resize ${ EVENT _KEY$6 } ` ;
const EVENT _CLICK _DISMISS$2 = ` click.dismiss ${ EVENT _KEY$6 } ` ;
2021-05-05 21:32:12 +02:00
const EVENT _KEYDOWN _DISMISS$1 = ` keydown.dismiss ${ EVENT _KEY$6 } ` ;
2021-03-23 17:26:54 +01:00
const EVENT _MOUSEUP _DISMISS = ` mouseup.dismiss ${ EVENT _KEY$6 } ` ;
const EVENT _MOUSEDOWN _DISMISS = ` mousedown.dismiss ${ EVENT _KEY$6 } ` ;
const EVENT _CLICK _DATA _API$2 = ` click ${ EVENT _KEY$6 } ${ DATA _API _KEY$3 } ` ;
const CLASS _NAME _OPEN = 'modal-open' ;
const CLASS _NAME _FADE$4 = 'fade' ;
const CLASS _NAME _SHOW$5 = 'show' ;
const CLASS _NAME _STATIC = 'modal-static' ;
const SELECTOR _DIALOG = '.modal-dialog' ;
const SELECTOR _MODAL _BODY = '.modal-body' ;
const SELECTOR _DATA _TOGGLE$2 = '[data-bs-toggle="modal"]' ;
const SELECTOR _DATA _DISMISS$2 = '[data-bs-dismiss="modal"]' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Modal extends BaseComponent {
constructor ( element , config ) {
super ( element ) ;
this . _config = this . _getConfig ( config ) ;
this . _dialog = SelectorEngine . findOne ( SELECTOR _DIALOG , this . _element ) ;
2021-05-05 21:32:12 +02:00
this . _backdrop = this . _initializeBackDrop ( ) ;
2021-03-23 17:26:54 +01:00
this . _isShown = false ;
this . _ignoreBackdropClick = false ;
this . _isTransitioning = false ;
2019-03-11 16:13:30 +01:00
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
return Default$5 ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static get DATA _KEY ( ) {
return DATA _KEY$6 ;
} // Public
2019-04-18 13:47:52 +02:00
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
toggle ( relatedTarget ) {
return this . _isShown ? this . hide ( ) : this . show ( relatedTarget ) ;
}
show ( relatedTarget ) {
2019-03-11 16:13:30 +01:00
if ( this . _isShown || this . _isTransitioning ) {
return ;
}
2021-03-23 17:26:54 +01:00
if ( this . _isAnimated ( ) ) {
2019-03-11 16:13:30 +01:00
this . _isTransitioning = true ;
}
2021-03-23 17:26:54 +01:00
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$3 , {
relatedTarget
2019-03-11 16:13:30 +01:00
} ) ;
if ( this . _isShown || showEvent . defaultPrevented ) {
return ;
}
this . _isShown = true ;
2021-05-05 21:32:12 +02:00
hide ( ) ;
document . body . classList . add ( CLASS _NAME _OPEN ) ;
2019-03-11 16:13:30 +01:00
this . _adjustDialog ( ) ;
this . _setEscapeEvent ( ) ;
this . _setResizeEvent ( ) ;
2021-03-23 17:26:54 +01:00
EventHandler . on ( this . _element , EVENT _CLICK _DISMISS$2 , SELECTOR _DATA _DISMISS$2 , event => this . hide ( event ) ) ;
EventHandler . on ( this . _dialog , EVENT _MOUSEDOWN _DISMISS , ( ) => {
EventHandler . one ( this . _element , EVENT _MOUSEUP _DISMISS , event => {
if ( event . target === this . _element ) {
this . _ignoreBackdropClick = true ;
2019-03-11 16:13:30 +01:00
}
} ) ;
} ) ;
2021-03-23 17:26:54 +01:00
this . _showBackdrop ( ( ) => this . _showElement ( relatedTarget ) ) ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
hide ( event ) {
2019-03-11 16:13:30 +01:00
if ( event ) {
event . preventDefault ( ) ;
}
if ( ! this . _isShown || this . _isTransitioning ) {
return ;
}
2021-03-23 17:26:54 +01:00
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$3 ) ;
2019-03-11 16:13:30 +01:00
2019-07-24 08:13:50 +02:00
if ( hideEvent . defaultPrevented ) {
2019-03-11 16:13:30 +01:00
return ;
}
this . _isShown = false ;
2021-03-23 17:26:54 +01:00
const isAnimated = this . _isAnimated ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( isAnimated ) {
2019-03-11 16:13:30 +01:00
this . _isTransitioning = true ;
}
this . _setEscapeEvent ( ) ;
this . _setResizeEvent ( ) ;
2021-03-23 17:26:54 +01:00
EventHandler . off ( document , EVENT _FOCUSIN$1 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _element . classList . remove ( CLASS _NAME _SHOW$5 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
EventHandler . off ( this . _element , EVENT _CLICK _DISMISS$2 ) ;
2020-03-28 11:29:08 +01:00
EventHandler . off ( this . _dialog , EVENT _MOUSEDOWN _DISMISS ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( isAnimated ) {
const transitionDuration = getTransitionDurationFromElement ( this . _element ) ;
EventHandler . one ( this . _element , 'transitionend' , event => this . _hideModal ( event ) ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( this . _element , transitionDuration ) ;
} else {
this . _hideModal ( ) ;
}
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 ( ) {
2021-05-05 21:32:12 +02:00
[ window , this . _dialog ] . forEach ( htmlElement => EventHandler . off ( htmlElement , EVENT _KEY$6 ) ) ;
2021-03-23 17:26:54 +01:00
super . dispose ( ) ;
2019-03-11 16:13:30 +01:00
/ * *
2020-03-28 11:29:08 +01:00
* ` document ` has 2 events ` EVENT_FOCUSIN ` and ` EVENT_CLICK_DATA_API `
2019-03-11 16:13:30 +01:00
* Do not move ` document ` in ` htmlElements ` array
2020-03-28 11:29:08 +01:00
* It will remove ` EVENT_CLICK_DATA_API ` event that should remain
2019-03-11 16:13:30 +01:00
* /
2021-03-23 17:26:54 +01:00
EventHandler . off ( document , EVENT _FOCUSIN$1 ) ;
2019-03-11 16:13:30 +01:00
this . _config = null ;
this . _dialog = null ;
2021-05-05 21:32:12 +02:00
this . _backdrop . dispose ( ) ;
2019-03-11 16:13:30 +01:00
this . _backdrop = null ;
this . _isShown = null ;
this . _ignoreBackdropClick = null ;
this . _isTransitioning = null ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
handleUpdate ( ) {
2019-03-11 16:13:30 +01:00
this . _adjustDialog ( ) ;
} // Private
2019-04-18 13:47:52 +02:00
2021-05-05 21:32:12 +02:00
_initializeBackDrop ( ) {
return new Backdrop ( {
isVisible : Boolean ( this . _config . backdrop ) ,
// 'static' option will be translated to true, and booleans will keep their value
isAnimated : this . _isAnimated ( )
} ) ;
}
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
config = { ... Default$5 ,
2021-05-05 21:32:12 +02:00
... Manipulator . getDataAttributes ( this . _element ) ,
2021-03-23 17:26:54 +01:00
... config
} ;
typeCheckConfig ( NAME$6 , config , DefaultType$5 ) ;
return config ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_showElement ( relatedTarget ) {
const isAnimated = this . _isAnimated ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const modalBody = SelectorEngine . findOne ( SELECTOR _MODAL _BODY , this . _dialog ) ;
2019-08-27 15:03:21 +02:00
2019-03-11 16:13:30 +01:00
if ( ! this . _element . parentNode || this . _element . parentNode . nodeType !== Node . ELEMENT _NODE ) {
// Don't move modal's DOM position
document . body . appendChild ( this . _element ) ;
}
this . _element . style . display = 'block' ;
this . _element . removeAttribute ( 'aria-hidden' ) ;
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 ;
if ( modalBody ) {
2019-08-27 15:03:21 +02:00
modalBody . scrollTop = 0 ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
if ( isAnimated ) {
2019-03-11 16:13:30 +01:00
reflow ( this . _element ) ;
}
2021-03-23 17:26:54 +01:00
this . _element . classList . add ( CLASS _NAME _SHOW$5 ) ;
2019-03-11 16:13:30 +01:00
if ( this . _config . focus ) {
this . _enforceFocus ( ) ;
}
2021-03-23 17:26:54 +01:00
const transitionComplete = ( ) => {
if ( this . _config . focus ) {
this . _element . focus ( ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
this . _isTransitioning = false ;
EventHandler . trigger ( this . _element , EVENT _SHOWN$3 , {
relatedTarget
2019-03-11 16:13:30 +01:00
} ) ;
} ;
2021-03-23 17:26:54 +01:00
if ( isAnimated ) {
const transitionDuration = getTransitionDurationFromElement ( this . _dialog ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( this . _dialog , 'transitionend' , transitionComplete ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( this . _dialog , transitionDuration ) ;
} else {
transitionComplete ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
_enforceFocus ( ) {
EventHandler . off ( document , EVENT _FOCUSIN$1 ) ; // guard against infinite focus loop
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
EventHandler . on ( document , EVENT _FOCUSIN$1 , event => {
if ( document !== event . target && this . _element !== event . target && ! this . _element . contains ( event . target ) ) {
this . _element . focus ( ) ;
2019-03-11 16:13:30 +01:00
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_setEscapeEvent ( ) {
2020-03-28 11:29:08 +01:00
if ( this . _isShown ) {
2021-05-05 21:32:12 +02:00
EventHandler . on ( this . _element , EVENT _KEYDOWN _DISMISS$1 , event => {
2021-03-23 17:26:54 +01:00
if ( this . _config . keyboard && event . key === ESCAPE _KEY$1 ) {
2020-03-28 11:29:08 +01:00
event . preventDefault ( ) ;
2021-03-23 17:26:54 +01:00
this . hide ( ) ;
} else if ( ! this . _config . keyboard && event . key === ESCAPE _KEY$1 ) {
this . _triggerBackdropTransition ( ) ;
2019-03-11 16:13:30 +01:00
}
} ) ;
2019-07-24 08:13:50 +02:00
} else {
2021-05-05 21:32:12 +02:00
EventHandler . off ( this . _element , EVENT _KEYDOWN _DISMISS$1 ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_setResizeEvent ( ) {
2019-03-11 16:13:30 +01:00
if ( this . _isShown ) {
2021-03-23 17:26:54 +01:00
EventHandler . on ( window , EVENT _RESIZE , ( ) => this . _adjustDialog ( ) ) ;
2019-03-11 16:13:30 +01:00
} else {
2020-03-28 11:29:08 +01:00
EventHandler . off ( window , EVENT _RESIZE ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_hideModal ( ) {
2019-03-11 16:13:30 +01:00
this . _element . style . display = 'none' ;
this . _element . setAttribute ( 'aria-hidden' , true ) ;
this . _element . removeAttribute ( 'aria-modal' ) ;
2020-06-14 00:40:28 +02:00
this . _element . removeAttribute ( 'role' ) ;
2019-03-11 16:13:30 +01:00
this . _isTransitioning = false ;
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 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _resetAdjustments ( ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
reset ( ) ;
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , EVENT _HIDDEN$3 ) ;
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_showBackdrop ( callback ) {
2021-05-05 21:32:12 +02:00
EventHandler . on ( this . _element , EVENT _CLICK _DISMISS$2 , event => {
if ( this . _ignoreBackdropClick ) {
this . _ignoreBackdropClick = false ;
return ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
if ( event . target !== event . currentTarget ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-05-05 21:32:12 +02:00
if ( this . _config . backdrop === true ) {
this . hide ( ) ;
} else if ( this . _config . backdrop === 'static' ) {
this . _triggerBackdropTransition ( ) ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
} ) ;
this . _backdrop . show ( callback ) ;
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 ( ) {
return this . _element . classList . contains ( CLASS _NAME _FADE$4 ) ;
}
2019-11-08 09:11:23 +01:00
2021-03-23 17:26:54 +01:00
_triggerBackdropTransition ( ) {
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE _PREVENTED ) ;
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
2021-03-23 17:26:54 +01:00
const isModalOverflowing = this . _element . scrollHeight > document . documentElement . clientHeight ;
2020-09-14 17:12:06 +02:00
2020-11-23 14:17:16 +01:00
if ( ! isModalOverflowing ) {
this . _element . style . overflowY = 'hidden' ;
}
2020-09-14 17:12:06 +02:00
2020-11-23 14:17:16 +01:00
this . _element . classList . add ( CLASS _NAME _STATIC ) ;
2019-11-08 09:11:23 +01:00
2021-03-23 17:26:54 +01:00
const modalTransitionDuration = getTransitionDurationFromElement ( this . _dialog ) ;
2021-02-10 17:14:51 +01:00
EventHandler . off ( this . _element , 'transitionend' ) ;
2021-03-23 17:26:54 +01:00
EventHandler . one ( this . _element , 'transitionend' , ( ) => {
this . _element . classList . remove ( CLASS _NAME _STATIC ) ;
2020-09-14 17:12:06 +02:00
2020-11-23 14:17:16 +01:00
if ( ! isModalOverflowing ) {
2021-03-23 17:26:54 +01:00
EventHandler . one ( this . _element , 'transitionend' , ( ) => {
this . _element . style . overflowY = '' ;
2020-11-23 14:17:16 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
emulateTransitionEnd ( this . _element , modalTransitionDuration ) ;
2020-11-23 14:17:16 +01:00
}
} ) ;
emulateTransitionEnd ( this . _element , modalTransitionDuration ) ;
2019-11-08 09:11:23 +01:00
2020-11-23 14:17:16 +01:00
this . _element . focus ( ) ;
2019-03-11 16:13:30 +01:00
} // ----------------------------------------------------------------------
// the following methods are used to handle overflowing modals
// ----------------------------------------------------------------------
2021-03-23 17:26:54 +01:00
_adjustDialog ( ) {
const isModalOverflowing = this . _element . scrollHeight > document . documentElement . clientHeight ;
2021-05-05 21:32:12 +02:00
const scrollbarWidth = getWidth ( ) ;
const isBodyOverflowing = scrollbarWidth > 0 ;
2021-03-23 17:26:54 +01:00
2021-05-05 21:32:12 +02:00
if ( ! isBodyOverflowing && isModalOverflowing && ! isRTL ( ) || isBodyOverflowing && ! isModalOverflowing && isRTL ( ) ) {
this . _element . style . paddingLeft = ` ${ scrollbarWidth } px ` ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
if ( isBodyOverflowing && ! isModalOverflowing && ! isRTL ( ) || ! isBodyOverflowing && isModalOverflowing && isRTL ( ) ) {
this . _element . style . paddingRight = ` ${ scrollbarWidth } px ` ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_resetAdjustments ( ) {
2019-03-11 16:13:30 +01:00
this . _element . style . paddingLeft = '' ;
this . _element . style . paddingRight = '' ;
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config , relatedTarget ) {
return this . each ( function ( ) {
2021-05-05 21:32:12 +02:00
const data = Modal . getInstance ( this ) || new Modal ( this , typeof config === 'object' ? config : { } ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
if ( typeof config !== 'string' ) {
return ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
if ( typeof data [ config ] === 'undefined' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
data [ config ] ( relatedTarget ) ;
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
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 ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
if ( [ 'A' , 'AREA' ] . includes ( this . tagName ) ) {
2019-03-11 16:13:30 +01:00
event . preventDefault ( ) ;
}
2021-03-23 17:26:54 +01:00
EventHandler . one ( target , EVENT _SHOW$3 , showEvent => {
2019-03-11 16:13:30 +01:00
if ( showEvent . defaultPrevented ) {
// only register focus restorer if modal will actually get shown
return ;
}
2021-03-23 17:26:54 +01:00
EventHandler . one ( target , EVENT _HIDDEN$3 , ( ) => {
if ( isVisible ( this ) ) {
this . focus ( ) ;
2019-03-11 16:13:30 +01:00
}
} ) ;
} ) ;
2021-05-05 21:32:12 +02:00
const data = Modal . getInstance ( target ) || new Modal ( target ) ;
2021-02-10 17:14:51 +01:00
data . toggle ( this ) ;
2019-03-11 16:13:30 +01:00
} ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-03-23 17:26:54 +01:00
* add . Modal to jQuery only if jQuery is present
* /
defineJQueryPlugin ( NAME$6 , Modal ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : offcanvas . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/master/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
const NAME$5 = 'offcanvas' ;
const DATA _KEY$5 = 'bs.offcanvas' ;
const EVENT _KEY$5 = ` . ${ DATA _KEY$5 } ` ;
const DATA _API _KEY$2 = '.data-api' ;
const EVENT _LOAD _DATA _API$1 = ` load ${ EVENT _KEY$5 } ${ DATA _API _KEY$2 } ` ;
const ESCAPE _KEY = 'Escape' ;
const Default$4 = {
backdrop : true ,
keyboard : true ,
scroll : false
} ;
const DefaultType$4 = {
backdrop : 'boolean' ,
keyboard : 'boolean' ,
scroll : 'boolean'
} ;
const CLASS _NAME _SHOW$4 = 'show' ;
const OPEN _SELECTOR = '.offcanvas.show' ;
const EVENT _SHOW$2 = ` show ${ EVENT _KEY$5 } ` ;
const EVENT _SHOWN$2 = ` shown ${ EVENT _KEY$5 } ` ;
const EVENT _HIDE$2 = ` hide ${ EVENT _KEY$5 } ` ;
const EVENT _HIDDEN$2 = ` hidden ${ EVENT _KEY$5 } ` ;
const EVENT _FOCUSIN = ` focusin ${ EVENT _KEY$5 } ` ;
const EVENT _CLICK _DATA _API$1 = ` click ${ EVENT _KEY$5 } ${ DATA _API _KEY$2 } ` ;
const EVENT _CLICK _DISMISS$1 = ` click.dismiss ${ EVENT _KEY$5 } ` ;
2021-05-05 21:32:12 +02:00
const EVENT _KEYDOWN _DISMISS = ` keydown.dismiss ${ EVENT _KEY$5 } ` ;
2021-03-23 17:26:54 +01:00
const SELECTOR _DATA _DISMISS$1 = '[data-bs-dismiss="offcanvas"]' ;
const SELECTOR _DATA _TOGGLE$1 = '[data-bs-toggle="offcanvas"]' ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
class Offcanvas extends BaseComponent {
constructor ( element , config ) {
super ( element ) ;
this . _config = this . _getConfig ( config ) ;
this . _isShown = false ;
2021-05-05 21:32:12 +02:00
this . _backdrop = this . _initializeBackDrop ( ) ;
2021-03-23 17:26:54 +01:00
this . _addEventListeners ( ) ;
} // Getters
static get Default ( ) {
return Default$4 ;
}
static get DATA _KEY ( ) {
return DATA _KEY$5 ;
} // Public
toggle ( relatedTarget ) {
return this . _isShown ? this . hide ( ) : this . show ( relatedTarget ) ;
}
show ( relatedTarget ) {
if ( this . _isShown ) {
return ;
}
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$2 , {
relatedTarget
} ) ;
if ( showEvent . defaultPrevented ) {
return ;
}
this . _isShown = true ;
this . _element . style . visibility = 'visible' ;
2021-05-05 21:32:12 +02:00
this . _backdrop . show ( ) ;
2021-03-23 17:26:54 +01:00
if ( ! this . _config . scroll ) {
hide ( ) ;
2021-05-05 21:32:12 +02:00
this . _enforceFocusOnElement ( this . _element ) ;
}
2021-03-23 17:26:54 +01:00
this . _element . removeAttribute ( 'aria-hidden' ) ;
this . _element . setAttribute ( 'aria-modal' , true ) ;
this . _element . setAttribute ( 'role' , 'dialog' ) ;
this . _element . classList . add ( CLASS _NAME _SHOW$4 ) ;
const completeCallBack = ( ) => {
EventHandler . trigger ( this . _element , EVENT _SHOWN$2 , {
relatedTarget
} ) ;
} ;
2021-05-05 21:32:12 +02:00
const transitionDuration = getTransitionDurationFromElement ( this . _element ) ;
EventHandler . one ( this . _element , 'transitionend' , completeCallBack ) ;
emulateTransitionEnd ( this . _element , transitionDuration ) ;
2021-03-23 17:26:54 +01:00
}
hide ( ) {
if ( ! this . _isShown ) {
return ;
}
const hideEvent = EventHandler . trigger ( this . _element , EVENT _HIDE$2 ) ;
if ( hideEvent . defaultPrevented ) {
return ;
}
EventHandler . off ( document , EVENT _FOCUSIN ) ;
this . _element . blur ( ) ;
this . _isShown = false ;
this . _element . classList . remove ( CLASS _NAME _SHOW$4 ) ;
2021-05-05 21:32:12 +02:00
this . _backdrop . hide ( ) ;
2021-03-23 17:26:54 +01:00
const completeCallback = ( ) => {
this . _element . setAttribute ( 'aria-hidden' , true ) ;
this . _element . removeAttribute ( 'aria-modal' ) ;
this . _element . removeAttribute ( 'role' ) ;
this . _element . style . visibility = 'hidden' ;
if ( ! this . _config . scroll ) {
reset ( ) ;
}
EventHandler . trigger ( this . _element , EVENT _HIDDEN$2 ) ;
} ;
2021-05-05 21:32:12 +02:00
const transitionDuration = getTransitionDurationFromElement ( this . _element ) ;
EventHandler . one ( this . _element , 'transitionend' , completeCallback ) ;
emulateTransitionEnd ( this . _element , transitionDuration ) ;
}
dispose ( ) {
this . _backdrop . dispose ( ) ;
super . dispose ( ) ;
EventHandler . off ( document , EVENT _FOCUSIN ) ;
this . _config = null ;
this . _backdrop = null ;
2021-03-23 17:26:54 +01:00
} // Private
_getConfig ( config ) {
config = { ... Default$4 ,
... Manipulator . getDataAttributes ( this . _element ) ,
... ( typeof config === 'object' ? config : { } )
} ;
typeCheckConfig ( NAME$5 , config , DefaultType$4 ) ;
return config ;
}
2021-05-05 21:32:12 +02:00
_initializeBackDrop ( ) {
return new Backdrop ( {
isVisible : this . _config . backdrop ,
isAnimated : true ,
rootElement : this . _element . parentNode ,
clickCallback : ( ) => this . hide ( )
} ) ;
}
2021-03-23 17:26:54 +01:00
_enforceFocusOnElement ( element ) {
EventHandler . off ( document , EVENT _FOCUSIN ) ; // guard against infinite focus loop
EventHandler . on ( document , EVENT _FOCUSIN , event => {
if ( document !== event . target && element !== event . target && ! element . contains ( event . target ) ) {
element . focus ( ) ;
}
} ) ;
element . focus ( ) ;
}
_addEventListeners ( ) {
EventHandler . on ( this . _element , EVENT _CLICK _DISMISS$1 , SELECTOR _DATA _DISMISS$1 , ( ) => this . hide ( ) ) ;
2021-05-05 21:32:12 +02:00
EventHandler . on ( this . _element , EVENT _KEYDOWN _DISMISS , event => {
2021-03-23 17:26:54 +01:00
if ( this . _config . keyboard && event . key === ESCAPE _KEY ) {
this . hide ( ) ;
}
} ) ;
} // Static
static jQueryInterface ( config ) {
return this . each ( function ( ) {
const data = Data . get ( this , DATA _KEY$5 ) || new Offcanvas ( this , typeof config === 'object' ? config : { } ) ;
if ( typeof config !== 'string' ) {
return ;
}
if ( data [ config ] === undefined || config . startsWith ( '_' ) || config === 'constructor' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
}
data [ config ] ( this ) ;
} ) ;
}
}
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
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 ;
}
EventHandler . one ( target , EVENT _HIDDEN$2 , ( ) => {
// 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
2021-05-05 21:32:12 +02:00
const allReadyOpen = SelectorEngine . findOne ( OPEN _SELECTOR ) ;
2021-03-23 17:26:54 +01:00
if ( allReadyOpen && allReadyOpen !== target ) {
2021-05-05 21:32:12 +02:00
Offcanvas . getInstance ( allReadyOpen ) . hide ( ) ;
2021-03-23 17:26:54 +01:00
}
const data = Data . get ( target , DATA _KEY$5 ) || new Offcanvas ( target ) ;
data . toggle ( this ) ;
} ) ;
EventHandler . on ( window , EVENT _LOAD _DATA _API$1 , ( ) => {
SelectorEngine . find ( OPEN _SELECTOR ) . forEach ( el => ( Data . get ( el , DATA _KEY$5 ) || new Offcanvas ( el ) ) . show ( ) ) ;
} ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2019-03-11 16:13:30 +01:00
* /
2021-03-23 17:26:54 +01:00
defineJQueryPlugin ( NAME$5 , Offcanvas ) ;
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : util / sanitizer . js
2020-06-16 20:50:01 +02:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
2019-03-11 16:13:30 +01:00
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const uriAttrs = new Set ( [ 'background' , 'cite' , 'href' , 'itemtype' , 'longdesc' , 'poster' , 'src' , 'xlink:href' ] ) ;
const ARIA _ATTRIBUTE _PATTERN = /^aria-[\w-]*$/i ;
2019-03-11 16:13:30 +01:00
/ * *
* A pattern that recognizes a commonly useful subset of URLs that are safe .
*
* Shoutout to Angular 7 https : //github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
* /
2021-03-23 17:26:54 +01:00
const SAFE _URL _PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i ;
2019-03-11 16:13:30 +01:00
/ * *
* A pattern that matches safe data URLs . Only matches image , video and audio types .
*
* Shoutout to Angular 7 https : //github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
* /
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-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const allowedAttribute = ( attr , allowedAttributeList ) => {
const attrName = attr . nodeName . toLowerCase ( ) ;
2019-03-11 16:13:30 +01:00
2020-11-23 14:17:16 +01:00
if ( allowedAttributeList . includes ( attrName ) ) {
if ( uriAttrs . has ( attrName ) ) {
2021-02-10 17:14:51 +01:00
return Boolean ( SAFE _URL _PATTERN . test ( attr . nodeValue ) || DATA _URL _PATTERN . test ( attr . nodeValue ) ) ;
2019-03-11 16:13:30 +01:00
}
return true ;
}
2021-03-23 17:26:54 +01:00
const regExp = allowedAttributeList . filter ( attrRegex => attrRegex instanceof RegExp ) ; // Check if a regular expression validates the attribute.
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
for ( let i = 0 , len = regExp . length ; i < len ; i ++ ) {
2021-02-10 17:14:51 +01:00
if ( regExp [ i ] . test ( attrName ) ) {
2019-03-11 16:13:30 +01:00
return true ;
}
}
return false ;
} ;
2021-03-23 17:26:54 +01:00
const DefaultAllowlist = {
2019-03-11 16:13:30 +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-03-11 16:13:30 +01:00
li : [ ] ,
ol : [ ] ,
p : [ ] ,
pre : [ ] ,
s : [ ] ,
small : [ ] ,
span : [ ] ,
sub : [ ] ,
sup : [ ] ,
strong : [ ] ,
u : [ ] ,
ul : [ ]
} ;
2020-09-14 17:12:06 +02:00
function sanitizeHtml ( unsafeHtml , allowList , sanitizeFn ) {
2019-03-11 16:13:30 +01:00
if ( ! unsafeHtml . length ) {
return unsafeHtml ;
}
if ( sanitizeFn && typeof sanitizeFn === 'function' ) {
return sanitizeFn ( unsafeHtml ) ;
}
2021-03-23 17:26:54 +01:00
const domParser = new window . DOMParser ( ) ;
const createdDocument = domParser . parseFromString ( unsafeHtml , 'text/html' ) ;
const allowlistKeys = Object . keys ( allowList ) ;
const elements = [ ] . concat ( ... createdDocument . body . querySelectorAll ( '*' ) ) ;
2020-03-28 11:29:08 +01:00
2021-03-23 17:26:54 +01:00
for ( let i = 0 , len = elements . length ; i < len ; i ++ ) {
const el = elements [ i ] ;
const elName = el . nodeName . toLowerCase ( ) ;
2019-03-11 16:13:30 +01:00
2020-11-23 14:17:16 +01:00
if ( ! allowlistKeys . includes ( elName ) ) {
2019-03-11 16:13:30 +01:00
el . parentNode . removeChild ( el ) ;
2021-03-23 17:26:54 +01:00
continue ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
const attributeList = [ ] . concat ( ... el . attributes ) ;
const allowedAttributes = [ ] . concat ( allowList [ '*' ] || [ ] , allowList [ elName ] || [ ] ) ;
attributeList . forEach ( attr => {
2020-09-14 17:12:06 +02:00
if ( ! allowedAttribute ( attr , allowedAttributes ) ) {
2019-03-11 16:13:30 +01:00
el . removeAttribute ( attr . nodeName ) ;
}
} ) ;
}
return createdDocument . body . innerHTML ;
}
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : tooltip . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const NAME$4 = 'tooltip' ;
const DATA _KEY$4 = 'bs.tooltip' ;
const EVENT _KEY$4 = ` . ${ DATA _KEY$4 } ` ;
const CLASS _PREFIX$1 = 'bs-tooltip' ;
const BSCLS _PREFIX _REGEX$1 = new RegExp ( ` (^| \\ s) ${ CLASS _PREFIX$1 } \\ S+ ` , 'g' ) ;
const DISALLOWED _ATTRIBUTES = new Set ( [ 'sanitize' , 'allowList' , 'sanitizeFn' ] ) ;
const DefaultType$3 = {
2019-03-11 16:13:30 +01:00
animation : 'boolean' ,
template : 'string' ,
title : '(string|element|function)' ,
trigger : 'string' ,
delay : '(number|object)' ,
html : 'boolean' ,
selector : '(string|boolean)' ,
placement : '(string|function)' ,
2021-02-10 17:14:51 +01:00
offset : '(array|string|function)' ,
2019-03-11 16:13:30 +01:00
container : '(string|element|boolean)' ,
2021-02-10 17:14:51 +01:00
fallbackPlacements : 'array' ,
2019-03-11 16:13:30 +01:00
boundary : '(string|element)' ,
2020-12-03 15:18:59 +01:00
customClass : '(string|function)' ,
2019-03-11 16:13:30 +01:00
sanitize : 'boolean' ,
sanitizeFn : '(null|function)' ,
2020-09-14 17:12:06 +02:00
allowList : 'object' ,
2021-02-10 17:14:51 +01:00
popperConfig : '(null|object|function)'
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const AttachmentMap = {
2019-03-11 16:13:30 +01:00
AUTO : 'auto' ,
TOP : 'top' ,
2021-03-23 17:26:54 +01:00
RIGHT : isRTL ( ) ? 'left' : 'right' ,
2019-03-11 16:13:30 +01:00
BOTTOM : 'bottom' ,
2021-03-23 17:26:54 +01:00
LEFT : isRTL ( ) ? 'right' : 'left'
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const Default$3 = {
2019-03-11 16:13:30 +01:00
animation : true ,
2020-12-03 15:18:59 +01:00
template : '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>' ,
2019-03-11 16:13:30 +01:00
trigger : 'hover focus' ,
title : '' ,
delay : 0 ,
html : false ,
selector : false ,
placement : 'top' ,
2021-02-10 17:14:51 +01:00
offset : [ 0 , 0 ] ,
2019-03-11 16:13:30 +01:00
container : false ,
2021-02-10 17:14:51 +01:00
fallbackPlacements : [ 'top' , 'right' , 'bottom' , 'left' ] ,
2020-12-07 16:50:24 +01:00
boundary : 'clippingParents' ,
2020-12-03 15:18:59 +01:00
customClass : '' ,
2019-03-11 16:13:30 +01:00
sanitize : true ,
sanitizeFn : null ,
2020-09-14 17:12:06 +02:00
allowList : DefaultAllowlist ,
2019-08-27 15:03:21 +02:00
popperConfig : null
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const Event$2 = {
HIDE : ` hide ${ EVENT _KEY$4 } ` ,
HIDDEN : ` hidden ${ EVENT _KEY$4 } ` ,
SHOW : ` show ${ EVENT _KEY$4 } ` ,
SHOWN : ` shown ${ EVENT _KEY$4 } ` ,
INSERTED : ` inserted ${ EVENT _KEY$4 } ` ,
CLICK : ` click ${ EVENT _KEY$4 } ` ,
FOCUSIN : ` focusin ${ EVENT _KEY$4 } ` ,
FOCUSOUT : ` focusout ${ EVENT _KEY$4 } ` ,
MOUSEENTER : ` mouseenter ${ EVENT _KEY$4 } ` ,
MOUSELEAVE : ` mouseleave ${ EVENT _KEY$4 } `
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const CLASS _NAME _FADE$3 = 'fade' ;
const CLASS _NAME _MODAL = 'modal' ;
const CLASS _NAME _SHOW$3 = 'show' ;
const HOVER _STATE _SHOW = 'show' ;
const HOVER _STATE _OUT = 'out' ;
const SELECTOR _TOOLTIP _INNER = '.tooltip-inner' ;
const TRIGGER _HOVER = 'hover' ;
const TRIGGER _FOCUS = 'focus' ;
const TRIGGER _CLICK = 'click' ;
const TRIGGER _MANUAL = 'manual' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Tooltip extends BaseComponent {
constructor ( element , config ) {
2019-03-11 16:13:30 +01:00
if ( typeof Popper === '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
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
super ( element ) ; // private
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _isEnabled = true ;
this . _timeout = 0 ;
this . _hoverState = '' ;
this . _activeTrigger = { } ;
this . _popper = null ; // Protected
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . config = this . _getConfig ( config ) ;
this . tip = null ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _setListeners ( ) ;
2019-03-11 16:13:30 +01:00
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
return Default$3 ;
}
static get NAME ( ) {
return NAME$4 ;
}
static get DATA _KEY ( ) {
return DATA _KEY$4 ;
}
static get Event ( ) {
return Event$2 ;
}
static get EVENT _KEY ( ) {
return EVENT _KEY$4 ;
}
static get DefaultType ( ) {
return DefaultType$3 ;
} // Public
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
enable ( ) {
2019-03-11 16:13:30 +01:00
this . _isEnabled = true ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
disable ( ) {
2019-03-11 16:13:30 +01:00
this . _isEnabled = false ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
toggleEnabled ( ) {
2019-03-11 16:13:30 +01:00
this . _isEnabled = ! this . _isEnabled ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
toggle ( event ) {
2019-03-11 16:13:30 +01:00
if ( ! this . _isEnabled ) {
return ;
}
if ( event ) {
2021-03-23 17:26:54 +01:00
const context = this . _initializeOnDelegatedTarget ( event ) ;
2019-03-11 16:13:30 +01:00
context . _activeTrigger . click = ! context . _activeTrigger . click ;
if ( context . _isWithActiveTrigger ( ) ) {
context . _enter ( null , context ) ;
} else {
context . _leave ( null , context ) ;
}
} else {
2021-03-23 17:26:54 +01:00
if ( this . getTipElement ( ) . classList . contains ( CLASS _NAME _SHOW$3 ) ) {
2019-03-11 16:13:30 +01:00
this . _leave ( null , this ) ;
return ;
}
this . _enter ( null , this ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2019-03-11 16:13:30 +01:00
clearTimeout ( this . _timeout ) ;
2021-03-23 17:26:54 +01:00
EventHandler . off ( this . _element . closest ( ` . ${ CLASS _NAME _MODAL } ` ) , 'hide.bs.modal' , this . _hideModalHandler ) ;
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
if ( this . tip && this . tip . parentNode ) {
2019-03-11 16:13:30 +01:00
this . tip . parentNode . removeChild ( this . tip ) ;
}
this . _isEnabled = null ;
this . _timeout = null ;
this . _hoverState = null ;
this . _activeTrigger = null ;
2019-08-27 15:03:21 +02:00
if ( this . _popper ) {
2019-03-11 16:13:30 +01:00
this . _popper . destroy ( ) ;
}
this . _popper = null ;
this . config = null ;
this . tip = null ;
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' ) {
2019-03-11 16:13:30 +01:00
throw new Error ( 'Please use show on visible elements' ) ;
}
2021-02-10 17:14:51 +01:00
if ( ! ( this . isWithContent ( ) && this . _isEnabled ) ) {
return ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const showEvent = EventHandler . trigger ( this . _element , this . constructor . Event . SHOW ) ;
const shadowRoot = findShadowRoot ( this . _element ) ;
const isInTheDom = shadowRoot === null ? this . _element . ownerDocument . documentElement . contains ( this . _element ) : shadowRoot . contains ( this . _element ) ;
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
if ( showEvent . defaultPrevented || ! isInTheDom ) {
return ;
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
const tip = this . getTipElement ( ) ;
const tipId = getUID ( this . constructor . NAME ) ;
2021-02-10 17:14:51 +01:00
tip . setAttribute ( 'id' , tipId ) ;
2020-12-03 15:18:59 +01:00
2021-02-10 17:14:51 +01:00
this . _element . setAttribute ( 'aria-describedby' , tipId ) ;
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
this . setContent ( ) ;
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
if ( this . config . animation ) {
2021-03-23 17:26:54 +01:00
tip . classList . add ( CLASS _NAME _FADE$3 ) ;
2021-02-10 17:14:51 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const placement = typeof this . config . placement === 'function' ? this . config . placement . call ( this , tip , this . _element ) : this . config . placement ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const attachment = this . _getAttachment ( placement ) ;
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
this . _addAttachmentClass ( attachment ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const container = this . _getContainer ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
Data . set ( tip , this . constructor . DATA _KEY , this ) ;
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
if ( ! this . _element . ownerDocument . documentElement . contains ( this . tip ) ) {
container . appendChild ( tip ) ;
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , this . constructor . Event . INSERTED ) ;
}
if ( this . _popper ) {
this . _popper . update ( ) ;
} else {
this . _popper = Popper . createPopper ( this . _element , tip , this . _getPopperConfig ( attachment ) ) ;
2021-02-10 17:14:51 +01:00
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
tip . classList . add ( CLASS _NAME _SHOW$3 ) ;
const customClass = typeof this . config . customClass === 'function' ? this . config . customClass ( ) : this . config . customClass ;
2020-12-03 15:18:59 +01:00
2021-02-10 17:14:51 +01:00
if ( customClass ) {
2021-03-23 17:26:54 +01:00
tip . classList . add ( ... customClass . split ( ' ' ) ) ;
2021-02-10 17:14:51 +01:00
} // If this is a touch-enabled device we add extra
// 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
2020-03-28 11:29:08 +01:00
2021-02-10 17:14:51 +01:00
if ( 'ontouchstart' in document . documentElement ) {
2021-03-23 17:26:54 +01:00
[ ] . concat ( ... document . body . children ) . forEach ( element => {
2021-05-05 21:32:12 +02:00
EventHandler . on ( element , 'mouseover' , noop ) ;
2021-02-10 17:14:51 +01:00
} ) ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
const prevHoverState = this . _hoverState ;
this . _hoverState = null ;
EventHandler . trigger ( this . _element , this . constructor . Event . SHOWN ) ;
2019-03-11 16:13:30 +01:00
2021-02-10 17:14:51 +01:00
if ( prevHoverState === HOVER _STATE _OUT ) {
2021-03-23 17:26:54 +01:00
this . _leave ( null , this ) ;
2019-03-11 16:13:30 +01:00
}
2021-02-10 17:14:51 +01:00
} ;
2021-03-23 17:26:54 +01:00
if ( this . tip . classList . contains ( CLASS _NAME _FADE$3 ) ) {
const transitionDuration = getTransitionDurationFromElement ( this . tip ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( this . tip , 'transitionend' , complete ) ;
emulateTransitionEnd ( this . tip , transitionDuration ) ;
} else {
complete ( ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
hide ( ) {
2020-09-29 17:33:00 +02:00
if ( ! this . _popper ) {
return ;
}
2021-03-23 17:26:54 +01:00
const tip = this . getTipElement ( ) ;
const complete = ( ) => {
if ( this . _isWithActiveTrigger ( ) ) {
return ;
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
if ( this . _hoverState !== HOVER _STATE _SHOW && tip . parentNode ) {
2019-03-11 16:13:30 +01:00
tip . parentNode . removeChild ( tip ) ;
}
2021-03-23 17:26:54 +01:00
this . _cleanTipClass ( ) ;
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
this . _element . removeAttribute ( 'aria-describedby' ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , this . constructor . Event . HIDDEN ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( this . _popper ) {
this . _popper . destroy ( ) ;
2020-12-07 16:50:24 +01:00
2021-03-23 17:26:54 +01:00
this . _popper = null ;
2020-12-07 16:50:24 +01:00
}
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const hideEvent = EventHandler . trigger ( this . _element , this . constructor . Event . HIDE ) ;
2019-03-11 16:13:30 +01:00
if ( hideEvent . defaultPrevented ) {
return ;
}
2021-03-23 17:26:54 +01:00
tip . classList . remove ( CLASS _NAME _SHOW$3 ) ; // If this is a touch-enabled device we remove the extra
2019-03-11 16:13:30 +01:00
// empty mouseover listeners we added for iOS support
if ( 'ontouchstart' in document . documentElement ) {
2021-03-23 17:26:54 +01:00
[ ] . concat ( ... document . body . children ) . forEach ( element => EventHandler . off ( element , 'mouseover' , noop ) ) ;
2019-03-11 16:13:30 +01:00
}
2020-03-28 11:29:08 +01:00
this . _activeTrigger [ TRIGGER _CLICK ] = false ;
this . _activeTrigger [ TRIGGER _FOCUS ] = false ;
this . _activeTrigger [ TRIGGER _HOVER ] = false ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( this . tip . classList . contains ( CLASS _NAME _FADE$3 ) ) {
const transitionDuration = getTransitionDurationFromElement ( tip ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( tip , 'transitionend' , complete ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( tip , transitionDuration ) ;
} else {
complete ( ) ;
}
this . _hoverState = '' ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
update ( ) {
2019-03-11 16:13:30 +01:00
if ( this . _popper !== null ) {
2020-12-07 16:50:24 +01:00
this . _popper . update ( ) ;
2019-03-11 16:13:30 +01:00
}
} // Protected
2021-03-23 17:26:54 +01:00
isWithContent ( ) {
2019-03-11 16:13:30 +01:00
return Boolean ( this . getTitle ( ) ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
getTipElement ( ) {
2019-03-11 16:13:30 +01:00
if ( this . tip ) {
return this . tip ;
}
2021-03-23 17:26:54 +01:00
const element = document . createElement ( 'div' ) ;
2019-03-11 16:13:30 +01:00
element . innerHTML = this . config . template ;
this . tip = element . children [ 0 ] ;
return this . tip ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
setContent ( ) {
const tip = this . getTipElement ( ) ;
2020-03-28 11:29:08 +01:00
this . setElementContent ( SelectorEngine . findOne ( SELECTOR _TOOLTIP _INNER , tip ) , this . getTitle ( ) ) ;
2021-03-23 17:26:54 +01:00
tip . classList . remove ( CLASS _NAME _FADE$3 , CLASS _NAME _SHOW$3 ) ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
setElementContent ( element , content ) {
2019-03-11 16:13:30 +01:00
if ( element === null ) {
return ;
}
2019-07-24 08:13:50 +02:00
if ( typeof content === 'object' && isElement ( content ) ) {
2019-03-11 16:13:30 +01:00
if ( content . jquery ) {
content = content [ 0 ] ;
} // content is a DOM node or a jQuery
if ( this . config . html ) {
if ( content . parentNode !== element ) {
element . innerHTML = '' ;
element . appendChild ( content ) ;
}
} else {
2020-05-13 20:53:43 +02:00
element . textContent = content . textContent ;
2019-03-11 16:13:30 +01:00
}
return ;
}
if ( this . config . html ) {
if ( this . config . sanitize ) {
2020-09-14 17:12:06 +02:00
content = sanitizeHtml ( content , this . config . allowList , this . config . sanitizeFn ) ;
2019-03-11 16:13:30 +01:00
}
element . innerHTML = content ;
} else {
2020-05-13 20:53:43 +02:00
element . textContent = content ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
getTitle ( ) {
let title = this . _element . getAttribute ( 'data-bs-original-title' ) ;
2019-03-11 16:13:30 +01:00
if ( ! title ) {
2020-12-03 15:18:59 +01:00
title = typeof this . config . title === 'function' ? this . config . title . call ( this . _element ) : this . config . title ;
2019-03-11 16:13:30 +01:00
}
return title ;
2021-03-23 17:26:54 +01:00
}
2020-12-03 14:08:31 +01:00
2021-03-23 17:26:54 +01:00
updateAttachment ( attachment ) {
2020-12-03 14:08:31 +01:00
if ( attachment === 'right' ) {
return 'end' ;
}
if ( attachment === 'left' ) {
return 'start' ;
}
return attachment ;
2019-03-11 16:13:30 +01:00
} // Private
2021-03-23 17:26:54 +01:00
_initializeOnDelegatedTarget ( event , context ) {
const dataKey = this . constructor . DATA _KEY ;
context = context || Data . get ( event . delegateTarget , dataKey ) ;
2021-02-10 17:14:51 +01:00
if ( ! context ) {
context = new this . constructor ( event . delegateTarget , this . _getDelegateConfig ( ) ) ;
2021-03-23 17:26:54 +01:00
Data . set ( event . delegateTarget , dataKey , context ) ;
2021-02-10 17:14:51 +01:00
}
return context ;
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
} = this . config ;
2021-02-10 17:14:51 +01:00
if ( typeof offset === 'string' ) {
2021-03-23 17:26:54 +01:00
return offset . split ( ',' ) . map ( val => Number . parseInt ( val , 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
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 : {
fallbackPlacements : this . config . fallbackPlacements
}
} , {
name : 'offset' ,
options : {
offset : this . _getOffset ( )
}
} , {
2020-12-07 16:50:24 +01:00
name : 'preventOverflow' ,
options : {
2021-02-10 17:14:51 +01: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
} , {
name : 'onChange' ,
enabled : true ,
phase : 'afterWrite' ,
2021-03-23 17:26:54 +01:00
fn : data => this . _handlePopperPlacementChange ( data )
2020-12-07 16:50:24 +01:00
} ] ,
2021-03-23 17:26:54 +01:00
onFirstUpdate : data => {
2020-12-07 16:50:24 +01:00
if ( data . options . placement !== data . placement ) {
2021-03-23 17:26:54 +01:00
this . _handlePopperPlacementChange ( data ) ;
2019-08-27 15:03:21 +02:00
}
}
} ;
2021-03-23 17:26:54 +01:00
return { ... defaultBsPopperConfig ,
... ( typeof this . config . popperConfig === 'function' ? this . config . popperConfig ( defaultBsPopperConfig ) : this . config . popperConfig )
} ;
}
2019-08-27 15:03:21 +02:00
2021-03-23 17:26:54 +01:00
_addAttachmentClass ( attachment ) {
this . getTipElement ( ) . classList . add ( ` ${ CLASS _PREFIX$1 } - ${ this . updateAttachment ( attachment ) } ` ) ;
}
2019-07-24 08:13:50 +02:00
2021-03-23 17:26:54 +01:00
_getContainer ( ) {
2019-03-11 16:13:30 +01:00
if ( this . config . container === false ) {
return document . body ;
}
if ( isElement ( this . config . container ) ) {
return this . config . container ;
}
return SelectorEngine . findOne ( this . config . container ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getAttachment ( placement ) {
2020-03-28 11:29:08 +01:00
return AttachmentMap [ placement . toUpperCase ( ) ] ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
_setListeners ( ) {
const triggers = this . config . trigger . split ( ' ' ) ;
triggers . forEach ( trigger => {
2019-03-11 16:13:30 +01:00
if ( trigger === 'click' ) {
2021-03-23 17:26:54 +01:00
EventHandler . on ( this . _element , this . constructor . Event . CLICK , this . config . selector , event => this . toggle ( event ) ) ;
2020-03-28 11:29:08 +01:00
} else if ( trigger !== TRIGGER _MANUAL ) {
2021-03-23 17:26:54 +01:00
const eventIn = trigger === TRIGGER _HOVER ? this . constructor . Event . MOUSEENTER : this . constructor . Event . FOCUSIN ;
const eventOut = trigger === TRIGGER _HOVER ? this . constructor . Event . MOUSELEAVE : this . constructor . Event . FOCUSOUT ;
EventHandler . on ( this . _element , eventIn , this . config . selector , event => this . _enter ( event ) ) ;
EventHandler . on ( this . _element , eventOut , this . config . selector , event => this . _leave ( event ) ) ;
2019-03-11 16:13:30 +01:00
}
} ) ;
2019-07-12 23:56:26 +02:00
2021-03-23 17:26:54 +01:00
this . _hideModalHandler = ( ) => {
if ( this . _element ) {
this . hide ( ) ;
2019-03-11 16:13:30 +01:00
}
2019-07-12 23:56:26 +02:00
} ;
2021-03-23 17:26:54 +01:00
EventHandler . on ( this . _element . closest ( ` . ${ CLASS _NAME _MODAL } ` ) , 'hide.bs.modal' , this . _hideModalHandler ) ;
2019-03-11 16:13:30 +01:00
if ( this . config . selector ) {
2021-03-23 17:26:54 +01:00
this . config = { ... this . config ,
2019-03-11 16:13:30 +01:00
trigger : 'manual' ,
selector : ''
2021-03-23 17:26:54 +01:00
} ;
2019-03-11 16:13:30 +01:00
} else {
this . _fixTitle ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_fixTitle ( ) {
const title = this . _element . getAttribute ( 'title' ) ;
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
const originalTitleType = typeof this . _element . getAttribute ( 'data-bs-original-title' ) ;
2019-03-11 16:13:30 +01:00
2020-11-23 14:17:16 +01:00
if ( title || originalTitleType !== 'string' ) {
2020-12-03 15:18:59 +01:00
this . _element . setAttribute ( 'data-bs-original-title' , title || '' ) ;
if ( title && ! this . _element . getAttribute ( 'aria-label' ) && ! this . _element . textContent ) {
this . _element . setAttribute ( 'aria-label' , title ) ;
}
this . _element . setAttribute ( 'title' , '' ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_enter ( event , context ) {
2021-02-10 17:14:51 +01:00
context = this . _initializeOnDelegatedTarget ( event , context ) ;
2019-03-11 16:13:30 +01:00
if ( event ) {
2020-03-28 11:29:08 +01:00
context . _activeTrigger [ event . type === 'focusin' ? TRIGGER _FOCUS : TRIGGER _HOVER ] = true ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
if ( context . getTipElement ( ) . classList . contains ( CLASS _NAME _SHOW$3 ) || context . _hoverState === HOVER _STATE _SHOW ) {
2020-03-28 11:29:08 +01:00
context . _hoverState = HOVER _STATE _SHOW ;
2019-03-11 16:13:30 +01:00
return ;
}
clearTimeout ( context . _timeout ) ;
2020-03-28 11:29:08 +01:00
context . _hoverState = HOVER _STATE _SHOW ;
2019-03-11 16:13:30 +01:00
if ( ! context . config . delay || ! context . config . delay . show ) {
context . show ( ) ;
return ;
}
2021-03-23 17:26:54 +01:00
context . _timeout = setTimeout ( ( ) => {
2020-03-28 11:29:08 +01:00
if ( context . _hoverState === HOVER _STATE _SHOW ) {
2019-03-11 16:13:30 +01:00
context . show ( ) ;
}
} , context . config . delay . show ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_leave ( event , context ) {
2021-02-10 17:14:51 +01:00
context = this . _initializeOnDelegatedTarget ( event , context ) ;
2019-03-11 16:13:30 +01:00
if ( event ) {
2021-03-23 17:26:54 +01:00
context . _activeTrigger [ event . type === 'focusout' ? TRIGGER _FOCUS : TRIGGER _HOVER ] = context . _element . contains ( event . relatedTarget ) ;
2019-03-11 16:13:30 +01:00
}
if ( context . _isWithActiveTrigger ( ) ) {
return ;
}
clearTimeout ( context . _timeout ) ;
2020-03-28 11:29:08 +01:00
context . _hoverState = HOVER _STATE _OUT ;
2019-03-11 16:13:30 +01:00
if ( ! context . config . delay || ! context . config . delay . hide ) {
context . hide ( ) ;
return ;
}
2021-03-23 17:26:54 +01:00
context . _timeout = setTimeout ( ( ) => {
2020-03-28 11:29:08 +01:00
if ( context . _hoverState === HOVER _STATE _OUT ) {
2019-03-11 16:13:30 +01:00
context . hide ( ) ;
}
} , context . config . delay . hide ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_isWithActiveTrigger ( ) {
for ( const trigger in this . _activeTrigger ) {
2019-03-11 16:13:30 +01:00
if ( this . _activeTrigger [ trigger ] ) {
return true ;
}
}
return false ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
const dataAttributes = Manipulator . getDataAttributes ( this . _element ) ;
Object . keys ( dataAttributes ) . forEach ( dataAttr => {
2020-11-23 14:17:16 +01:00
if ( DISALLOWED _ATTRIBUTES . has ( dataAttr ) ) {
2019-03-11 16:13:30 +01:00
delete dataAttributes [ dataAttr ] ;
}
} ) ;
if ( config && typeof config . container === 'object' && config . container . jquery ) {
config . container = config . container [ 0 ] ;
}
2021-03-23 17:26:54 +01:00
config = { ... this . constructor . Default ,
... dataAttributes ,
... ( typeof config === 'object' && config ? config : { } )
} ;
2019-03-11 16:13:30 +01:00
if ( typeof config . delay === 'number' ) {
config . delay = {
show : config . delay ,
hide : config . delay
} ;
}
if ( typeof config . title === 'number' ) {
config . title = config . title . toString ( ) ;
}
if ( typeof config . content === 'number' ) {
config . content = config . content . toString ( ) ;
}
2021-03-23 17:26:54 +01:00
typeCheckConfig ( NAME$4 , config , this . constructor . DefaultType ) ;
2019-03-11 16:13:30 +01:00
if ( config . sanitize ) {
2020-09-14 17:12:06 +02:00
config . template = sanitizeHtml ( config . template , config . allowList , config . sanitizeFn ) ;
2019-03-11 16:13:30 +01:00
}
return config ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getDelegateConfig ( ) {
const config = { } ;
2019-03-11 16:13:30 +01:00
if ( this . config ) {
2021-03-23 17:26:54 +01:00
for ( const key in this . config ) {
2019-03-11 16:13:30 +01:00
if ( this . constructor . Default [ key ] !== this . config [ key ] ) {
config [ key ] = this . config [ key ] ;
}
}
}
return config ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_cleanTipClass ( ) {
const tip = this . getTipElement ( ) ;
const tabClass = tip . getAttribute ( 'class' ) . match ( BSCLS _PREFIX _REGEX$1 ) ;
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
if ( tabClass !== null && tabClass . length > 0 ) {
2021-03-23 17:26:54 +01:00
tabClass . map ( token => token . trim ( ) ) . forEach ( tClass => tip . classList . remove ( tClass ) ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_handlePopperPlacementChange ( popperData ) {
const {
state
} = popperData ;
2019-03-11 16:13:30 +01:00
2020-12-07 16:50:24 +01:00
if ( ! state ) {
2019-03-11 16:13:30 +01:00
return ;
}
2020-12-07 16:50:24 +01:00
this . tip = state . elements . popper ;
this . _cleanTipClass ( ) ;
this . _addAttachmentClass ( this . _getAttachment ( state . placement ) ) ;
2019-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2021-03-23 17:26:54 +01:00
let data = Data . get ( this , DATA _KEY$4 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const _config = typeof config === 'object' && config ;
2019-03-11 16:13:30 +01:00
if ( ! data && /dispose|hide/ . test ( config ) ) {
return ;
}
if ( ! data ) {
data = new Tooltip ( this , _config ) ;
}
if ( typeof config === 'string' ) {
if ( typeof data [ config ] === 'undefined' ) {
2021-03-23 17:26:54 +01:00
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2019-03-11 16:13:30 +01:00
}
data [ config ] ( ) ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Tooltip to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2019-07-24 08:13:50 +02:00
2021-03-23 17:26:54 +01:00
defineJQueryPlugin ( NAME$4 , Tooltip ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : popover . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const NAME$3 = 'popover' ;
const DATA _KEY$3 = 'bs.popover' ;
const EVENT _KEY$3 = ` . ${ DATA _KEY$3 } ` ;
const CLASS _PREFIX = 'bs-popover' ;
const BSCLS _PREFIX _REGEX = new RegExp ( ` (^| \\ s) ${ CLASS _PREFIX } \\ S+ ` , 'g' ) ;
const Default$2 = { ... Tooltip . Default ,
2019-03-11 16:13:30 +01:00
placement : 'right' ,
2021-02-10 17:14:51 +01:00
offset : [ 0 , 8 ] ,
2019-03-11 16:13:30 +01:00
trigger : 'click' ,
content : '' ,
2020-12-03 15:18:59 +01:00
template : '<div class="popover" role="tooltip">' + '<div class="popover-arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div>' + '</div>'
2021-03-23 17:26:54 +01:00
} ;
const DefaultType$2 = { ... Tooltip . DefaultType ,
2019-03-11 16:13:30 +01:00
content : '(string|element|function)'
} ;
2021-03-23 17:26:54 +01:00
const Event$1 = {
HIDE : ` hide ${ EVENT _KEY$3 } ` ,
HIDDEN : ` hidden ${ EVENT _KEY$3 } ` ,
SHOW : ` show ${ EVENT _KEY$3 } ` ,
SHOWN : ` shown ${ EVENT _KEY$3 } ` ,
INSERTED : ` inserted ${ EVENT _KEY$3 } ` ,
CLICK : ` click ${ EVENT _KEY$3 } ` ,
FOCUSIN : ` focusin ${ EVENT _KEY$3 } ` ,
FOCUSOUT : ` focusout ${ EVENT _KEY$3 } ` ,
MOUSEENTER : ` mouseenter ${ EVENT _KEY$3 } ` ,
MOUSELEAVE : ` mouseleave ${ EVENT _KEY$3 } `
} ;
const CLASS _NAME _FADE$2 = 'fade' ;
const CLASS _NAME _SHOW$2 = 'show' ;
const SELECTOR _TITLE = '.popover-header' ;
const SELECTOR _CONTENT = '.popover-body' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Popover extends Tooltip {
// Getters
static get Default ( ) {
return Default$2 ;
}
static get NAME ( ) {
return NAME$3 ;
}
static get DATA _KEY ( ) {
return DATA _KEY$3 ;
}
static get Event ( ) {
return Event$1 ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static get EVENT _KEY ( ) {
return EVENT _KEY$3 ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
static get DefaultType ( ) {
return DefaultType$2 ;
} // Overrides
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
isWithContent ( ) {
2019-03-11 16:13:30 +01:00
return this . getTitle ( ) || this . _getContent ( ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
setContent ( ) {
const tip = this . getTipElement ( ) ; // we use append for html objects to maintain js events
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
this . setElementContent ( SelectorEngine . findOne ( SELECTOR _TITLE , tip ) , this . getTitle ( ) ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
let content = this . _getContent ( ) ;
2019-03-11 16:13:30 +01:00
if ( typeof content === 'function' ) {
2020-12-03 15:18:59 +01:00
content = content . call ( this . _element ) ;
2019-03-11 16:13:30 +01:00
}
2020-03-28 11:29:08 +01:00
this . setElementContent ( SelectorEngine . findOne ( SELECTOR _CONTENT , tip ) , content ) ;
2021-03-23 17:26:54 +01:00
tip . classList . remove ( CLASS _NAME _FADE$2 , CLASS _NAME _SHOW$2 ) ;
2020-09-14 17:12:06 +02:00
} // Private
2019-08-27 15:03:21 +02:00
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_addAttachmentClass ( attachment ) {
this . getTipElement ( ) . classList . add ( ` ${ CLASS _PREFIX } - ${ this . updateAttachment ( attachment ) } ` ) ;
}
_getContent ( ) {
2020-12-03 15:18:59 +01:00
return this . _element . getAttribute ( 'data-bs-content' ) || this . config . content ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_cleanTipClass ( ) {
const tip = this . getTipElement ( ) ;
const tabClass = tip . getAttribute ( 'class' ) . match ( BSCLS _PREFIX _REGEX ) ;
2019-03-11 16:13:30 +01:00
if ( tabClass !== null && tabClass . length > 0 ) {
2021-03-23 17:26:54 +01:00
tabClass . map ( token => token . trim ( ) ) . forEach ( tClass => tip . classList . remove ( tClass ) ) ;
2019-03-11 16:13:30 +01:00
}
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2021-03-23 17:26:54 +01:00
let data = Data . get ( this , DATA _KEY$3 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const _config = typeof config === 'object' ? config : null ;
2019-03-11 16:13:30 +01:00
if ( ! data && /dispose|hide/ . test ( config ) ) {
return ;
}
if ( ! data ) {
data = new Popover ( this , _config ) ;
2021-03-23 17:26:54 +01:00
Data . set ( this , DATA _KEY$3 , data ) ;
2019-03-11 16:13:30 +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 } " ` ) ;
2019-03-11 16:13:30 +01:00
}
data [ config ] ( ) ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Popover to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2019-07-24 08:13:50 +02:00
2021-03-23 17:26:54 +01:00
defineJQueryPlugin ( NAME$3 , Popover ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : scrollspy . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +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 } ` ;
const DATA _API _KEY$1 = '.data-api' ;
const Default$1 = {
2019-03-11 16:13:30 +01:00
offset : 10 ,
method : 'auto' ,
target : ''
} ;
2021-03-23 17:26:54 +01:00
const DefaultType$1 = {
2019-03-11 16:13:30 +01:00
offset : 'number' ,
method : 'string' ,
target : '(string|element)'
} ;
2021-03-23 17:26:54 +01:00
const EVENT _ACTIVATE = ` activate ${ EVENT _KEY$2 } ` ;
const EVENT _SCROLL = ` scroll ${ EVENT _KEY$2 } ` ;
const EVENT _LOAD _DATA _API = ` load ${ EVENT _KEY$2 } ${ DATA _API _KEY$1 } ` ;
const CLASS _NAME _DROPDOWN _ITEM = 'dropdown-item' ;
const CLASS _NAME _ACTIVE$1 = 'active' ;
const SELECTOR _DATA _SPY = '[data-bs-spy="scroll"]' ;
const SELECTOR _NAV _LIST _GROUP$1 = '.nav, .list-group' ;
const SELECTOR _NAV _LINKS = '.nav-link' ;
const SELECTOR _NAV _ITEMS = '.nav-item' ;
const SELECTOR _LIST _ITEMS = '.list-group-item' ;
const SELECTOR _DROPDOWN$1 = '.dropdown' ;
const SELECTOR _DROPDOWN _TOGGLE$1 = '.dropdown-toggle' ;
const METHOD _OFFSET = 'offset' ;
const METHOD _POSITION = 'position' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class ScrollSpy extends BaseComponent {
constructor ( element , config ) {
super ( element ) ;
this . _scrollElement = this . _element . tagName === 'BODY' ? window : this . _element ;
this . _config = this . _getConfig ( config ) ;
this . _selector = ` ${ this . _config . target } ${ SELECTOR _NAV _LINKS } , ${ this . _config . target } ${ SELECTOR _LIST _ITEMS } , ${ this . _config . target } . ${ CLASS _NAME _DROPDOWN _ITEM } ` ;
this . _offsets = [ ] ;
this . _targets = [ ] ;
this . _activeTarget = null ;
this . _scrollHeight = 0 ;
EventHandler . on ( this . _scrollElement , EVENT _SCROLL , ( ) => this . _process ( ) ) ;
this . refresh ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _process ( ) ;
2019-03-11 16:13:30 +01:00
} // Getters
2021-03-23 17:26:54 +01:00
static get Default ( ) {
return Default$1 ;
}
static get DATA _KEY ( ) {
return DATA _KEY$2 ;
} // Public
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
refresh ( ) {
const autoMethod = this . _scrollElement === this . _scrollElement . window ? METHOD _OFFSET : METHOD _POSITION ;
const offsetMethod = this . _config . method === 'auto' ? autoMethod : this . _config . method ;
const offsetBase = offsetMethod === METHOD _POSITION ? this . _getScrollTop ( ) : 0 ;
2019-03-11 16:13:30 +01:00
this . _offsets = [ ] ;
this . _targets = [ ] ;
this . _scrollHeight = this . _getScrollHeight ( ) ;
2021-03-23 17:26:54 +01:00
const targets = SelectorEngine . find ( this . _selector ) ;
targets . map ( element => {
const targetSelector = getSelectorFromElement ( element ) ;
const target = targetSelector ? SelectorEngine . findOne ( targetSelector ) : null ;
2019-03-11 16:13:30 +01:00
if ( target ) {
2021-03-23 17:26:54 +01:00
const targetBCR = target . getBoundingClientRect ( ) ;
2019-03-11 16:13:30 +01:00
if ( targetBCR . width || targetBCR . height ) {
return [ Manipulator [ offsetMethod ] ( target ) . top + offsetBase , targetSelector ] ;
}
}
return null ;
2021-03-23 17:26:54 +01:00
} ) . filter ( item => item ) . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) . forEach ( item => {
this . _offsets . push ( item [ 0 ] ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _targets . push ( item [ 1 ] ) ;
} ) ;
}
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
super . dispose ( ) ;
EventHandler . off ( this . _scrollElement , EVENT _KEY$2 ) ;
2019-03-11 16:13:30 +01:00
this . _scrollElement = null ;
this . _config = null ;
this . _selector = null ;
this . _offsets = null ;
this . _targets = null ;
this . _activeTarget = null ;
this . _scrollHeight = null ;
} // Private
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
config = { ... Default$1 ,
2021-05-05 21:32:12 +02:00
... Manipulator . getDataAttributes ( this . _element ) ,
2021-03-23 17:26:54 +01:00
... ( typeof config === 'object' && config ? config : { } )
} ;
2019-03-11 16:13:30 +01:00
2020-05-13 20:53:43 +02:00
if ( typeof config . target !== 'string' && isElement ( config . target ) ) {
2021-03-23 17:26:54 +01:00
let {
id
} = config . target ;
2019-03-11 16:13:30 +01:00
if ( ! id ) {
2021-03-23 17:26:54 +01:00
id = getUID ( NAME$2 ) ;
2019-03-11 16:13:30 +01:00
config . target . id = id ;
}
2021-03-23 17:26:54 +01:00
config . target = ` # ${ id } ` ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
typeCheckConfig ( NAME$2 , config , DefaultType$1 ) ;
2019-03-11 16:13:30 +01:00
return config ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getScrollTop ( ) {
2019-03-11 16:13:30 +01:00
return this . _scrollElement === window ? this . _scrollElement . pageYOffset : this . _scrollElement . scrollTop ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getScrollHeight ( ) {
2019-03-11 16:13:30 +01:00
return this . _scrollElement . scrollHeight || Math . max ( document . body . scrollHeight , document . documentElement . scrollHeight ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_getOffsetHeight ( ) {
2019-03-11 16:13:30 +01:00
return this . _scrollElement === window ? window . innerHeight : this . _scrollElement . getBoundingClientRect ( ) . height ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_process ( ) {
const scrollTop = this . _getScrollTop ( ) + this . _config . offset ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const scrollHeight = this . _getScrollHeight ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const maxScroll = this . _config . offset + scrollHeight - this . _getOffsetHeight ( ) ;
2019-03-11 16:13:30 +01:00
if ( this . _scrollHeight !== scrollHeight ) {
this . refresh ( ) ;
}
if ( scrollTop >= maxScroll ) {
2021-03-23 17:26:54 +01:00
const target = this . _targets [ this . _targets . length - 1 ] ;
2019-03-11 16:13:30 +01:00
if ( this . _activeTarget !== target ) {
this . _activate ( target ) ;
}
return ;
}
if ( this . _activeTarget && scrollTop < this . _offsets [ 0 ] && this . _offsets [ 0 ] > 0 ) {
this . _activeTarget = null ;
this . _clear ( ) ;
return ;
}
2021-03-23 17:26:54 +01:00
for ( let i = this . _offsets . length ; i -- ; ) {
const isActiveTarget = this . _activeTarget !== this . _targets [ i ] && scrollTop >= this . _offsets [ i ] && ( typeof this . _offsets [ i + 1 ] === 'undefined' || scrollTop < this . _offsets [ i + 1 ] ) ;
2019-03-11 16:13:30 +01:00
if ( isActiveTarget ) {
this . _activate ( this . _targets [ i ] ) ;
}
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_activate ( target ) {
2019-03-11 16:13:30 +01:00
this . _activeTarget = target ;
this . _clear ( ) ;
2021-03-23 17:26:54 +01:00
const queries = this . _selector . split ( ',' ) . map ( selector => ` ${ selector } [data-bs-target=" ${ target } "], ${ selector } [href=" ${ target } "] ` ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const link = SelectorEngine . findOne ( queries . join ( ',' ) ) ;
2019-03-11 16:13:30 +01:00
2020-03-28 11:29:08 +01:00
if ( link . classList . contains ( CLASS _NAME _DROPDOWN _ITEM ) ) {
2021-03-23 17:26:54 +01:00
SelectorEngine . findOne ( SELECTOR _DROPDOWN _TOGGLE$1 , link . closest ( SELECTOR _DROPDOWN$1 ) ) . classList . add ( CLASS _NAME _ACTIVE$1 ) ;
link . classList . add ( CLASS _NAME _ACTIVE$1 ) ;
2019-03-11 16:13:30 +01:00
} else {
// Set triggered link as active
2021-03-23 17:26:54 +01:00
link . classList . add ( CLASS _NAME _ACTIVE$1 ) ;
SelectorEngine . parents ( link , SELECTOR _NAV _LIST _GROUP$1 ) . forEach ( listGroup => {
2019-03-11 16:13:30 +01:00
// Set triggered links parents as active
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
2021-03-23 17:26:54 +01:00
SelectorEngine . prev ( listGroup , ` ${ SELECTOR _NAV _LINKS } , ${ SELECTOR _LIST _ITEMS } ` ) . forEach ( item => item . classList . add ( CLASS _NAME _ACTIVE$1 ) ) ; // Handle special case when .nav-link is inside .nav-item
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
SelectorEngine . prev ( listGroup , SELECTOR _NAV _ITEMS ) . forEach ( navItem => {
SelectorEngine . children ( navItem , SELECTOR _NAV _LINKS ) . forEach ( item => item . classList . add ( CLASS _NAME _ACTIVE$1 ) ) ;
2019-03-11 16:13:30 +01:00
} ) ;
} ) ;
}
2020-03-28 11:29:08 +01:00
EventHandler . trigger ( this . _scrollElement , EVENT _ACTIVATE , {
2019-03-11 16:13:30 +01:00
relatedTarget : target
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_clear ( ) {
SelectorEngine . find ( this . _selector ) . filter ( node => node . classList . contains ( CLASS _NAME _ACTIVE$1 ) ) . forEach ( node => node . classList . remove ( CLASS _NAME _ACTIVE$1 ) ) ;
2019-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2021-05-05 21:32:12 +02:00
const data = ScrollSpy . getInstance ( this ) || new ScrollSpy ( this , typeof config === 'object' ? config : { } ) ;
2019-03-11 16:13:30 +01:00
2021-05-05 21:32:12 +02:00
if ( typeof config !== 'string' ) {
return ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
if ( typeof data [ config ] === 'undefined' ) {
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
data [ config ] ( ) ;
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
EventHandler . on ( window , EVENT _LOAD _DATA _API , ( ) => {
2021-05-05 21:32:12 +02:00
SelectorEngine . find ( SELECTOR _DATA _SPY ) . forEach ( spy => new ScrollSpy ( spy ) ) ;
2019-03-11 16:13:30 +01:00
} ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . ScrollSpy to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2021-03-23 17:26:54 +01:00
defineJQueryPlugin ( NAME$2 , ScrollSpy ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : tab . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
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 DATA _API _KEY = '.data-api' ;
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 } ` ;
const EVENT _CLICK _DATA _API = ` click ${ EVENT _KEY$1 } ${ DATA _API _KEY } ` ;
const CLASS _NAME _DROPDOWN _MENU = 'dropdown-menu' ;
const CLASS _NAME _ACTIVE = 'active' ;
const CLASS _NAME _FADE$1 = 'fade' ;
const CLASS _NAME _SHOW$1 = 'show' ;
const SELECTOR _DROPDOWN = '.dropdown' ;
const SELECTOR _NAV _LIST _GROUP = '.nav, .list-group' ;
const SELECTOR _ACTIVE = '.active' ;
const SELECTOR _ACTIVE _UL = ':scope > li > .active' ;
const SELECTOR _DATA _TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]' ;
const SELECTOR _DROPDOWN _TOGGLE = '.dropdown-toggle' ;
const SELECTOR _DROPDOWN _ACTIVE _CHILD = ':scope > .dropdown-menu .active' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Tab extends BaseComponent {
// Getters
static get DATA _KEY ( ) {
return DATA _KEY$1 ;
} // Public
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
show ( ) {
2021-05-05 21:32:12 +02:00
if ( this . _element . parentNode && this . _element . parentNode . nodeType === Node . ELEMENT _NODE && this . _element . classList . contains ( CLASS _NAME _ACTIVE ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
2021-03-23 17:26:54 +01:00
let previous ;
const target = getElementFromSelector ( this . _element ) ;
2020-05-13 20:53:43 +02:00
2021-03-23 17:26:54 +01:00
const listElement = this . _element . closest ( SELECTOR _NAV _LIST _GROUP ) ;
2019-03-11 16:13:30 +01:00
if ( listElement ) {
2021-03-23 17:26:54 +01:00
const itemSelector = listElement . nodeName === 'UL' || listElement . nodeName === 'OL' ? SELECTOR _ACTIVE _UL : SELECTOR _ACTIVE ;
2020-03-28 11:29:08 +01:00
previous = SelectorEngine . find ( itemSelector , listElement ) ;
2019-03-11 16:13:30 +01:00
previous = previous [ previous . length - 1 ] ;
}
2021-03-23 17:26:54 +01:00
const hideEvent = previous ? EventHandler . trigger ( previous , EVENT _HIDE$1 , {
2021-02-10 17:14:51 +01:00
relatedTarget : this . _element
} ) : null ;
2021-03-23 17:26:54 +01:00
const showEvent = EventHandler . trigger ( this . _element , EVENT _SHOW$1 , {
2019-03-11 16:13:30 +01:00
relatedTarget : previous
} ) ;
if ( showEvent . defaultPrevented || hideEvent !== null && hideEvent . defaultPrevented ) {
return ;
}
this . _activate ( this . _element , listElement ) ;
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
EventHandler . trigger ( previous , EVENT _HIDDEN$1 , {
relatedTarget : this . _element
2019-03-11 16:13:30 +01:00
} ) ;
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , EVENT _SHOWN$1 , {
2019-03-11 16:13:30 +01:00
relatedTarget : previous
} ) ;
} ;
if ( target ) {
this . _activate ( target , target . parentNode , complete ) ;
} else {
complete ( ) ;
}
} // Private
2021-03-23 17:26:54 +01:00
_activate ( element , container , callback ) {
const activeElements = container && ( container . nodeName === 'UL' || container . nodeName === 'OL' ) ? SelectorEngine . find ( SELECTOR _ACTIVE _UL , container ) : SelectorEngine . children ( container , SELECTOR _ACTIVE ) ;
const active = activeElements [ 0 ] ;
const isTransitioning = callback && active && active . classList . contains ( CLASS _NAME _FADE$1 ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => this . _transitionComplete ( element , active , callback ) ;
2019-03-11 16:13:30 +01:00
if ( active && isTransitioning ) {
2021-03-23 17:26:54 +01:00
const transitionDuration = getTransitionDurationFromElement ( active ) ;
active . classList . remove ( CLASS _NAME _SHOW$1 ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( active , 'transitionend' , complete ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( active , transitionDuration ) ;
} else {
complete ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_transitionComplete ( element , active , callback ) {
2019-03-11 16:13:30 +01:00
if ( active ) {
2021-03-23 17:26:54 +01:00
active . classList . remove ( CLASS _NAME _ACTIVE ) ;
const dropdownChild = SelectorEngine . findOne ( SELECTOR _DROPDOWN _ACTIVE _CHILD , active . parentNode ) ;
2019-03-11 16:13:30 +01:00
if ( dropdownChild ) {
2021-03-23 17:26:54 +01:00
dropdownChild . classList . remove ( CLASS _NAME _ACTIVE ) ;
2019-03-11 16:13:30 +01:00
}
if ( active . getAttribute ( 'role' ) === 'tab' ) {
active . setAttribute ( 'aria-selected' , false ) ;
}
}
2021-03-23 17:26:54 +01:00
element . classList . add ( CLASS _NAME _ACTIVE ) ;
2019-03-11 16:13:30 +01:00
if ( element . getAttribute ( 'role' ) === 'tab' ) {
element . setAttribute ( 'aria-selected' , true ) ;
}
reflow ( element ) ;
2021-03-23 17:26:54 +01:00
if ( element . classList . contains ( CLASS _NAME _FADE$1 ) ) {
element . classList . add ( CLASS _NAME _SHOW$1 ) ;
2019-03-11 16:13:30 +01:00
}
2021-05-05 21:32:12 +02:00
let parent = element . parentNode ;
if ( parent && parent . nodeName === 'LI' ) {
parent = parent . parentNode ;
}
if ( parent && parent . classList . contains ( CLASS _NAME _DROPDOWN _MENU ) ) {
2021-03-23 17:26:54 +01:00
const dropdownElement = element . closest ( SELECTOR _DROPDOWN ) ;
2019-03-11 16:13:30 +01:00
if ( dropdownElement ) {
2021-05-05 21:32:12 +02:00
SelectorEngine . find ( SELECTOR _DROPDOWN _TOGGLE , dropdownElement ) . forEach ( dropdown => dropdown . classList . add ( CLASS _NAME _ACTIVE ) ) ;
2019-03-11 16:13:30 +01:00
}
element . setAttribute ( 'aria-expanded' , true ) ;
}
if ( callback ) {
callback ( ) ;
}
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2021-03-23 17:26:54 +01:00
const data = Data . get ( this , DATA _KEY$1 ) || new Tab ( this ) ;
2019-03-11 16:13:30 +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 } " ` ) ;
2019-03-11 16:13:30 +01:00
}
data [ config ] ( ) ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Data Api implementation
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
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 ;
}
2021-03-23 17:26:54 +01:00
const data = Data . get ( this , DATA _KEY$1 ) || new Tab ( this ) ;
2019-03-11 16:13:30 +01:00
data . show ( ) ;
} ) ;
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Tab to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2021-03-23 17:26:54 +01:00
defineJQueryPlugin ( NAME$1 , Tab ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2021-05-05 21:32:12 +02:00
* Bootstrap ( v5 . 0.0 ) : toast . js
2021-03-23 17:26:54 +01:00
* Licensed under MIT ( https : //github.com/twbs/bootstrap/blob/main/LICENSE)
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Constants
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2021-03-23 17:26:54 +01:00
const NAME = 'toast' ;
const DATA _KEY = 'bs.toast' ;
const EVENT _KEY = ` . ${ DATA _KEY } ` ;
const EVENT _CLICK _DISMISS = ` click.dismiss ${ EVENT _KEY } ` ;
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' ;
const CLASS _NAME _HIDE = 'hide' ;
const CLASS _NAME _SHOW = 'show' ;
const CLASS _NAME _SHOWING = 'showing' ;
const DefaultType = {
2019-03-11 16:13:30 +01:00
animation : 'boolean' ,
autohide : 'boolean' ,
delay : 'number'
} ;
2021-03-23 17:26:54 +01:00
const Default = {
2019-03-11 16:13:30 +01:00
animation : true ,
autohide : true ,
2020-09-14 17:12:06 +02:00
delay : 5000
2019-03-11 16:13:30 +01:00
} ;
2021-03-23 17:26:54 +01:00
const SELECTOR _DATA _DISMISS = '[data-bs-dismiss="toast"]' ;
2019-10-08 08:39:10 +02:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* Class Definition
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
class Toast extends BaseComponent {
constructor ( element , config ) {
super ( element ) ;
this . _config = this . _getConfig ( config ) ;
this . _timeout = null ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _setListeners ( ) ;
} // Getters
2019-03-11 16:13:30 +01:00
2020-12-03 15:18:59 +01:00
2021-03-23 17:26:54 +01:00
static get DefaultType ( ) {
return DefaultType ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static get Default ( ) {
return Default ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
static get DATA _KEY ( ) {
return DATA _KEY ;
} // Public
2019-03-11 16:13:30 +01: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 ;
}
2019-03-11 16:13:30 +01:00
2020-09-14 17:12:06 +02:00
this . _clearTimeout ( ) ;
2019-03-11 16:13:30 +01:00
if ( this . _config . animation ) {
2021-03-23 17:26:54 +01:00
this . _element . classList . add ( CLASS _NAME _FADE ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
this . _element . classList . remove ( CLASS _NAME _SHOWING ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
this . _element . classList . add ( CLASS _NAME _SHOW ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
EventHandler . trigger ( this . _element , EVENT _SHOWN ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( this . _config . autohide ) {
this . _timeout = setTimeout ( ( ) => {
this . hide ( ) ;
} , this . _config . delay ) ;
2019-03-11 16:13:30 +01:00
}
} ;
2020-03-28 11:29:08 +01:00
this . _element . classList . remove ( CLASS _NAME _HIDE ) ;
2019-03-11 16:13:30 +01:00
2019-07-24 08:13:50 +02:00
reflow ( this . _element ) ;
2020-03-28 11:29:08 +01:00
this . _element . classList . add ( CLASS _NAME _SHOWING ) ;
2019-03-11 16:13:30 +01:00
if ( this . _config . animation ) {
2021-03-23 17:26:54 +01:00
const transitionDuration = getTransitionDurationFromElement ( this . _element ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( this . _element , 'transitionend' , complete ) ;
2019-03-11 16:13:30 +01:00
emulateTransitionEnd ( this . _element , transitionDuration ) ;
} else {
complete ( ) ;
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
hide ( ) {
if ( ! this . _element . classList . contains ( CLASS _NAME _SHOW ) ) {
2019-03-11 16:13:30 +01:00
return ;
}
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 ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const complete = ( ) => {
this . _element . classList . add ( CLASS _NAME _HIDE ) ;
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-03-23 17:26:54 +01:00
this . _element . classList . remove ( CLASS _NAME _SHOW ) ;
2019-04-18 13:47:52 +02:00
if ( this . _config . animation ) {
2021-03-23 17:26:54 +01:00
const transitionDuration = getTransitionDurationFromElement ( this . _element ) ;
2021-02-10 17:14:51 +01:00
EventHandler . one ( this . _element , 'transitionend' , complete ) ;
2019-04-18 13:47:52 +02:00
emulateTransitionEnd ( this . _element , transitionDuration ) ;
2019-03-11 16:13:30 +01:00
} else {
2019-04-18 13:47:52 +02:00
complete ( ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
dispose ( ) {
2020-09-14 17:12:06 +02:00
this . _clearTimeout ( ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
if ( this . _element . classList . contains ( CLASS _NAME _SHOW ) ) {
this . _element . classList . remove ( CLASS _NAME _SHOW ) ;
2019-03-11 16:13:30 +01:00
}
2021-03-23 17:26:54 +01:00
super . dispose ( ) ;
2019-03-11 16:13:30 +01:00
this . _config = null ;
} // Private
2021-03-23 17:26:54 +01:00
_getConfig ( config ) {
config = { ... Default ,
... Manipulator . getDataAttributes ( this . _element ) ,
... ( typeof config === 'object' && config ? config : { } )
} ;
typeCheckConfig ( NAME , config , this . constructor . DefaultType ) ;
return config ;
}
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
_setListeners ( ) {
EventHandler . on ( this . _element , EVENT _CLICK _DISMISS , SELECTOR _DATA _DISMISS , ( ) => this . hide ( ) ) ;
}
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-03-11 16:13:30 +01:00
} // Static
2021-03-23 17:26:54 +01:00
static jQueryInterface ( config ) {
2019-03-11 16:13:30 +01:00
return this . each ( function ( ) {
2021-03-23 17:26:54 +01:00
let data = Data . get ( this , DATA _KEY ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
const _config = typeof config === 'object' && config ;
2019-03-11 16:13:30 +01:00
if ( ! data ) {
data = new Toast ( this , _config ) ;
}
if ( typeof config === 'string' ) {
if ( typeof data [ config ] === 'undefined' ) {
2021-03-23 17:26:54 +01:00
throw new TypeError ( ` No method named " ${ config } " ` ) ;
2019-03-11 16:13:30 +01:00
}
data [ config ] ( this ) ;
}
} ) ;
2021-03-23 17:26:54 +01:00
}
2019-04-18 13:47:52 +02:00
2021-03-23 17:26:54 +01:00
}
2019-03-11 16:13:30 +01:00
/ * *
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* jQuery
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2020-11-11 18:07:37 +01:00
* add . Toast to jQuery only if jQuery is present
2019-03-11 16:13:30 +01:00
* /
2019-07-24 08:13:50 +02:00
2021-03-23 17:26:54 +01:00
defineJQueryPlugin ( NAME , Toast ) ;
2019-03-11 16:13:30 +01:00
2021-03-23 17:26:54 +01:00
export { Alert , Button , Carousel , Collapse , Dropdown , Modal , Offcanvas , Popover , ScrollSpy , Tab , Toast , Tooltip } ;
2019-03-11 16:13:30 +01:00
//# sourceMappingURL=bootstrap.esm.js.map