/*! * Bootstrap tooltip.js v5.1.0 (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'; function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n['default'] = e; return Object.freeze(n); } var Popper__namespace = /*#__PURE__*/_interopNamespace(Popper); var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data); var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler); var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator); var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine); var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent); /** * -------------------------------------------------------------------------- * Bootstrap (v5.1.0): 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.0): util/sanitizer.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const uriAttrs = 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 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts */ const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i; /** * 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 */ 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 = (attr, allowedAttributeList) => { const attrName = attr.nodeName.toLowerCase(); if (allowedAttributeList.includes(attrName)) { if (uriAttrs.has(attrName)) { return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue)); } return true; } const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp); // Check if a regular expression validates the attribute. for (let i = 0, len = regExp.length; i < len; i++) { if (regExp[i].test(attrName)) { 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 allowlistKeys = Object.keys(allowList); const elements = [].concat(...createdDocument.body.querySelectorAll('*')); for (let i = 0, len = elements.length; i < len; i++) { const el = elements[i]; const elName = el.nodeName.toLowerCase(); if (!allowlistKeys.includes(elName)) { el.remove(); continue; } const attributeList = [].concat(...el.attributes); const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []); attributeList.forEach(attr => { if (!allowedAttribute(attr, allowedAttributes)) { el.removeAttribute(attr.nodeName); } }); } return createdDocument.body.innerHTML; } /** * -------------------------------------------------------------------------- * Bootstrap (v5.1.0): 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: '', 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(); } if (this._popper) { this._popper.destroy(); } 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; } 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); if (this._popper) { this._popper.destroy(); this._popper = null; } }; 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)); } // 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