import { b as isRTL, d as defineJQueryPlugin, B as BaseComponent, E as EventHandler, o as findShadowRoot, p as getUID, D as Data, n as noop, S as SelectorEngine, k as isElement, h as getElement, s as sanitizeHtml, M as Manipulator, a as typeCheckConfig, q as DefaultAllowlist } from './dom.js?5.1.3'; import { P as Popper, c as createPopper } from './popper.js?5.1.3'; /** * -------------------------------------------------------------------------- * Bootstrap (v5.1.3): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$1 = 'tooltip'; const DATA_KEY$1 = 'bs.tooltip'; const EVENT_KEY$1 = `.${DATA_KEY$1}`; const CLASS_PREFIX$1 = 'bs-tooltip'; const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); const DefaultType$1 = { animation: 'boolean', template: 'string', title: '(string|element|function)', trigger: 'string', delay: '(number|object)', html: 'boolean', selector: '(string|boolean)', placement: '(string|function)', offset: '(array|string|function)', container: '(string|element|boolean)', fallbackPlacements: 'array', boundary: '(string|element)', customClass: '(string|function)', sanitize: 'boolean', sanitizeFn: '(null|function)', allowList: 'object', popperConfig: '(null|object|function)' }; const AttachmentMap = { AUTO: 'auto', TOP: 'top', RIGHT: isRTL() ? 'left' : 'right', BOTTOM: 'bottom', LEFT: isRTL() ? 'right' : 'left' }; const Default$1 = { animation: true, template: '', trigger: 'hover focus', title: '', delay: 0, html: false, selector: false, placement: 'top', offset: [0, 0], container: false, fallbackPlacements: ['top', 'right', 'bottom', 'left'], boundary: 'clippingParents', customClass: '', sanitize: true, sanitizeFn: null, allowList: DefaultAllowlist, popperConfig: null }; const Event$1 = { HIDE: `hide${EVENT_KEY$1}`, HIDDEN: `hidden${EVENT_KEY$1}`, SHOW: `show${EVENT_KEY$1}`, SHOWN: `shown${EVENT_KEY$1}`, INSERTED: `inserted${EVENT_KEY$1}`, CLICK: `click${EVENT_KEY$1}`, FOCUSIN: `focusin${EVENT_KEY$1}`, FOCUSOUT: `focusout${EVENT_KEY$1}`, MOUSEENTER: `mouseenter${EVENT_KEY$1}`, MOUSELEAVE: `mouseleave${EVENT_KEY$1}` }; const CLASS_NAME_FADE = 'fade'; const CLASS_NAME_MODAL = 'modal'; const CLASS_NAME_SHOW = 'show'; const HOVER_STATE_SHOW = 'show'; const HOVER_STATE_OUT = 'out'; const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`; const EVENT_MODAL_HIDE = 'hide.bs.modal'; const TRIGGER_HOVER = 'hover'; const TRIGGER_FOCUS = 'focus'; const TRIGGER_CLICK = 'click'; const TRIGGER_MANUAL = 'manual'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Tooltip extends BaseComponent { constructor(element, config) { if (typeof Popper === 'undefined') { throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)'); } super(element); // private this._isEnabled = true; this._timeout = 0; this._hoverState = ''; this._activeTrigger = {}; this._popper = null; // Protected this._config = this._getConfig(config); this.tip = null; this._setListeners(); } // Getters static get Default() { return Default$1; } static get NAME() { return NAME$1; } static get Event() { return Event$1; } static get DefaultType() { return DefaultType$1; } // Public enable() { this._isEnabled = true; } disable() { this._isEnabled = false; } toggleEnabled() { this._isEnabled = !this._isEnabled; } toggle(event) { if (!this._isEnabled) { return; } if (event) { const context = this._initializeOnDelegatedTarget(event); context._activeTrigger.click = !context._activeTrigger.click; if (context._isWithActiveTrigger()) { context._enter(null, context); } else { context._leave(null, context); } } else { if (this.getTipElement().classList.contains(CLASS_NAME_SHOW)) { this._leave(null, this); return; } this._enter(null, this); } } dispose() { clearTimeout(this._timeout); EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); if (this.tip) { this.tip.remove(); } this._disposePopper(); super.dispose(); } show() { if (this._element.style.display === 'none') { throw new Error('Please use show on visible elements'); } if (!(this.isWithContent() && this._isEnabled)) { return; } 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); if (showEvent.defaultPrevented || !isInTheDom) { return; } // A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title` // This will be removed later in favor of a `setContent` method if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) { this._disposePopper(); this.tip.remove(); this.tip = null; } const tip = this.getTipElement(); const tipId = getUID(this.constructor.NAME); tip.setAttribute('id', tipId); this._element.setAttribute('aria-describedby', tipId); if (this._config.animation) { tip.classList.add(CLASS_NAME_FADE); } const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement; const attachment = this._getAttachment(placement); this._addAttachmentClass(attachment); const { container } = this._config; Data.set(tip, this.constructor.DATA_KEY, this); if (!this._element.ownerDocument.documentElement.contains(this.tip)) { container.append(tip); EventHandler.trigger(this._element, this.constructor.Event.INSERTED); } if (this._popper) { this._popper.update(); } else { this._popper = createPopper(this._element, tip, this._getPopperConfig(attachment)); } tip.classList.add(CLASS_NAME_SHOW); const customClass = this._resolvePossibleFunction(this._config.customClass); if (customClass) { tip.classList.add(...customClass.split(' ')); } // 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 if ('ontouchstart' in document.documentElement) { [].concat(...document.body.children).forEach(element => { EventHandler.on(element, 'mouseover', noop); }); } const complete = () => { const prevHoverState = this._hoverState; this._hoverState = null; EventHandler.trigger(this._element, this.constructor.Event.SHOWN); if (prevHoverState === HOVER_STATE_OUT) { this._leave(null, this); } }; const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE); this._queueCallback(complete, this.tip, isAnimated); } hide() { if (!this._popper) { return; } const tip = this.getTipElement(); const complete = () => { if (this._isWithActiveTrigger()) { return; } if (this._hoverState !== HOVER_STATE_SHOW) { tip.remove(); } this._cleanTipClass(); this._element.removeAttribute('aria-describedby'); EventHandler.trigger(this._element, this.constructor.Event.HIDDEN); this._disposePopper(); }; const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE); if (hideEvent.defaultPrevented) { return; } tip.classList.remove(CLASS_NAME_SHOW); // 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(element => EventHandler.off(element, 'mouseover', noop)); } this._activeTrigger[TRIGGER_CLICK] = false; this._activeTrigger[TRIGGER_FOCUS] = false; this._activeTrigger[TRIGGER_HOVER] = false; const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE); this._queueCallback(complete, this.tip, isAnimated); this._hoverState = ''; } update() { if (this._popper !== null) { this._popper.update(); } } // Protected isWithContent() { return Boolean(this.getTitle()); } getTipElement() { if (this.tip) { return this.tip; } const element = document.createElement('div'); element.innerHTML = this._config.template; const tip = element.children[0]; this.setContent(tip); tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW); this.tip = tip; return this.tip; } setContent(tip) { this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER); } _sanitizeAndSetContent(template, content, selector) { const templateElement = SelectorEngine.findOne(selector, template); if (!content && templateElement) { templateElement.remove(); return; } // we use append for html objects to maintain js events this.setElementContent(templateElement, content); } setElementContent(element, content) { if (element === null) { return; } if (isElement(content)) { content = getElement(content); // content is a DOM node or a jQuery if (this._config.html) { if (content.parentNode !== element) { element.innerHTML = ''; element.append(content); } } else { element.textContent = content.textContent; } return; } if (this._config.html) { if (this._config.sanitize) { content = sanitizeHtml(content, this._config.allowList, this._config.sanitizeFn); } element.innerHTML = content; } else { element.textContent = content; } } getTitle() { const title = this._element.getAttribute('data-bs-original-title') || this._config.title; return this._resolvePossibleFunction(title); } updateAttachment(attachment) { if (attachment === 'right') { return 'end'; } if (attachment === 'left') { return 'start'; } return attachment; } // Private _initializeOnDelegatedTarget(event, context) { return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig()); } _getOffset() { const { offset } = this._config; if (typeof offset === 'string') { return offset.split(',').map(val => Number.parseInt(val, 10)); } if (typeof offset === 'function') { return popperData => offset(popperData, this._element); } return offset; } _resolvePossibleFunction(content) { return typeof content === 'function' ? content.call(this._element) : content; } _getPopperConfig(attachment) { const defaultBsPopperConfig = { placement: attachment, modifiers: [{ name: 'flip', options: { fallbackPlacements: this._config.fallbackPlacements } }, { name: 'offset', options: { offset: this._getOffset() } }, { name: 'preventOverflow', options: { boundary: this._config.boundary } }, { name: 'arrow', options: { element: `.${this.constructor.NAME}-arrow` } }, { name: 'onChange', enabled: true, phase: 'afterWrite', fn: data => this._handlePopperPlacementChange(data) }], onFirstUpdate: data => { if (data.options.placement !== data.placement) { this._handlePopperPlacementChange(data); } } }; return { ...defaultBsPopperConfig, ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) }; } _addAttachmentClass(attachment) { this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`); } _getAttachment(placement) { return AttachmentMap[placement.toUpperCase()]; } _setListeners() { const triggers = this._config.trigger.split(' '); triggers.forEach(trigger => { if (trigger === 'click') { EventHandler.on(this._element, this.constructor.Event.CLICK, this._config.selector, event => this.toggle(event)); } else if (trigger !== TRIGGER_MANUAL) { 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)); } }); this._hideModalHandler = () => { if (this._element) { this.hide(); } }; EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); if (this._config.selector) { this._config = { ...this._config, trigger: 'manual', selector: '' }; } else { this._fixTitle(); } } _fixTitle() { const title = this._element.getAttribute('title'); const originalTitleType = typeof this._element.getAttribute('data-bs-original-title'); if (title || originalTitleType !== 'string') { 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', ''); } } _enter(event, context) { context = this._initializeOnDelegatedTarget(event, context); if (event) { context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true; } if (context.getTipElement().classList.contains(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) { context._hoverState = HOVER_STATE_SHOW; return; } clearTimeout(context._timeout); context._hoverState = HOVER_STATE_SHOW; if (!context._config.delay || !context._config.delay.show) { context.show(); return; } context._timeout = setTimeout(() => { if (context._hoverState === HOVER_STATE_SHOW) { context.show(); } }, context._config.delay.show); } _leave(event, context) { context = this._initializeOnDelegatedTarget(event, context); if (event) { context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget); } if (context._isWithActiveTrigger()) { return; } clearTimeout(context._timeout); context._hoverState = HOVER_STATE_OUT; if (!context._config.delay || !context._config.delay.hide) { context.hide(); return; } context._timeout = setTimeout(() => { if (context._hoverState === HOVER_STATE_OUT) { context.hide(); } }, context._config.delay.hide); } _isWithActiveTrigger() { for (const trigger in this._activeTrigger) { if (this._activeTrigger[trigger]) { return true; } } return false; } _getConfig(config) { const dataAttributes = Manipulator.getDataAttributes(this._element); Object.keys(dataAttributes).forEach(dataAttr => { if (DISALLOWED_ATTRIBUTES.has(dataAttr)) { delete dataAttributes[dataAttr]; } }); config = { ...this.constructor.Default, ...dataAttributes, ...(typeof config === 'object' && config ? config : {}) }; config.container = config.container === false ? document.body : getElement(config.container); 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(); } typeCheckConfig(NAME$1, config, this.constructor.DefaultType); if (config.sanitize) { config.template = sanitizeHtml(config.template, config.allowList, config.sanitizeFn); } return config; } _getDelegateConfig() { const config = {}; for (const key in this._config) { if (this.constructor.Default[key] !== this._config[key]) { config[key] = this._config[key]; } } // In the future can be replaced with: // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]]) // `Object.fromEntries(keysWithDifferentValues)` return config; } _cleanTipClass() { const tip = this.getTipElement(); const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g'); const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex); if (tabClass !== null && tabClass.length > 0) { tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass)); } } _getBasicClassPrefix() { return CLASS_PREFIX$1; } _handlePopperPlacementChange(popperData) { const { state } = popperData; if (!state) { return; } this.tip = state.elements.popper; this._cleanTipClass(); this._addAttachmentClass(this._getAttachment(state.placement)); } _disposePopper() { if (this._popper) { this._popper.destroy(); this._popper = null; } } // Static static jQueryInterface(config) { return this.each(function () { const data = Tooltip.getOrCreateInstance(this, config); if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } }); } } /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Tooltip to jQuery only if jQuery is present */ defineJQueryPlugin(Tooltip); /** * -------------------------------------------------------------------------- * Bootstrap (v5.1.3): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME = 'popover'; const DATA_KEY = 'bs.popover'; const EVENT_KEY = `.${DATA_KEY}`; const CLASS_PREFIX = 'bs-popover'; const Default = { ...Tooltip.Default, placement: 'right', offset: [0, 8], trigger: 'click', content: '', template: '' }; const DefaultType = { ...Tooltip.DefaultType, content: '(string|element|function)' }; const Event = { HIDE: `hide${EVENT_KEY}`, HIDDEN: `hidden${EVENT_KEY}`, SHOW: `show${EVENT_KEY}`, SHOWN: `shown${EVENT_KEY}`, INSERTED: `inserted${EVENT_KEY}`, CLICK: `click${EVENT_KEY}`, FOCUSIN: `focusin${EVENT_KEY}`, FOCUSOUT: `focusout${EVENT_KEY}`, MOUSEENTER: `mouseenter${EVENT_KEY}`, MOUSELEAVE: `mouseleave${EVENT_KEY}` }; const SELECTOR_TITLE = '.popover-header'; const SELECTOR_CONTENT = '.popover-body'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Popover extends Tooltip { // Getters static get Default() { return Default; } static get NAME() { return NAME; } static get Event() { return Event; } static get DefaultType() { return DefaultType; } // Overrides isWithContent() { return this.getTitle() || this._getContent(); } setContent(tip) { this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TITLE); this._sanitizeAndSetContent(tip, this._getContent(), SELECTOR_CONTENT); } // Private _getContent() { return this._resolvePossibleFunction(this._config.content); } _getBasicClassPrefix() { return CLASS_PREFIX; } // Static static jQueryInterface(config) { return this.each(function () { const data = Popover.getOrCreateInstance(this, config); if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } }); } } /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Popover to jQuery only if jQuery is present */ defineJQueryPlugin(Popover); window.bootstrap = window.bootstrap || {}; window.bootstrap.Popover = Popover; window.bootstrap.Tooltip = Tooltip; if (Joomla && Joomla.getOptions) { // Get the elements/configurations from the PHP const tooltips = Joomla.getOptions('bootstrap.tooltip'); const popovers = Joomla.getOptions('bootstrap.popover'); // Initialise the elements if (typeof popovers === 'object' && popovers !== null) { Object.keys(popovers).forEach(popover => { const opt = popovers[popover]; const options = { animation: opt.animation ? opt.animation : true, container: opt.container ? opt.container : false, delay: opt.delay ? opt.delay : 0, html: opt.html ? opt.html : false, placement: opt.placement ? opt.placement : 'top', selector: opt.selector ? opt.selector : false, title: opt.title ? opt.title : '', trigger: opt.trigger ? opt.trigger : 'click', offset: opt.offset ? opt.offset : 0, fallbackPlacement: opt.fallbackPlacement ? opt.fallbackPlacement : 'flip', boundary: opt.boundary ? opt.boundary : 'scrollParent', customClass: opt.customClass ? opt.customClass : '', sanitize: opt.sanitize ? opt.sanitize : true, sanitizeFn: opt.sanitizeFn ? opt.sanitizeFn : null, popperConfig: opt.popperConfig ? opt.popperConfig : null }; if (opt.content) { options.content = opt.content; } if (opt.template) { options.template = opt.template; } if (opt.allowList) { options.allowList = opt.allowList; } const elements = Array.from(document.querySelectorAll(popover)); if (elements.length) { elements.map(el => new window.bootstrap.Popover(el, options)); } }); } // Initialise the elements if (typeof tooltips === 'object' && tooltips !== null) { Object.keys(tooltips).forEach(tooltip => { const opt = tooltips[tooltip]; const options = { animation: opt.animation ? opt.animation : true, container: opt.container ? opt.container : false, delay: opt.delay ? opt.delay : 0, html: opt.html ? opt.html : false, selector: opt.selector ? opt.selector : false, trigger: opt.trigger ? opt.trigger : 'hover focus', fallbackPlacement: opt.fallbackPlacement ? opt.fallbackPlacement : null, boundary: opt.boundary ? opt.boundary : 'clippingParents', title: opt.title ? opt.title : '', customClass: opt.customClass ? opt.customClass : '', sanitize: opt.sanitize ? opt.sanitize : true, sanitizeFn: opt.sanitizeFn ? opt.sanitizeFn : null, popperConfig: opt.popperConfig ? opt.popperConfig : null }; if (opt.placement) { options.placement = opt.placement; } if (opt.template) { options.template = opt.template; } if (opt.allowList) { options.allowList = opt.allowList; } const elements = Array.from(document.querySelectorAll(tooltip)); if (elements.length) { elements.map(el => new window.bootstrap.Tooltip(el, options)); } }); } } export { Popover as P };