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.