| /*! |
| * Bootstrap tooltip.js v5.1.3 (https://getbootstrap.com/) |
| * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| */ |
| (function (global, factory) { |
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) : |
| typeof define === 'function' && define.amd ? define(['@popperjs/core', './dom/data', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) : |
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global.Popper, global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base)); |
| })(this, (function (Popper, Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict'; |
| |
| const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e }; |
| |
| function _interopNamespace(e) { |
| if (e && e.__esModule) return e; |
| const n = Object.create(null); |
| if (e) { |
| for (const k in e) { |
| if (k !== 'default') { |
| const d = Object.getOwnPropertyDescriptor(e, k); |
| Object.defineProperty(n, k, d.get ? d : { |
| enumerable: true, |
| get: () => e[k] |
| }); |
| } |
| } |
| } |
| n.default = e; |
| return Object.freeze(n); |
| } |
| |
| const Popper__namespace = /*#__PURE__*/_interopNamespace(Popper); |
| const Data__default = /*#__PURE__*/_interopDefaultLegacy(Data); |
| const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler); |
| const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator); |
| const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine); |
| const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent); |
| |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap (v5.1.3): util/index.js |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| const MAX_UID = 1000000; |
| |
| 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 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 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 = () => {}; |
| |
| 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; |
| }; |
| } |
| }); |
| }; |
| |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap (v5.1.3): util/sanitizer.js |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']); |
| const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; |
| /** |
| * A pattern that recognizes a commonly useful subset of URLs that are safe. |
| * |
| * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts |
| */ |
| |
| const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i; |
| /** |
| * A pattern that matches safe data URLs. Only matches image, video and audio types. |
| * |
| * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts |
| */ |
| |
| const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; |
| |
| const allowedAttribute = (attribute, allowedAttributeList) => { |
| const attributeName = attribute.nodeName.toLowerCase(); |
| |
| if (allowedAttributeList.includes(attributeName)) { |
| if (uriAttributes.has(attributeName)) { |
| return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)); |
| } |
| |
| return true; |
| } |
| |
| const regExp = allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp); // Check if a regular expression validates the attribute. |
| |
| for (let i = 0, len = regExp.length; i < len; i++) { |
| if (regExp[i].test(attributeName)) { |
| return true; |
| } |
| } |
| |
| return false; |
| }; |
| |
| const DefaultAllowlist = { |
| // 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: [], |
| img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], |
| li: [], |
| ol: [], |
| p: [], |
| pre: [], |
| s: [], |
| small: [], |
| span: [], |
| sub: [], |
| sup: [], |
| strong: [], |
| u: [], |
| ul: [] |
| }; |
| function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) { |
| if (!unsafeHtml.length) { |
| return unsafeHtml; |
| } |
| |
| if (sanitizeFn && typeof sanitizeFn === 'function') { |
| return sanitizeFn(unsafeHtml); |
| } |
| |
| const domParser = new window.DOMParser(); |
| const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); |
| const elements = [].concat(...createdDocument.body.querySelectorAll('*')); |
| |
| for (let i = 0, len = elements.length; i < len; i++) { |
| const element = elements[i]; |
| const elementName = element.nodeName.toLowerCase(); |
| |
| if (!Object.keys(allowList).includes(elementName)) { |
| element.remove(); |
| continue; |
| } |
| |
| const attributeList = [].concat(...element.attributes); |
| const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []); |
| attributeList.forEach(attribute => { |
| if (!allowedAttribute(attribute, allowedAttributes)) { |
| element.removeAttribute(attribute.nodeName); |
| } |
| }); |
| } |
| |
| return createdDocument.body.innerHTML; |
| } |
| |
| /** |
| * -------------------------------------------------------------------------- |
| * Bootstrap (v5.1.3): tooltip.js |
| * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
| * -------------------------------------------------------------------------- |
| */ |
| /** |
| * ------------------------------------------------------------------------ |
| * Constants |
| * ------------------------------------------------------------------------ |
| */ |
| |
| const NAME = 'tooltip'; |
| const DATA_KEY = 'bs.tooltip'; |
| const EVENT_KEY = `.${DATA_KEY}`; |
| const CLASS_PREFIX = 'bs-tooltip'; |
| const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); |
| const DefaultType = { |
| 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 = { |
| animation: true, |
| template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>', |
| 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 = { |
| 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 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__default.default { |
| constructor(element, config) { |
| if (typeof Popper__namespace === '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; |
| } |
| |
| static get NAME() { |
| return NAME; |
| } |
| |
| static get Event() { |
| return Event; |
| } |
| |
| static get DefaultType() { |
| return DefaultType; |
| } // 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__default.default.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__default.default.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__default.default.set(tip, this.constructor.DATA_KEY, this); |
| |
| if (!this._element.ownerDocument.documentElement.contains(this.tip)) { |
| container.append(tip); |
| EventHandler__default.default.trigger(this._element, this.constructor.Event.INSERTED); |
| } |
| |
| if (this._popper) { |
| this._popper.update(); |
| } else { |
| this._popper = Popper__namespace.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__default.default.on(element, 'mouseover', noop); |
| }); |
| } |
| |
| const complete = () => { |
| const prevHoverState = this._hoverState; |
| this._hoverState = null; |
| EventHandler__default.default.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__default.default.trigger(this._element, this.constructor.Event.HIDDEN); |
| |
| this._disposePopper(); |
| }; |
| |
| const hideEvent = EventHandler__default.default.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__default.default.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__default.default.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__default.default.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__default.default.on(this._element, eventIn, this._config.selector, event => this._enter(event)); |
| EventHandler__default.default.on(this._element, eventOut, this._config.selector, event => this._leave(event)); |
| } |
| }); |
| |
| this._hideModalHandler = () => { |
| if (this._element) { |
| this.hide(); |
| } |
| }; |
| |
| EventHandler__default.default.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__default.default.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, 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; |
| } |
| |
| _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); |
| |
| return Tooltip; |
| |
| })); |
| //# sourceMappingURL=tooltip.js.map |