source: trip-planner-front/node_modules/bootstrap/js/dist/tooltip.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 29.0 KB
Line 
1/*!
2 * Bootstrap tooltip.js v5.1.3 (https://getbootstrap.com/)
3 * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5 */
6(function (global, factory) {
7 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')) :
8 typeof define === 'function' && define.amd ? define(['@popperjs/core', './dom/data', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
9 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global.Popper, global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base));
10})(this, (function (Popper, Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
11
12 const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
14 function _interopNamespace(e) {
15 if (e && e.__esModule) return e;
16 const n = Object.create(null);
17 if (e) {
18 for (const k in e) {
19 if (k !== 'default') {
20 const d = Object.getOwnPropertyDescriptor(e, k);
21 Object.defineProperty(n, k, d.get ? d : {
22 enumerable: true,
23 get: () => e[k]
24 });
25 }
26 }
27 }
28 n.default = e;
29 return Object.freeze(n);
30 }
31
32 const Popper__namespace = /*#__PURE__*/_interopNamespace(Popper);
33 const Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
34 const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
35 const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
36 const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
37 const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
38
39 /**
40 * --------------------------------------------------------------------------
41 * Bootstrap (v5.1.3): util/index.js
42 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
43 * --------------------------------------------------------------------------
44 */
45 const MAX_UID = 1000000;
46
47 const toType = obj => {
48 if (obj === null || obj === undefined) {
49 return `${obj}`;
50 }
51
52 return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
53 };
54 /**
55 * --------------------------------------------------------------------------
56 * Public Util Api
57 * --------------------------------------------------------------------------
58 */
59
60
61 const getUID = prefix => {
62 do {
63 prefix += Math.floor(Math.random() * MAX_UID);
64 } while (document.getElementById(prefix));
65
66 return prefix;
67 };
68
69 const isElement = obj => {
70 if (!obj || typeof obj !== 'object') {
71 return false;
72 }
73
74 if (typeof obj.jquery !== 'undefined') {
75 obj = obj[0];
76 }
77
78 return typeof obj.nodeType !== 'undefined';
79 };
80
81 const getElement = obj => {
82 if (isElement(obj)) {
83 // it's a jQuery object or a node element
84 return obj.jquery ? obj[0] : obj;
85 }
86
87 if (typeof obj === 'string' && obj.length > 0) {
88 return document.querySelector(obj);
89 }
90
91 return null;
92 };
93
94 const typeCheckConfig = (componentName, config, configTypes) => {
95 Object.keys(configTypes).forEach(property => {
96 const expectedTypes = configTypes[property];
97 const value = config[property];
98 const valueType = value && isElement(value) ? 'element' : toType(value);
99
100 if (!new RegExp(expectedTypes).test(valueType)) {
101 throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
102 }
103 });
104 };
105
106 const findShadowRoot = element => {
107 if (!document.documentElement.attachShadow) {
108 return null;
109 } // Can find the shadow root otherwise it'll return the document
110
111
112 if (typeof element.getRootNode === 'function') {
113 const root = element.getRootNode();
114 return root instanceof ShadowRoot ? root : null;
115 }
116
117 if (element instanceof ShadowRoot) {
118 return element;
119 } // when we don't find a shadow root
120
121
122 if (!element.parentNode) {
123 return null;
124 }
125
126 return findShadowRoot(element.parentNode);
127 };
128
129 const noop = () => {};
130
131 const getjQuery = () => {
132 const {
133 jQuery
134 } = window;
135
136 if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
137 return jQuery;
138 }
139
140 return null;
141 };
142
143 const DOMContentLoadedCallbacks = [];
144
145 const onDOMContentLoaded = callback => {
146 if (document.readyState === 'loading') {
147 // add listener on the first call when the document is in loading state
148 if (!DOMContentLoadedCallbacks.length) {
149 document.addEventListener('DOMContentLoaded', () => {
150 DOMContentLoadedCallbacks.forEach(callback => callback());
151 });
152 }
153
154 DOMContentLoadedCallbacks.push(callback);
155 } else {
156 callback();
157 }
158 };
159
160 const isRTL = () => document.documentElement.dir === 'rtl';
161
162 const defineJQueryPlugin = plugin => {
163 onDOMContentLoaded(() => {
164 const $ = getjQuery();
165 /* istanbul ignore if */
166
167 if ($) {
168 const name = plugin.NAME;
169 const JQUERY_NO_CONFLICT = $.fn[name];
170 $.fn[name] = plugin.jQueryInterface;
171 $.fn[name].Constructor = plugin;
172
173 $.fn[name].noConflict = () => {
174 $.fn[name] = JQUERY_NO_CONFLICT;
175 return plugin.jQueryInterface;
176 };
177 }
178 });
179 };
180
181 /**
182 * --------------------------------------------------------------------------
183 * Bootstrap (v5.1.3): util/sanitizer.js
184 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
185 * --------------------------------------------------------------------------
186 */
187 const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']);
188 const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
189 /**
190 * A pattern that recognizes a commonly useful subset of URLs that are safe.
191 *
192 * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
193 */
194
195 const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i;
196 /**
197 * A pattern that matches safe data URLs. Only matches image, video and audio types.
198 *
199 * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
200 */
201
202 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;
203
204 const allowedAttribute = (attribute, allowedAttributeList) => {
205 const attributeName = attribute.nodeName.toLowerCase();
206
207 if (allowedAttributeList.includes(attributeName)) {
208 if (uriAttributes.has(attributeName)) {
209 return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue));
210 }
211
212 return true;
213 }
214
215 const regExp = allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp); // Check if a regular expression validates the attribute.
216
217 for (let i = 0, len = regExp.length; i < len; i++) {
218 if (regExp[i].test(attributeName)) {
219 return true;
220 }
221 }
222
223 return false;
224 };
225
226 const DefaultAllowlist = {
227 // Global attributes allowed on any supplied element below.
228 '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
229 a: ['target', 'href', 'title', 'rel'],
230 area: [],
231 b: [],
232 br: [],
233 col: [],
234 code: [],
235 div: [],
236 em: [],
237 hr: [],
238 h1: [],
239 h2: [],
240 h3: [],
241 h4: [],
242 h5: [],
243 h6: [],
244 i: [],
245 img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
246 li: [],
247 ol: [],
248 p: [],
249 pre: [],
250 s: [],
251 small: [],
252 span: [],
253 sub: [],
254 sup: [],
255 strong: [],
256 u: [],
257 ul: []
258 };
259 function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
260 if (!unsafeHtml.length) {
261 return unsafeHtml;
262 }
263
264 if (sanitizeFn && typeof sanitizeFn === 'function') {
265 return sanitizeFn(unsafeHtml);
266 }
267
268 const domParser = new window.DOMParser();
269 const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
270 const elements = [].concat(...createdDocument.body.querySelectorAll('*'));
271
272 for (let i = 0, len = elements.length; i < len; i++) {
273 const element = elements[i];
274 const elementName = element.nodeName.toLowerCase();
275
276 if (!Object.keys(allowList).includes(elementName)) {
277 element.remove();
278 continue;
279 }
280
281 const attributeList = [].concat(...element.attributes);
282 const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);
283 attributeList.forEach(attribute => {
284 if (!allowedAttribute(attribute, allowedAttributes)) {
285 element.removeAttribute(attribute.nodeName);
286 }
287 });
288 }
289
290 return createdDocument.body.innerHTML;
291 }
292
293 /**
294 * --------------------------------------------------------------------------
295 * Bootstrap (v5.1.3): tooltip.js
296 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
297 * --------------------------------------------------------------------------
298 */
299 /**
300 * ------------------------------------------------------------------------
301 * Constants
302 * ------------------------------------------------------------------------
303 */
304
305 const NAME = 'tooltip';
306 const DATA_KEY = 'bs.tooltip';
307 const EVENT_KEY = `.${DATA_KEY}`;
308 const CLASS_PREFIX = 'bs-tooltip';
309 const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
310 const DefaultType = {
311 animation: 'boolean',
312 template: 'string',
313 title: '(string|element|function)',
314 trigger: 'string',
315 delay: '(number|object)',
316 html: 'boolean',
317 selector: '(string|boolean)',
318 placement: '(string|function)',
319 offset: '(array|string|function)',
320 container: '(string|element|boolean)',
321 fallbackPlacements: 'array',
322 boundary: '(string|element)',
323 customClass: '(string|function)',
324 sanitize: 'boolean',
325 sanitizeFn: '(null|function)',
326 allowList: 'object',
327 popperConfig: '(null|object|function)'
328 };
329 const AttachmentMap = {
330 AUTO: 'auto',
331 TOP: 'top',
332 RIGHT: isRTL() ? 'left' : 'right',
333 BOTTOM: 'bottom',
334 LEFT: isRTL() ? 'right' : 'left'
335 };
336 const Default = {
337 animation: true,
338 template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
339 trigger: 'hover focus',
340 title: '',
341 delay: 0,
342 html: false,
343 selector: false,
344 placement: 'top',
345 offset: [0, 0],
346 container: false,
347 fallbackPlacements: ['top', 'right', 'bottom', 'left'],
348 boundary: 'clippingParents',
349 customClass: '',
350 sanitize: true,
351 sanitizeFn: null,
352 allowList: DefaultAllowlist,
353 popperConfig: null
354 };
355 const Event = {
356 HIDE: `hide${EVENT_KEY}`,
357 HIDDEN: `hidden${EVENT_KEY}`,
358 SHOW: `show${EVENT_KEY}`,
359 SHOWN: `shown${EVENT_KEY}`,
360 INSERTED: `inserted${EVENT_KEY}`,
361 CLICK: `click${EVENT_KEY}`,
362 FOCUSIN: `focusin${EVENT_KEY}`,
363 FOCUSOUT: `focusout${EVENT_KEY}`,
364 MOUSEENTER: `mouseenter${EVENT_KEY}`,
365 MOUSELEAVE: `mouseleave${EVENT_KEY}`
366 };
367 const CLASS_NAME_FADE = 'fade';
368 const CLASS_NAME_MODAL = 'modal';
369 const CLASS_NAME_SHOW = 'show';
370 const HOVER_STATE_SHOW = 'show';
371 const HOVER_STATE_OUT = 'out';
372 const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
373 const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
374 const EVENT_MODAL_HIDE = 'hide.bs.modal';
375 const TRIGGER_HOVER = 'hover';
376 const TRIGGER_FOCUS = 'focus';
377 const TRIGGER_CLICK = 'click';
378 const TRIGGER_MANUAL = 'manual';
379 /**
380 * ------------------------------------------------------------------------
381 * Class Definition
382 * ------------------------------------------------------------------------
383 */
384
385 class Tooltip extends BaseComponent__default.default {
386 constructor(element, config) {
387 if (typeof Popper__namespace === 'undefined') {
388 throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
389 }
390
391 super(element); // private
392
393 this._isEnabled = true;
394 this._timeout = 0;
395 this._hoverState = '';
396 this._activeTrigger = {};
397 this._popper = null; // Protected
398
399 this._config = this._getConfig(config);
400 this.tip = null;
401
402 this._setListeners();
403 } // Getters
404
405
406 static get Default() {
407 return Default;
408 }
409
410 static get NAME() {
411 return NAME;
412 }
413
414 static get Event() {
415 return Event;
416 }
417
418 static get DefaultType() {
419 return DefaultType;
420 } // Public
421
422
423 enable() {
424 this._isEnabled = true;
425 }
426
427 disable() {
428 this._isEnabled = false;
429 }
430
431 toggleEnabled() {
432 this._isEnabled = !this._isEnabled;
433 }
434
435 toggle(event) {
436 if (!this._isEnabled) {
437 return;
438 }
439
440 if (event) {
441 const context = this._initializeOnDelegatedTarget(event);
442
443 context._activeTrigger.click = !context._activeTrigger.click;
444
445 if (context._isWithActiveTrigger()) {
446 context._enter(null, context);
447 } else {
448 context._leave(null, context);
449 }
450 } else {
451 if (this.getTipElement().classList.contains(CLASS_NAME_SHOW)) {
452 this._leave(null, this);
453
454 return;
455 }
456
457 this._enter(null, this);
458 }
459 }
460
461 dispose() {
462 clearTimeout(this._timeout);
463 EventHandler__default.default.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
464
465 if (this.tip) {
466 this.tip.remove();
467 }
468
469 this._disposePopper();
470
471 super.dispose();
472 }
473
474 show() {
475 if (this._element.style.display === 'none') {
476 throw new Error('Please use show on visible elements');
477 }
478
479 if (!(this.isWithContent() && this._isEnabled)) {
480 return;
481 }
482
483 const showEvent = EventHandler__default.default.trigger(this._element, this.constructor.Event.SHOW);
484 const shadowRoot = findShadowRoot(this._element);
485 const isInTheDom = shadowRoot === null ? this._element.ownerDocument.documentElement.contains(this._element) : shadowRoot.contains(this._element);
486
487 if (showEvent.defaultPrevented || !isInTheDom) {
488 return;
489 } // A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title`
490 // This will be removed later in favor of a `setContent` method
491
492
493 if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) {
494 this._disposePopper();
495
496 this.tip.remove();
497 this.tip = null;
498 }
499
500 const tip = this.getTipElement();
501 const tipId = getUID(this.constructor.NAME);
502 tip.setAttribute('id', tipId);
503
504 this._element.setAttribute('aria-describedby', tipId);
505
506 if (this._config.animation) {
507 tip.classList.add(CLASS_NAME_FADE);
508 }
509
510 const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;
511
512 const attachment = this._getAttachment(placement);
513
514 this._addAttachmentClass(attachment);
515
516 const {
517 container
518 } = this._config;
519 Data__default.default.set(tip, this.constructor.DATA_KEY, this);
520
521 if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
522 container.append(tip);
523 EventHandler__default.default.trigger(this._element, this.constructor.Event.INSERTED);
524 }
525
526 if (this._popper) {
527 this._popper.update();
528 } else {
529 this._popper = Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
530 }
531
532 tip.classList.add(CLASS_NAME_SHOW);
533
534 const customClass = this._resolvePossibleFunction(this._config.customClass);
535
536 if (customClass) {
537 tip.classList.add(...customClass.split(' '));
538 } // If this is a touch-enabled device we add extra
539 // empty mouseover listeners to the body's immediate children;
540 // only needed because of broken event delegation on iOS
541 // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
542
543
544 if ('ontouchstart' in document.documentElement) {
545 [].concat(...document.body.children).forEach(element => {
546 EventHandler__default.default.on(element, 'mouseover', noop);
547 });
548 }
549
550 const complete = () => {
551 const prevHoverState = this._hoverState;
552 this._hoverState = null;
553 EventHandler__default.default.trigger(this._element, this.constructor.Event.SHOWN);
554
555 if (prevHoverState === HOVER_STATE_OUT) {
556 this._leave(null, this);
557 }
558 };
559
560 const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
561
562 this._queueCallback(complete, this.tip, isAnimated);
563 }
564
565 hide() {
566 if (!this._popper) {
567 return;
568 }
569
570 const tip = this.getTipElement();
571
572 const complete = () => {
573 if (this._isWithActiveTrigger()) {
574 return;
575 }
576
577 if (this._hoverState !== HOVER_STATE_SHOW) {
578 tip.remove();
579 }
580
581 this._cleanTipClass();
582
583 this._element.removeAttribute('aria-describedby');
584
585 EventHandler__default.default.trigger(this._element, this.constructor.Event.HIDDEN);
586
587 this._disposePopper();
588 };
589
590 const hideEvent = EventHandler__default.default.trigger(this._element, this.constructor.Event.HIDE);
591
592 if (hideEvent.defaultPrevented) {
593 return;
594 }
595
596 tip.classList.remove(CLASS_NAME_SHOW); // If this is a touch-enabled device we remove the extra
597 // empty mouseover listeners we added for iOS support
598
599 if ('ontouchstart' in document.documentElement) {
600 [].concat(...document.body.children).forEach(element => EventHandler__default.default.off(element, 'mouseover', noop));
601 }
602
603 this._activeTrigger[TRIGGER_CLICK] = false;
604 this._activeTrigger[TRIGGER_FOCUS] = false;
605 this._activeTrigger[TRIGGER_HOVER] = false;
606 const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
607
608 this._queueCallback(complete, this.tip, isAnimated);
609
610 this._hoverState = '';
611 }
612
613 update() {
614 if (this._popper !== null) {
615 this._popper.update();
616 }
617 } // Protected
618
619
620 isWithContent() {
621 return Boolean(this.getTitle());
622 }
623
624 getTipElement() {
625 if (this.tip) {
626 return this.tip;
627 }
628
629 const element = document.createElement('div');
630 element.innerHTML = this._config.template;
631 const tip = element.children[0];
632 this.setContent(tip);
633 tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
634 this.tip = tip;
635 return this.tip;
636 }
637
638 setContent(tip) {
639 this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER);
640 }
641
642 _sanitizeAndSetContent(template, content, selector) {
643 const templateElement = SelectorEngine__default.default.findOne(selector, template);
644
645 if (!content && templateElement) {
646 templateElement.remove();
647 return;
648 } // we use append for html objects to maintain js events
649
650
651 this.setElementContent(templateElement, content);
652 }
653
654 setElementContent(element, content) {
655 if (element === null) {
656 return;
657 }
658
659 if (isElement(content)) {
660 content = getElement(content); // content is a DOM node or a jQuery
661
662 if (this._config.html) {
663 if (content.parentNode !== element) {
664 element.innerHTML = '';
665 element.append(content);
666 }
667 } else {
668 element.textContent = content.textContent;
669 }
670
671 return;
672 }
673
674 if (this._config.html) {
675 if (this._config.sanitize) {
676 content = sanitizeHtml(content, this._config.allowList, this._config.sanitizeFn);
677 }
678
679 element.innerHTML = content;
680 } else {
681 element.textContent = content;
682 }
683 }
684
685 getTitle() {
686 const title = this._element.getAttribute('data-bs-original-title') || this._config.title;
687
688 return this._resolvePossibleFunction(title);
689 }
690
691 updateAttachment(attachment) {
692 if (attachment === 'right') {
693 return 'end';
694 }
695
696 if (attachment === 'left') {
697 return 'start';
698 }
699
700 return attachment;
701 } // Private
702
703
704 _initializeOnDelegatedTarget(event, context) {
705 return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
706 }
707
708 _getOffset() {
709 const {
710 offset
711 } = this._config;
712
713 if (typeof offset === 'string') {
714 return offset.split(',').map(val => Number.parseInt(val, 10));
715 }
716
717 if (typeof offset === 'function') {
718 return popperData => offset(popperData, this._element);
719 }
720
721 return offset;
722 }
723
724 _resolvePossibleFunction(content) {
725 return typeof content === 'function' ? content.call(this._element) : content;
726 }
727
728 _getPopperConfig(attachment) {
729 const defaultBsPopperConfig = {
730 placement: attachment,
731 modifiers: [{
732 name: 'flip',
733 options: {
734 fallbackPlacements: this._config.fallbackPlacements
735 }
736 }, {
737 name: 'offset',
738 options: {
739 offset: this._getOffset()
740 }
741 }, {
742 name: 'preventOverflow',
743 options: {
744 boundary: this._config.boundary
745 }
746 }, {
747 name: 'arrow',
748 options: {
749 element: `.${this.constructor.NAME}-arrow`
750 }
751 }, {
752 name: 'onChange',
753 enabled: true,
754 phase: 'afterWrite',
755 fn: data => this._handlePopperPlacementChange(data)
756 }],
757 onFirstUpdate: data => {
758 if (data.options.placement !== data.placement) {
759 this._handlePopperPlacementChange(data);
760 }
761 }
762 };
763 return { ...defaultBsPopperConfig,
764 ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
765 };
766 }
767
768 _addAttachmentClass(attachment) {
769 this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`);
770 }
771
772 _getAttachment(placement) {
773 return AttachmentMap[placement.toUpperCase()];
774 }
775
776 _setListeners() {
777 const triggers = this._config.trigger.split(' ');
778
779 triggers.forEach(trigger => {
780 if (trigger === 'click') {
781 EventHandler__default.default.on(this._element, this.constructor.Event.CLICK, this._config.selector, event => this.toggle(event));
782 } else if (trigger !== TRIGGER_MANUAL) {
783 const eventIn = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSEENTER : this.constructor.Event.FOCUSIN;
784 const eventOut = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSELEAVE : this.constructor.Event.FOCUSOUT;
785 EventHandler__default.default.on(this._element, eventIn, this._config.selector, event => this._enter(event));
786 EventHandler__default.default.on(this._element, eventOut, this._config.selector, event => this._leave(event));
787 }
788 });
789
790 this._hideModalHandler = () => {
791 if (this._element) {
792 this.hide();
793 }
794 };
795
796 EventHandler__default.default.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
797
798 if (this._config.selector) {
799 this._config = { ...this._config,
800 trigger: 'manual',
801 selector: ''
802 };
803 } else {
804 this._fixTitle();
805 }
806 }
807
808 _fixTitle() {
809 const title = this._element.getAttribute('title');
810
811 const originalTitleType = typeof this._element.getAttribute('data-bs-original-title');
812
813 if (title || originalTitleType !== 'string') {
814 this._element.setAttribute('data-bs-original-title', title || '');
815
816 if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) {
817 this._element.setAttribute('aria-label', title);
818 }
819
820 this._element.setAttribute('title', '');
821 }
822 }
823
824 _enter(event, context) {
825 context = this._initializeOnDelegatedTarget(event, context);
826
827 if (event) {
828 context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
829 }
830
831 if (context.getTipElement().classList.contains(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {
832 context._hoverState = HOVER_STATE_SHOW;
833 return;
834 }
835
836 clearTimeout(context._timeout);
837 context._hoverState = HOVER_STATE_SHOW;
838
839 if (!context._config.delay || !context._config.delay.show) {
840 context.show();
841 return;
842 }
843
844 context._timeout = setTimeout(() => {
845 if (context._hoverState === HOVER_STATE_SHOW) {
846 context.show();
847 }
848 }, context._config.delay.show);
849 }
850
851 _leave(event, context) {
852 context = this._initializeOnDelegatedTarget(event, context);
853
854 if (event) {
855 context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
856 }
857
858 if (context._isWithActiveTrigger()) {
859 return;
860 }
861
862 clearTimeout(context._timeout);
863 context._hoverState = HOVER_STATE_OUT;
864
865 if (!context._config.delay || !context._config.delay.hide) {
866 context.hide();
867 return;
868 }
869
870 context._timeout = setTimeout(() => {
871 if (context._hoverState === HOVER_STATE_OUT) {
872 context.hide();
873 }
874 }, context._config.delay.hide);
875 }
876
877 _isWithActiveTrigger() {
878 for (const trigger in this._activeTrigger) {
879 if (this._activeTrigger[trigger]) {
880 return true;
881 }
882 }
883
884 return false;
885 }
886
887 _getConfig(config) {
888 const dataAttributes = Manipulator__default.default.getDataAttributes(this._element);
889 Object.keys(dataAttributes).forEach(dataAttr => {
890 if (DISALLOWED_ATTRIBUTES.has(dataAttr)) {
891 delete dataAttributes[dataAttr];
892 }
893 });
894 config = { ...this.constructor.Default,
895 ...dataAttributes,
896 ...(typeof config === 'object' && config ? config : {})
897 };
898 config.container = config.container === false ? document.body : getElement(config.container);
899
900 if (typeof config.delay === 'number') {
901 config.delay = {
902 show: config.delay,
903 hide: config.delay
904 };
905 }
906
907 if (typeof config.title === 'number') {
908 config.title = config.title.toString();
909 }
910
911 if (typeof config.content === 'number') {
912 config.content = config.content.toString();
913 }
914
915 typeCheckConfig(NAME, config, this.constructor.DefaultType);
916
917 if (config.sanitize) {
918 config.template = sanitizeHtml(config.template, config.allowList, config.sanitizeFn);
919 }
920
921 return config;
922 }
923
924 _getDelegateConfig() {
925 const config = {};
926
927 for (const key in this._config) {
928 if (this.constructor.Default[key] !== this._config[key]) {
929 config[key] = this._config[key];
930 }
931 } // In the future can be replaced with:
932 // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
933 // `Object.fromEntries(keysWithDifferentValues)`
934
935
936 return config;
937 }
938
939 _cleanTipClass() {
940 const tip = this.getTipElement();
941 const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g');
942 const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex);
943
944 if (tabClass !== null && tabClass.length > 0) {
945 tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass));
946 }
947 }
948
949 _getBasicClassPrefix() {
950 return CLASS_PREFIX;
951 }
952
953 _handlePopperPlacementChange(popperData) {
954 const {
955 state
956 } = popperData;
957
958 if (!state) {
959 return;
960 }
961
962 this.tip = state.elements.popper;
963
964 this._cleanTipClass();
965
966 this._addAttachmentClass(this._getAttachment(state.placement));
967 }
968
969 _disposePopper() {
970 if (this._popper) {
971 this._popper.destroy();
972
973 this._popper = null;
974 }
975 } // Static
976
977
978 static jQueryInterface(config) {
979 return this.each(function () {
980 const data = Tooltip.getOrCreateInstance(this, config);
981
982 if (typeof config === 'string') {
983 if (typeof data[config] === 'undefined') {
984 throw new TypeError(`No method named "${config}"`);
985 }
986
987 data[config]();
988 }
989 });
990 }
991
992 }
993 /**
994 * ------------------------------------------------------------------------
995 * jQuery
996 * ------------------------------------------------------------------------
997 * add .Tooltip to jQuery only if jQuery is present
998 */
999
1000
1001 defineJQueryPlugin(Tooltip);
1002
1003 return Tooltip;
1004
1005}));
1006//# sourceMappingURL=tooltip.js.map
Note: See TracBrowser for help on using the repository browser.