PageSourceSearch

https://doebeln.de/media/vendor/bootstrap/js/popover.js?5.3.8

js doebeln.de collected 2026-10-01 12:39:02 UTC 20,848 bytes, 676 lines download raw bytes

vendor: 17,512 bytes, lines 1-583
1import { P as Popper, c as createPopper } from './popper.js?5.3.8';
2import { c as isRTL, d as defineJQueryPlugin, B as BaseComponent, D as DefaultAllowlist, E as EventHandler, m as findShadowRoot, n as noop, o as getUID, T as TemplateFactory, j as execute, M as Manipulator, g as getElement } from './dom.js?5.3.8';
3
4/**
5 * --------------------------------------------------------------------------
6 * Bootstrap tooltip.js
7 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
8 * --------------------------------------------------------------------------
9 */
10
11
12/**
13 * Constants
14 */
15
16const NAME$1 = 'tooltip';
17const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
18const CLASS_NAME_FADE = 'fade';
19const CLASS_NAME_MODAL = 'modal';
20const CLASS_NAME_SHOW = 'show';
21const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
22const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
23const EVENT_MODAL_HIDE = 'hide.bs.modal';
24const TRIGGER_HOVER = 'hover';
25const TRIGGER_FOCUS = 'focus';
26const TRIGGER_CLICK = 'click';
27const TRIGGER_MANUAL = 'manual';
28const EVENT_HIDE = 'hide';
29const EVENT_HIDDEN = 'hidden';
30const EVENT_SHOW = 'show';
31const EVENT_SHOWN = 'shown';
32const EVENT_INSERTED = 'inserted';
33const EVENT_CLICK = 'click';
34const EVENT_FOCUSIN = 'focusin';
35const EVENT_FOCUSOUT = 'focusout';
36const EVENT_MOUSEENTER = 'mouseenter';
37const EVENT_MOUSELEAVE = 'mouseleave';
38const AttachmentMap = {
39  AUTO: 'auto',
40  TOP: 'top',
41  RIGHT: isRTL() ? 'left' : 'right',
42  BOTTOM: 'bottom',
43  LEFT: isRTL() ? 'right' : 'left'
44};
45const Default$1 = {
46  allowList: DefaultAllowlist,
47  animation: true,
48  boundary: 'clippingParents',
49  container: false,
50  customClass: '',
51  delay: 0,
52  fallbackPlacements: ['top', 'right', 'bottom', 'left'],
53  html: false,
54  offset: [0, 6],
55  placement: 'top',
56  popperConfig: null,
57  sanitize: true,
58  sanitizeFn: null,
59  selector: false,
60  template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
61  title: '',
62  trigger: 'hover focus'
63};
64const DefaultType$1 = {
65  allowList: 'object',
66  animation: 'boolean',
67  boundary: '(string|element)',
68  container: '(string|element|boolean)',
69  customClass: '(string|function)',
70  delay: '(number|object)',
71  fallbackPlacements: 'array',
72  html: 'boolean',
73  offset: '(array|string|function)',
74  placement: '(string|function)',
75  popperConfig: '(null|object|function)',
76  sanitize: 'boolean',
77  sanitizeFn: '(null|function)',
78  selector: '(string|boolean)',
79  template: 'string',
80  title: '(string|element|function)',
81  trigger: 'string'
82};
83
84/**
85 * Class definition
86 */
87
88class Tooltip extends BaseComponent {
89  constructor(element, config) {
90    if (typeof Popper === 'undefined') {
91      throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org/docs/v2/)');
92    }
93    super(element, config);
94
95    // Private
96    this._isEnabled = true;
97    this._timeout = 0;
98    this._isHovered = null;
99    this._activeTrigger = {};
100    this._popper = null;
101    this._templateFactory = null;
102    this._newContent = null;
103
104    // Protected
105    this.tip = null;
106    this._setListeners();
107    if (!this._config.selector) {
108      this._fixTitle();
109    }
110  }
111
112  // Getters
113  static get Default() {
114    return Default$1;
115  }
116  static get DefaultType() {
117    return DefaultType$1;
118  }
119  static get NAME() {
120    return NAME$1;
121  }
122
123  // Public
124  enable() {
125    this._isEnabled = true;
126  }
127  disable() {
128    this._isEnabled = false;
129  }
130  toggleEnabled() {
131    this._isEnabled = !this._isEnabled;
132  }
133  toggle() {
134    if (!this._isEnabled) {
135      return;
136    }
137    if (this._isShown()) {
138      this._leave();
139      return;
140    }
141    this._enter();
142  }
143  dispose() {
144    clearTimeout(this._timeout);
145    EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
146    if (this._element.getAttribute('data-bs-original-title')) {
147      this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'));
148    }
149    this._disposePopper();
150    super.dispose();
151  }
152  show() {
153    if (this._element.style.display === 'none') {
154      throw new Error('Please use show on visible elements');
155    }
156    if (!(this._isWithContent() && this._isEnabled)) {
157      return;
158    }
159    const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW));
160    const shadowRoot = findShadowRoot(this._element);
161    const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);
162    if (showEvent.defaultPrevented || !isInTheDom) {
163      return;
164    }
165
166    // TODO: v6 remove this or make it optional
167    this._disposePopper();
168    const tip = this._getTipElement();
169    this._element.setAttribute('aria-describedby', tip.getAttribute('id'));
170    const {
171      container
172    } = this._config;
173    if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
174      container.append(tip);
175      EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));
176    }
177    this._popper = this._createPopper(tip);
178    tip.classList.add(CLASS_NAME_SHOW);
179
180    // If this is a touch-enabled device we add extra
181    // empty mouseover listeners to the body's immediate children;
182    // only needed because of broken event delegation on iOS
183    // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
184    if ('ontouchstart' in document.documentElement) {
185      for (const element of [].concat(...document.body.children)) {
186        EventHandler.on(element, 'mouseover', noop);
187      }
188    }
189    const complete = () => {
190      EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN));
191      if (this._isHovered === false) {
192        this._leave();
193      }
194      this._isHovered = false;
195    };
196    this._queueCallback(complete, this.tip, this._isAnimated());
197  }
198  hide() {
199    if (!this._isShown()) {
200      return;
201    }
202    const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE));
203    if (hideEvent.defaultPrevented) {
204      return;
205    }
206    const tip = this._getTipElement();
207    tip.classList.remove(CLASS_NAME_SHOW);
208
209    // If this is a touch-enabled device we remove the extra
210    // empty mouseover listeners we added for iOS support
211    if ('ontouchstart' in document.documentElement) {
212      for (const element of [].concat(...document.body.children)) {
213        EventHandler.off(element, 'mouseover', noop);
214      }
215    }
216    this._activeTrigger[TRIGGER_CLICK] = false;
217    this._activeTrigger[TRIGGER_FOCUS] = false;
218    this._activeTrigger[TRIGGER_HOVER] = false;
219    this._isHovered = null; // it is a trick to support manual triggering
220
221    const complete = () => {
222      if (this._isWithActiveTrigger()) {
223        return;
224      }
225      if (!this._isHovered) {
226        this._disposePopper();
227      }
228      this._element.removeAttribute('aria-describedby');
229      EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN));
230    };
231    this._queueCallback(complete, this.tip, this._isAnimated());
232  }
233  update() {
234    if (this._popper) {
235      this._popper.update();
236    }
237  }
238
239  // Protected
240  _isWithContent() {
241    return Boolean(this._getTitle());
242  }
243  _getTipElement() {
244    if (!this.tip) {
245      this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());
246    }
247    return this.tip;
248  }
249  _createTipElement(content) {
250    const tip = this._getTemplateFactory(content).toHtml();
251
252    // TODO: remove this check in v6
253    if (!tip) {
254      return null;
255    }
256    tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
257    // TODO: v6 the following can be achieved with CSS only
258    tip.classList.add(`bs-${this.constructor.NAME}-auto`);
259    const tipId = getUID(this.constructor.NAME).toString();
260    tip.setAttribute('id', tipId);
261    if (this._isAnimated()) {
262      tip.classList.add(CLASS_NAME_FADE);
263    }
264    return tip;
265  }
266  setContent(content) {
267    this._newContent = content;
268    if (this._isShown()) {
269      this._disposePopper();
270      this.show();
271    }
272  }
273  _getTemplateFactory(content) {
274    if (this._templateFactory) {
275      this._templateFactory.changeContent(content);
276    } else {
277      this._templateFactory = new TemplateFactory({
278        ...this._config,
279        // the `content` var has to be after `this._config`
280        // to override config.content in case of popover
281        content,
282        extraClass: this._resolvePossibleFunction(this._config.customClass)
283      });
284    }
285    return this._templateFactory;
286  }
287  _getContentForTemplate() {
288    return {
289      [SELECTOR_TOOLTIP_INNER]: this._getTitle()
290    };
291  }
292  _getTitle() {
293    return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title');
294  }
295
296  // Private
297  _initializeOnDelegatedTarget(event) {
298    return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
299  }
300  _isAnimated() {
301    return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE);
302  }
303  _isShown() {
304    return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW);
305  }
306  _createPopper(tip) {
307    const placement = execute(this._config.placement, [this, tip, this._element]);
308    const attachment = AttachmentMap[placement.toUpperCase()];
309    return createPopper(this._element, tip, this._getPopperConfig(attachment));
310  }
311  _getOffset() {
312    const {
313      offset
314    } = this._config;
315    if (typeof offset === 'string') {
316      return offset.split(',').map(value => Number.parseInt(value, 10));
317    }
318    if (typeof offset === 'function') {
319      return popperData => offset(popperData, this._element);
320    }
321    return offset;
322  }
323  _resolvePossibleFunction(arg) {
324    return execute(arg, [this._element, this._element]);
325  }
326  _getPopperConfig(attachment) {
327    const defaultBsPopperConfig = {
328      placement: attachment,
329      modifiers: [{
330        name: 'flip',
331        options: {
332          fallbackPlacements: this._config.fallbackPlacements
333        }
334      }, {
335        name: 'offset',
336        options: {
337          offset: this._getOffset()
338        }
339      }, {
340        name: 'preventOverflow',
341        options: {
342          boundary: this._config.boundary
343        }
344      }, {
345        name: 'arrow',
346        options: {
347          element: `.${this.constructor.NAME}-arrow`
348        }
349      }, {
350        name: 'preSetPlacement',
351        enabled: true,
352        phase: 'beforeMain',
353        fn: data => {
354          // Pre-set Popper's placement attribute in order to read the arrow sizes properly.
355          // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
356          this._getTipElement().setAttribute('data-popper-placement', data.state.placement);
357        }
358      }]
359    };
360    return {
361      ...defaultBsPopperConfig,
362      ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
363    };
364  }
365  _setListeners() {
366    const triggers = this._config.trigger.split(' ');
367    for (const trigger of triggers) {
368      if (trigger === 'click') {
369        EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => {
370          const context = this._initializeOnDelegatedTarget(event);
371          context._activeTrigger[TRIGGER_CLICK] = !(context._isShown() && context._activeTrigger[TRIGGER_CLICK]);
372          context.toggle();
373        });
374      } else if (trigger !== TRIGGER_MANUAL) {
375        const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN);
376        const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT);
377        EventHandler.on(this._element, eventIn, this._config.selector, event => {
378          const context = this._initializeOnDelegatedTarget(event);
379          context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
380          context._enter();
381        });
382        EventHandler.on(this._element, eventOut, this._config.selector, event => {
383          const context = this._initializeOnDelegatedTarget(event);
384          context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
385          context._leave();
386        });
387      }
388    }
389    this._hideModalHandler = () => {
390      if (this._element) {
391        this.hide();
392      }
393    };
394    EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
395  }
396  _fixTitle() {
397    const title = this._element.getAttribute('title');
398    if (!title) {
399      return;
400    }
401    if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {
402      this._element.setAttribute('aria-label', title);
403    }
404    this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility
405    this._element.removeAttribute('title');
406  }
407  _enter() {
408    if (this._isShown() || this._isHovered) {
409      this._isHovered = true;
410      return;
411    }
412    this._isHovered = true;
413    this._setTimeout(() => {
414      if (this._isHovered) {
415        this.show();
416      }
417    }, this._config.delay.show);
418  }
419  _leave() {
420    if (this._isWithActiveTrigger()) {
421      return;
422    }
423    this._isHovered = false;
424    this._setTimeout(() => {
425      if (!this._isHovered) {
426        this.hide();
427      }
428    }, this._config.delay.hide);
429  }
430  _setTimeout(handler, timeout) {
431    clearTimeout(this._timeout);
432    this._timeout = setTimeout(handler, timeout);
433  }
434  _isWithActiveTrigger() {
435    return Object.values(this._activeTrigger).includes(true);
436  }
437  _getConfig(config) {
438    const dataAttributes = Manipulator.getDataAttributes(this._element);
439    for (const dataAttribute of Object.keys(dataAttributes)) {
440      if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
441        delete dataAttributes[dataAttribute];
442      }
443    }
444    config = {
445      ...dataAttributes,
446      ...(typeof config === 'object' && config ? config : {})
447    };
448    config = this._mergeConfigObj(config);
449    config = this._configAfterMerge(config);
450    this._typeCheckConfig(config);
451    return config;
452  }
453  _configAfterMerge(config) {
454    config.container = config.container === false ? document.body : getElement(config.container);
455    if (typeof config.delay === 'number') {
456      config.delay = {
457        show: config.delay,
458        hide: config.delay
459      };
460    }
461    if (typeof config.title === 'number') {
462      config.title = config.title.toString();
463    }
464    if (typeof config.content === 'number') {
465      config.content = config.content.toString();
466    }
467    return config;
468  }
469  _getDelegateConfig() {
470    const config = {};
471    for (const [key, value] of Object.entries(this._config)) {
472      if (this.constructor.Default[key] !== value) {
473        config[key] = value;
474      }
475    }
476    config.selector = false;
477    config.trigger = 'manual';
478
479    // In the future can be replaced with:
480    // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
481    // `Object.fromEntries(keysWithDifferentValues)`
482    return config;
483  }
484  _disposePopper() {
485    if (this._popper) {
486      this._popper.destroy();
487      this._popper = null;
488    }
489    if (this.tip) {
490      this.tip.remove();
491      this.tip = null;
492    }
493  }
494
495  // Static
496  static jQueryInterface(config) {
497    return this.each(function () {
498      const data = Tooltip.getOrCreateInstance(this, config);
499      if (typeof config !== 'string') {
500        return;
501      }
502      if (typeof data[config] === 'undefined') {
503        throw new TypeError(`No method named "${config}"`);
504      }
505      data[config]();
506    });
507  }
508}
509
510/**
511 * jQuery
512 */
513
514defineJQueryPlugin(Tooltip);
515
516/**
517 * --------------------------------------------------------------------------
518 * Bootstrap popover.js
519 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
520 * --------------------------------------------------------------------------
521 */
522
523
524/**
525 * Constants
526 */
527
528const NAME = 'popover';
529const SELECTOR_TITLE = '.popover-header';
530const SELECTOR_CONTENT = '.popover-body';
531const Default = {
532  ...Tooltip.Default,
533  content: '',
534  offset: [0, 8],
535  placement: 'right',
536  template: '<div class="popover" role="tooltip">' + '<div class="popover-arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div>' + '</div>',
537  trigger: 'click'
538};
539const DefaultType = {
540  ...Tooltip.DefaultType,
541  content: '(null|string|element|function)'
542};
543
544/**
545 * Class definition
546 */
547
548class Popover extends Tooltip {
549  // Getters
550  static get Default() {
551    return Default;
552  }
553  static get DefaultType() {
554    return DefaultType;
555  }
556  static get NAME() {
557    return NAME;
558  }
559
560  // Overrides
561  _isWithContent() {
562    return this._getTitle() || this._getContent();
563  }
564
565  // Private
566  _getContentForTemplate() {
567    return {
568      [SELECTOR_TITLE]: this._getTitle(),
569      [SELECTOR_CONTENT]: this._getContent()
570    };
571  }
572  _getContent() {
573    return this._resolvePossibleFunction(this._config.content);
574  }
575
576  // Static
577  static jQueryInterface(config) {
578    return this.each(function () {
579      const data = Popover.getOrCreateInstance(this, config);
580      if (typeof config !== 'string') {
581        return;
582      }
583      if (typeof data[config] === 'undefined') {
584        throw new TypeError(`No method named "${config}"`);
585      }
586      data[config]();
587    });
588  }
589}
590
591/**
592 * jQuery
593 */
594
595defineJQueryPlugin(Popover);
596
597window.bootstrap = window.bootstrap || {};
598window.bootstrap.Popover = Popover;
599window.bootstrap.Tooltip = Tooltip;
600if (Joomla && Joomla.getOptions) {
601  // Get the elements/configurations from the PHP
602  const tooltips = Joomla.getOptions('bootstrap.tooltip');
603  const popovers = Joomla.getOptions('bootstrap.popover');
604  // Initialise the elements
605  if (typeof popovers === 'object' && popovers !== null) {
606    Object.keys(popovers).forEach(popover => {
607      const opt = popovers[popover];
608      const options = {
609        animation: opt.animation ? opt.animation : true,
610        container: opt.container ? opt.container : false,
611        delay: opt.delay ? opt.delay : 0,
612        html: opt.html ? opt.html : false,
613        placement: opt.placement ? opt.placement : 'top',
614        selector: opt.selector ? opt.selector : false,
615        title: opt.title ? opt.title : '',
616        trigger: opt.trigger ? opt.trigger : 'click',
617        offset: opt.offset ? opt.offset : 0,
618        fallbackPlacement: opt.fallbackPlacement ? opt.fallbackPlacement : 'flip',
619        boundary: opt.boundary ? opt.boundary : 'scrollParent',
620        customClass: opt.customClass ? opt.customClass : '',
621        sanitize: opt.sanitize ? opt.sanitize : true,
622        sanitizeFn: opt.sanitizeFn ? opt.sanitizeFn : null,
623        popperConfig: opt.popperConfig ? opt.popperConfig : null
624      };
625      if (opt.content) {
626        options.content = opt.content;
627      }
628      if (opt.template) {
629        options.template = opt.template;
630      }
631      if (opt.allowList) {
632        options.allowList = opt.allowList;
633      }
634      const elements = Array.from(document.querySelectorAll(popover));
635      if (elements.length) {
636        elements.map(el => new window.bootstrap.Popover(el, options));
637      }
638    });
639  }
640  // Initialise the elements
641  if (typeof tooltips === 'object' && tooltips !== null) {
642    Object.keys(tooltips).forEach(tooltip => {
643      const opt = tooltips[tooltip];
644      const options = {
645        animation: opt.animation ? opt.animation : true,
646        container: opt.container ? opt.container : false,
647        delay: opt.delay ? opt.delay : 0,
648        html: opt.html ? opt.html : false,
649        selector: opt.selector ? opt.selector : false,
650        trigger: opt.trigger ? opt.trigger : 'hover focus',
651        fallbackPlacement: opt.fallbackPlacement ? opt.fallbackPlacement : null,
652        boundary: opt.boundary ? opt.boundary : 'clippingParents',
653        title: opt.title ? opt.title : '',
654        customClass: opt.customClass ? opt.customClass : '',
655        sanitize: opt.sanitize ? opt.sanitize : true,
656        sanitizeFn: opt.sanitizeFn ? opt.sanitizeFn : null,
657        popperConfig: opt.popperConfig ? opt.popperConfig : null
658      };
659      if (opt.placement) {
660        options.placement = opt.placement;
661      }
662      if (opt.template) {
663        options.template = opt.template;
664      }
665      if (opt.allowList) {
666        options.allowList = opt.allowList;
667      }
668      const elements = Array.from(document.querySelectorAll(tooltip));
669      if (elements.length) {
670        elements.map(el => new window.bootstrap.Tooltip(el, options));
671      }
672    });
673  }
674}
675
676export { Popover as P };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.