342 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			342 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
/**
 | 
						|
 * --------------------------------------------------------------------------
 | 
						|
 * Bootstrap (v5.1.3): util/index.js
 | 
						|
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 | 
						|
 * --------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
define([
 | 
						|
    "jquery",
 | 
						|
    'domReady!'
 | 
						|
], function() {
 | 
						|
    'use strict';
 | 
						|
 | 
						|
    const MAX_UID = 1000000;
 | 
						|
    const MILLISECONDS_MULTIPLIER = 1000;
 | 
						|
    const TRANSITION_END = 'transitionend';
 | 
						|
 | 
						|
    // Shoutout AngusCroll (https://goo.gl/pxwQGp)
 | 
						|
    const toType = obj => {
 | 
						|
        if (obj === null || obj === undefined) {
 | 
						|
            return `${obj}`
 | 
						|
        }
 | 
						|
 | 
						|
        return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * --------------------------------------------------------------------------
 | 
						|
     * Public Util Api
 | 
						|
     * --------------------------------------------------------------------------
 | 
						|
     */
 | 
						|
 | 
						|
    const getUID = prefix => {
 | 
						|
        do {
 | 
						|
            prefix += Math.floor(Math.random() * MAX_UID)
 | 
						|
        } while (document.getElementById(prefix))
 | 
						|
 | 
						|
        return prefix
 | 
						|
    };
 | 
						|
 | 
						|
    const getSelector = element => {
 | 
						|
        let selector = element.getAttribute('data-bs-target');
 | 
						|
 | 
						|
        if (!selector || selector === '#') {
 | 
						|
            let hrefAttr = element.getAttribute('href');
 | 
						|
 | 
						|
            // The only valid content that could double as a selector are IDs or classes,
 | 
						|
            // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
 | 
						|
            // `document.querySelector` will rightfully complain it is invalid.
 | 
						|
            // See https://github.com/twbs/bootstrap/issues/32273
 | 
						|
            if (!hrefAttr || (!hrefAttr.includes('#') && !hrefAttr.startsWith('.'))) {
 | 
						|
                return null
 | 
						|
            }
 | 
						|
 | 
						|
            // Just in case some CMS puts out a full URL with the anchor appended
 | 
						|
            if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
 | 
						|
                hrefAttr = `#${hrefAttr.split('#')[1]}`
 | 
						|
            }
 | 
						|
 | 
						|
            selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null
 | 
						|
        }
 | 
						|
 | 
						|
        return selector
 | 
						|
    };
 | 
						|
 | 
						|
    const getSelectorFromElement = element => {
 | 
						|
        const selector = getSelector(element);
 | 
						|
 | 
						|
        if (selector) {
 | 
						|
            return document.querySelector(selector) ? selector : null
 | 
						|
        }
 | 
						|
 | 
						|
        return null
 | 
						|
    };
 | 
						|
 | 
						|
    const getElementFromSelector = element => {
 | 
						|
        const selector = getSelector(element);
 | 
						|
 | 
						|
        return selector ? document.querySelector(selector) : null
 | 
						|
    };
 | 
						|
 | 
						|
    const getTransitionDurationFromElement = element => {
 | 
						|
        if (!element) {
 | 
						|
            return 0
 | 
						|
        }
 | 
						|
 | 
						|
        // Get transition-duration of the element
 | 
						|
        let {transitionDuration, transitionDelay} = window.getComputedStyle(element);
 | 
						|
 | 
						|
        const floatTransitionDuration = Number.parseFloat(transitionDuration);
 | 
						|
        const floatTransitionDelay = Number.parseFloat(transitionDelay);
 | 
						|
 | 
						|
        // Return 0 if element or transition duration is not found
 | 
						|
        if (!floatTransitionDuration && !floatTransitionDelay) {
 | 
						|
            return 0
 | 
						|
        }
 | 
						|
 | 
						|
        // If multiple durations are defined, take the first
 | 
						|
        transitionDuration = transitionDuration.split(',')[0]
 | 
						|
        transitionDelay = transitionDelay.split(',')[0]
 | 
						|
 | 
						|
        return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
 | 
						|
    };
 | 
						|
 | 
						|
    const triggerTransitionEnd = element => {
 | 
						|
        element.dispatchEvent(new Event(TRANSITION_END))
 | 
						|
    };
 | 
						|
 | 
						|
    const isElement = obj => {
 | 
						|
        if (!obj || typeof obj !== 'object') {
 | 
						|
            return false
 | 
						|
        }
 | 
						|
 | 
						|
        if (typeof obj.jquery !== 'undefined') {
 | 
						|
            obj = obj[0]
 | 
						|
        }
 | 
						|
 | 
						|
        return typeof obj.nodeType !== 'undefined'
 | 
						|
    };
 | 
						|
 | 
						|
    const getElement = obj => {
 | 
						|
        if (isElement(obj)) { // it's a jQuery object or a node element
 | 
						|
            return obj.jquery ? obj[0] : obj
 | 
						|
        }
 | 
						|
 | 
						|
        if (typeof obj === 'string' && obj.length > 0) {
 | 
						|
            return document.querySelector(obj)
 | 
						|
        }
 | 
						|
 | 
						|
        return null
 | 
						|
    };
 | 
						|
 | 
						|
    const typeCheckConfig = (componentName, config, configTypes) => {
 | 
						|
        Object.keys(configTypes).forEach(property => {
 | 
						|
            const expectedTypes = configTypes[property];
 | 
						|
            const value = config[property];
 | 
						|
            const valueType = value && isElement(value) ? 'element' : toType(value);
 | 
						|
 | 
						|
            if (!new RegExp(expectedTypes).test(valueType)) {
 | 
						|
                throw new TypeError(
 | 
						|
                    `${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
 | 
						|
                )
 | 
						|
            }
 | 
						|
        })
 | 
						|
    };
 | 
						|
 | 
						|
    const isVisible = element => {
 | 
						|
        if (!isElement(element) || element.getClientRects().length === 0) {
 | 
						|
            return false
 | 
						|
        }
 | 
						|
 | 
						|
        return getComputedStyle(element).getPropertyValue('visibility') === 'visible'
 | 
						|
    };
 | 
						|
 | 
						|
    const isDisabled = element => {
 | 
						|
        if (!element || element.nodeType !== Node.ELEMENT_NODE) {
 | 
						|
            return true
 | 
						|
        }
 | 
						|
 | 
						|
        if (element.classList.contains('disabled')) {
 | 
						|
            return true
 | 
						|
        }
 | 
						|
 | 
						|
        if (typeof element.disabled !== 'undefined') {
 | 
						|
            return element.disabled
 | 
						|
        }
 | 
						|
 | 
						|
        return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'
 | 
						|
    };
 | 
						|
 | 
						|
    const findShadowRoot = element => {
 | 
						|
        if (!document.documentElement.attachShadow) {
 | 
						|
            return null
 | 
						|
        }
 | 
						|
 | 
						|
        // Can find the shadow root otherwise it'll return the document
 | 
						|
        if (typeof element.getRootNode === 'function') {
 | 
						|
            const root = element.getRootNode();
 | 
						|
            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)
 | 
						|
    };
 | 
						|
 | 
						|
    const noop = () => {};
 | 
						|
 | 
						|
    /**
 | 
						|
     * Trick to restart an element's animation
 | 
						|
     *
 | 
						|
     * @param {HTMLElement} element
 | 
						|
     * @return void
 | 
						|
     *
 | 
						|
     * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
 | 
						|
     */
 | 
						|
    const reflow = element => {
 | 
						|
        // eslint-disable-next-line no-unused-expressions
 | 
						|
        element.offsetHeight
 | 
						|
    };
 | 
						|
 | 
						|
    const getjQuery = () => {
 | 
						|
        const {jQuery} = window;
 | 
						|
 | 
						|
        if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
 | 
						|
            return jQuery
 | 
						|
        }
 | 
						|
 | 
						|
        return null
 | 
						|
    };
 | 
						|
 | 
						|
    const DOMContentLoadedCallbacks = [];
 | 
						|
 | 
						|
    const onDOMContentLoaded = callback => {
 | 
						|
        if (document.readyState === 'loading') {
 | 
						|
            // add listener on the first call when the document is in loading state
 | 
						|
            if (!DOMContentLoadedCallbacks.length) {
 | 
						|
                document.addEventListener('DOMContentLoaded', () => {
 | 
						|
                    DOMContentLoadedCallbacks.forEach(callback => callback())
 | 
						|
                })
 | 
						|
            }
 | 
						|
 | 
						|
            DOMContentLoadedCallbacks.push(callback)
 | 
						|
        } else {
 | 
						|
            callback()
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    const isRTL = () => document.documentElement.dir === 'rtl';
 | 
						|
 | 
						|
    const defineJQueryPlugin = plugin => {
 | 
						|
        onDOMContentLoaded(() => {
 | 
						|
            const $ = getjQuery();
 | 
						|
            /* istanbul ignore if */
 | 
						|
            if ($) {
 | 
						|
                const name = plugin.NAME;
 | 
						|
                const JQUERY_NO_CONFLICT = $.fn[name];
 | 
						|
                $.fn[name] = plugin.jQueryInterface
 | 
						|
                $.fn[name].Constructor = plugin
 | 
						|
                $.fn[name].noConflict = () => {
 | 
						|
                    $.fn[name] = JQUERY_NO_CONFLICT
 | 
						|
                    return plugin.jQueryInterface
 | 
						|
                }
 | 
						|
            }
 | 
						|
        })
 | 
						|
    };
 | 
						|
 | 
						|
    const execute = callback => {
 | 
						|
        if (typeof callback === 'function') {
 | 
						|
            callback()
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
 | 
						|
        if (!waitForTransition) {
 | 
						|
            execute(callback)
 | 
						|
            return
 | 
						|
        }
 | 
						|
 | 
						|
        const durationPadding = 5;
 | 
						|
        const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
 | 
						|
 | 
						|
        let called = false;
 | 
						|
 | 
						|
        const handler = ({ target }) => {
 | 
						|
            if (target !== transitionElement) {
 | 
						|
                return
 | 
						|
            }
 | 
						|
 | 
						|
            called = true
 | 
						|
            transitionElement.removeEventListener(TRANSITION_END, handler)
 | 
						|
            execute(callback)
 | 
						|
        };
 | 
						|
 | 
						|
        transitionElement.addEventListener(TRANSITION_END, handler)
 | 
						|
        setTimeout(() => {
 | 
						|
            if (!called) {
 | 
						|
                triggerTransitionEnd(transitionElement)
 | 
						|
            }
 | 
						|
        }, emulatedDuration)
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * Return the previous/next element of a list.
 | 
						|
     *
 | 
						|
     * @param {array} list    The list of elements
 | 
						|
     * @param activeElement   The active element
 | 
						|
     * @param shouldGetNext   Choose to get next or previous element
 | 
						|
     * @param isCycleAllowed
 | 
						|
     * @return {Element|elem} The proper element
 | 
						|
     */
 | 
						|
    const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
 | 
						|
        let index = list.indexOf(activeElement);
 | 
						|
 | 
						|
        // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
 | 
						|
        if (index === -1) {
 | 
						|
            return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0]
 | 
						|
        }
 | 
						|
 | 
						|
        const listLength = list.length;
 | 
						|
 | 
						|
        index += shouldGetNext ? 1 : -1
 | 
						|
 | 
						|
        if (isCycleAllowed) {
 | 
						|
            index = (index + listLength) % listLength
 | 
						|
        }
 | 
						|
 | 
						|
        return list[Math.max(0, Math.min(index, listLength - 1))]
 | 
						|
    };
 | 
						|
 | 
						|
    return {
 | 
						|
        getElement,
 | 
						|
        getUID,
 | 
						|
        getSelectorFromElement,
 | 
						|
        getElementFromSelector,
 | 
						|
        getTransitionDurationFromElement,
 | 
						|
        triggerTransitionEnd,
 | 
						|
        isElement,
 | 
						|
        typeCheckConfig,
 | 
						|
        isVisible,
 | 
						|
        isDisabled,
 | 
						|
        findShadowRoot,
 | 
						|
        noop,
 | 
						|
        getNextActiveElement,
 | 
						|
        reflow,
 | 
						|
        getjQuery,
 | 
						|
        onDOMContentLoaded,
 | 
						|
        isRTL,
 | 
						|
        defineJQueryPlugin,
 | 
						|
        execute,
 | 
						|
        executeAfterTransition
 | 
						|
    };
 | 
						|
});
 |