source: imaps-frontend/node_modules/bootstrap/js/dist/tooltip.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 18.0 KB
RevLine 
[d565449]1/*!
2 * Bootstrap tooltip.js v5.3.3 (https://getbootstrap.com/)
3 * Copyright 2011-2024 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('./base-component.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./util/index.js'), require('./util/sanitizer.js'), require('./util/template-factory.js')) :
8 typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/event-handler', './dom/manipulator', './util/index', './util/sanitizer', './util/template-factory'], factory) :
9 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global["@popperjs/core"], global.BaseComponent, global.EventHandler, global.Manipulator, global.Index, global.Sanitizer, global.TemplateFactory));
10})(this, (function (Popper, BaseComponent, EventHandler, Manipulator, index_js, sanitizer_js, TemplateFactory) { 'use strict';
11
12 function _interopNamespaceDefault(e) {
13 const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
14 if (e) {
15 for (const k in e) {
16 if (k !== 'default') {
17 const d = Object.getOwnPropertyDescriptor(e, k);
18 Object.defineProperty(n, k, d.get ? d : {
19 enumerable: true,
20 get: () => e[k]
21 });
22 }
23 }
24 }
25 n.default = e;
26 return Object.freeze(n);
27 }
28
29 const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper);
30
31 /**
32 * --------------------------------------------------------------------------
33 * Bootstrap tooltip.js
34 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
35 * --------------------------------------------------------------------------
36 */
37
38
39 /**
40 * Constants
41 */
42
43 const NAME = 'tooltip';
44 const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
45 const CLASS_NAME_FADE = 'fade';
46 const CLASS_NAME_MODAL = 'modal';
47 const CLASS_NAME_SHOW = 'show';
48 const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
49 const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
50 const EVENT_MODAL_HIDE = 'hide.bs.modal';
51 const TRIGGER_HOVER = 'hover';
52 const TRIGGER_FOCUS = 'focus';
53 const TRIGGER_CLICK = 'click';
54 const TRIGGER_MANUAL = 'manual';
55 const EVENT_HIDE = 'hide';
56 const EVENT_HIDDEN = 'hidden';
57 const EVENT_SHOW = 'show';
58 const EVENT_SHOWN = 'shown';
59 const EVENT_INSERTED = 'inserted';
60 const EVENT_CLICK = 'click';
61 const EVENT_FOCUSIN = 'focusin';
62 const EVENT_FOCUSOUT = 'focusout';
63 const EVENT_MOUSEENTER = 'mouseenter';
64 const EVENT_MOUSELEAVE = 'mouseleave';
65 const AttachmentMap = {
66 AUTO: 'auto',
67 TOP: 'top',
68 RIGHT: index_js.isRTL() ? 'left' : 'right',
69 BOTTOM: 'bottom',
70 LEFT: index_js.isRTL() ? 'right' : 'left'
71 };
72 const Default = {
73 allowList: sanitizer_js.DefaultAllowlist,
74 animation: true,
75 boundary: 'clippingParents',
76 container: false,
77 customClass: '',
78 delay: 0,
79 fallbackPlacements: ['top', 'right', 'bottom', 'left'],
80 html: false,
81 offset: [0, 6],
82 placement: 'top',
83 popperConfig: null,
84 sanitize: true,
85 sanitizeFn: null,
86 selector: false,
87 template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
88 title: '',
89 trigger: 'hover focus'
90 };
91 const DefaultType = {
92 allowList: 'object',
93 animation: 'boolean',
94 boundary: '(string|element)',
95 container: '(string|element|boolean)',
96 customClass: '(string|function)',
97 delay: '(number|object)',
98 fallbackPlacements: 'array',
99 html: 'boolean',
100 offset: '(array|string|function)',
101 placement: '(string|function)',
102 popperConfig: '(null|object|function)',
103 sanitize: 'boolean',
104 sanitizeFn: '(null|function)',
105 selector: '(string|boolean)',
106 template: 'string',
107 title: '(string|element|function)',
108 trigger: 'string'
109 };
110
111 /**
112 * Class definition
113 */
114
115 class Tooltip extends BaseComponent {
116 constructor(element, config) {
117 if (typeof Popper__namespace === 'undefined') {
118 throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
119 }
120 super(element, config);
121
122 // Private
123 this._isEnabled = true;
124 this._timeout = 0;
125 this._isHovered = null;
126 this._activeTrigger = {};
127 this._popper = null;
128 this._templateFactory = null;
129 this._newContent = null;
130
131 // Protected
132 this.tip = null;
133 this._setListeners();
134 if (!this._config.selector) {
135 this._fixTitle();
136 }
137 }
138
139 // Getters
140 static get Default() {
141 return Default;
142 }
143 static get DefaultType() {
144 return DefaultType;
145 }
146 static get NAME() {
147 return NAME;
148 }
149
150 // Public
151 enable() {
152 this._isEnabled = true;
153 }
154 disable() {
155 this._isEnabled = false;
156 }
157 toggleEnabled() {
158 this._isEnabled = !this._isEnabled;
159 }
160 toggle() {
161 if (!this._isEnabled) {
162 return;
163 }
164 this._activeTrigger.click = !this._activeTrigger.click;
165 if (this._isShown()) {
166 this._leave();
167 return;
168 }
169 this._enter();
170 }
171 dispose() {
172 clearTimeout(this._timeout);
173 EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
174 if (this._element.getAttribute('data-bs-original-title')) {
175 this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'));
176 }
177 this._disposePopper();
178 super.dispose();
179 }
180 show() {
181 if (this._element.style.display === 'none') {
182 throw new Error('Please use show on visible elements');
183 }
184 if (!(this._isWithContent() && this._isEnabled)) {
185 return;
186 }
187 const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW));
188 const shadowRoot = index_js.findShadowRoot(this._element);
189 const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);
190 if (showEvent.defaultPrevented || !isInTheDom) {
191 return;
192 }
193
194 // TODO: v6 remove this or make it optional
195 this._disposePopper();
196 const tip = this._getTipElement();
197 this._element.setAttribute('aria-describedby', tip.getAttribute('id'));
198 const {
199 container
200 } = this._config;
201 if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
202 container.append(tip);
203 EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));
204 }
205 this._popper = this._createPopper(tip);
206 tip.classList.add(CLASS_NAME_SHOW);
207
208 // If this is a touch-enabled device we add extra
209 // empty mouseover listeners to the body's immediate children;
210 // only needed because of broken event delegation on iOS
211 // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
212 if ('ontouchstart' in document.documentElement) {
213 for (const element of [].concat(...document.body.children)) {
214 EventHandler.on(element, 'mouseover', index_js.noop);
215 }
216 }
217 const complete = () => {
218 EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN));
219 if (this._isHovered === false) {
220 this._leave();
221 }
222 this._isHovered = false;
223 };
224 this._queueCallback(complete, this.tip, this._isAnimated());
225 }
226 hide() {
227 if (!this._isShown()) {
228 return;
229 }
230 const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE));
231 if (hideEvent.defaultPrevented) {
232 return;
233 }
234 const tip = this._getTipElement();
235 tip.classList.remove(CLASS_NAME_SHOW);
236
237 // If this is a touch-enabled device we remove the extra
238 // empty mouseover listeners we added for iOS support
239 if ('ontouchstart' in document.documentElement) {
240 for (const element of [].concat(...document.body.children)) {
241 EventHandler.off(element, 'mouseover', index_js.noop);
242 }
243 }
244 this._activeTrigger[TRIGGER_CLICK] = false;
245 this._activeTrigger[TRIGGER_FOCUS] = false;
246 this._activeTrigger[TRIGGER_HOVER] = false;
247 this._isHovered = null; // it is a trick to support manual triggering
248
249 const complete = () => {
250 if (this._isWithActiveTrigger()) {
251 return;
252 }
253 if (!this._isHovered) {
254 this._disposePopper();
255 }
256 this._element.removeAttribute('aria-describedby');
257 EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN));
258 };
259 this._queueCallback(complete, this.tip, this._isAnimated());
260 }
261 update() {
262 if (this._popper) {
263 this._popper.update();
264 }
265 }
266
267 // Protected
268 _isWithContent() {
269 return Boolean(this._getTitle());
270 }
271 _getTipElement() {
272 if (!this.tip) {
273 this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());
274 }
275 return this.tip;
276 }
277 _createTipElement(content) {
278 const tip = this._getTemplateFactory(content).toHtml();
279
280 // TODO: remove this check in v6
281 if (!tip) {
282 return null;
283 }
284 tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
285 // TODO: v6 the following can be achieved with CSS only
286 tip.classList.add(`bs-${this.constructor.NAME}-auto`);
287 const tipId = index_js.getUID(this.constructor.NAME).toString();
288 tip.setAttribute('id', tipId);
289 if (this._isAnimated()) {
290 tip.classList.add(CLASS_NAME_FADE);
291 }
292 return tip;
293 }
294 setContent(content) {
295 this._newContent = content;
296 if (this._isShown()) {
297 this._disposePopper();
298 this.show();
299 }
300 }
301 _getTemplateFactory(content) {
302 if (this._templateFactory) {
303 this._templateFactory.changeContent(content);
304 } else {
305 this._templateFactory = new TemplateFactory({
306 ...this._config,
307 // the `content` var has to be after `this._config`
308 // to override config.content in case of popover
309 content,
310 extraClass: this._resolvePossibleFunction(this._config.customClass)
311 });
312 }
313 return this._templateFactory;
314 }
315 _getContentForTemplate() {
316 return {
317 [SELECTOR_TOOLTIP_INNER]: this._getTitle()
318 };
319 }
320 _getTitle() {
321 return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title');
322 }
323
324 // Private
325 _initializeOnDelegatedTarget(event) {
326 return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
327 }
328 _isAnimated() {
329 return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE);
330 }
331 _isShown() {
332 return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW);
333 }
334 _createPopper(tip) {
335 const placement = index_js.execute(this._config.placement, [this, tip, this._element]);
336 const attachment = AttachmentMap[placement.toUpperCase()];
337 return Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
338 }
339 _getOffset() {
340 const {
341 offset
342 } = this._config;
343 if (typeof offset === 'string') {
344 return offset.split(',').map(value => Number.parseInt(value, 10));
345 }
346 if (typeof offset === 'function') {
347 return popperData => offset(popperData, this._element);
348 }
349 return offset;
350 }
351 _resolvePossibleFunction(arg) {
352 return index_js.execute(arg, [this._element]);
353 }
354 _getPopperConfig(attachment) {
355 const defaultBsPopperConfig = {
356 placement: attachment,
357 modifiers: [{
358 name: 'flip',
359 options: {
360 fallbackPlacements: this._config.fallbackPlacements
361 }
362 }, {
363 name: 'offset',
364 options: {
365 offset: this._getOffset()
366 }
367 }, {
368 name: 'preventOverflow',
369 options: {
370 boundary: this._config.boundary
371 }
372 }, {
373 name: 'arrow',
374 options: {
375 element: `.${this.constructor.NAME}-arrow`
376 }
377 }, {
378 name: 'preSetPlacement',
379 enabled: true,
380 phase: 'beforeMain',
381 fn: data => {
382 // Pre-set Popper's placement attribute in order to read the arrow sizes properly.
383 // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
384 this._getTipElement().setAttribute('data-popper-placement', data.state.placement);
385 }
386 }]
387 };
388 return {
389 ...defaultBsPopperConfig,
390 ...index_js.execute(this._config.popperConfig, [defaultBsPopperConfig])
391 };
392 }
393 _setListeners() {
394 const triggers = this._config.trigger.split(' ');
395 for (const trigger of triggers) {
396 if (trigger === 'click') {
397 EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => {
398 const context = this._initializeOnDelegatedTarget(event);
399 context.toggle();
400 });
401 } else if (trigger !== TRIGGER_MANUAL) {
402 const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN);
403 const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT);
404 EventHandler.on(this._element, eventIn, this._config.selector, event => {
405 const context = this._initializeOnDelegatedTarget(event);
406 context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
407 context._enter();
408 });
409 EventHandler.on(this._element, eventOut, this._config.selector, event => {
410 const context = this._initializeOnDelegatedTarget(event);
411 context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
412 context._leave();
413 });
414 }
415 }
416 this._hideModalHandler = () => {
417 if (this._element) {
418 this.hide();
419 }
420 };
421 EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
422 }
423 _fixTitle() {
424 const title = this._element.getAttribute('title');
425 if (!title) {
426 return;
427 }
428 if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {
429 this._element.setAttribute('aria-label', title);
430 }
431 this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility
432 this._element.removeAttribute('title');
433 }
434 _enter() {
435 if (this._isShown() || this._isHovered) {
436 this._isHovered = true;
437 return;
438 }
439 this._isHovered = true;
440 this._setTimeout(() => {
441 if (this._isHovered) {
442 this.show();
443 }
444 }, this._config.delay.show);
445 }
446 _leave() {
447 if (this._isWithActiveTrigger()) {
448 return;
449 }
450 this._isHovered = false;
451 this._setTimeout(() => {
452 if (!this._isHovered) {
453 this.hide();
454 }
455 }, this._config.delay.hide);
456 }
457 _setTimeout(handler, timeout) {
458 clearTimeout(this._timeout);
459 this._timeout = setTimeout(handler, timeout);
460 }
461 _isWithActiveTrigger() {
462 return Object.values(this._activeTrigger).includes(true);
463 }
464 _getConfig(config) {
465 const dataAttributes = Manipulator.getDataAttributes(this._element);
466 for (const dataAttribute of Object.keys(dataAttributes)) {
467 if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
468 delete dataAttributes[dataAttribute];
469 }
470 }
471 config = {
472 ...dataAttributes,
473 ...(typeof config === 'object' && config ? config : {})
474 };
475 config = this._mergeConfigObj(config);
476 config = this._configAfterMerge(config);
477 this._typeCheckConfig(config);
478 return config;
479 }
480 _configAfterMerge(config) {
481 config.container = config.container === false ? document.body : index_js.getElement(config.container);
482 if (typeof config.delay === 'number') {
483 config.delay = {
484 show: config.delay,
485 hide: config.delay
486 };
487 }
488 if (typeof config.title === 'number') {
489 config.title = config.title.toString();
490 }
491 if (typeof config.content === 'number') {
492 config.content = config.content.toString();
493 }
494 return config;
495 }
496 _getDelegateConfig() {
497 const config = {};
498 for (const [key, value] of Object.entries(this._config)) {
499 if (this.constructor.Default[key] !== value) {
500 config[key] = value;
501 }
502 }
503 config.selector = false;
504 config.trigger = 'manual';
505
506 // In the future can be replaced with:
507 // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
508 // `Object.fromEntries(keysWithDifferentValues)`
509 return config;
510 }
511 _disposePopper() {
512 if (this._popper) {
513 this._popper.destroy();
514 this._popper = null;
515 }
516 if (this.tip) {
517 this.tip.remove();
518 this.tip = null;
519 }
520 }
521
522 // Static
523 static jQueryInterface(config) {
524 return this.each(function () {
525 const data = Tooltip.getOrCreateInstance(this, config);
526 if (typeof config !== 'string') {
527 return;
528 }
529 if (typeof data[config] === 'undefined') {
530 throw new TypeError(`No method named "${config}"`);
531 }
532 data[config]();
533 });
534 }
535 }
536
537 /**
538 * jQuery
539 */
540
541 index_js.defineJQueryPlugin(Tooltip);
542
543 return Tooltip;
544
545}));
546//# sourceMappingURL=tooltip.js.map
Note: See TracBrowser for help on using the repository browser.