Rev 1151 | Rev 1339 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
597 | daniel-mar | 1 | /*! |
1308 | daniel-mar | 2 | * Bootstrap v5.3.0 (https://getbootstrap.com/) |
1134 | daniel-mar | 3 | * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) |
597 | daniel-mar | 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() : |
||
8 | typeof define === 'function' && define.amd ? define(factory) : |
||
9 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrap = factory()); |
||
679 | daniel-mar | 10 | })(this, (function () { 'use strict'; |
597 | daniel-mar | 11 | |
12 | /** |
||
13 | * -------------------------------------------------------------------------- |
||
1151 | daniel-mar | 14 | * Bootstrap dom/data.js |
15 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
||
16 | * -------------------------------------------------------------------------- |
||
17 | */ |
||
18 | |||
19 | /** |
||
20 | * Constants |
||
21 | */ |
||
22 | |||
23 | const elementMap = new Map(); |
||
24 | const Data = { |
||
25 | set(element, key, instance) { |
||
26 | if (!elementMap.has(element)) { |
||
27 | elementMap.set(element, new Map()); |
||
28 | } |
||
29 | const instanceMap = elementMap.get(element); |
||
30 | |||
31 | // make it clear we only want one instance per element |
||
32 | // can be removed later when multiple key/instances are fine to be used |
||
33 | if (!instanceMap.has(key) && instanceMap.size !== 0) { |
||
34 | // eslint-disable-next-line no-console |
||
35 | console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`); |
||
36 | return; |
||
37 | } |
||
38 | instanceMap.set(key, instance); |
||
39 | }, |
||
40 | get(element, key) { |
||
41 | if (elementMap.has(element)) { |
||
42 | return elementMap.get(element).get(key) || null; |
||
43 | } |
||
44 | return null; |
||
45 | }, |
||
46 | remove(element, key) { |
||
47 | if (!elementMap.has(element)) { |
||
48 | return; |
||
49 | } |
||
50 | const instanceMap = elementMap.get(element); |
||
51 | instanceMap.delete(key); |
||
52 | |||
53 | // free up element references if there are no instances left for an element |
||
54 | if (instanceMap.size === 0) { |
||
55 | elementMap.delete(element); |
||
56 | } |
||
57 | } |
||
58 | }; |
||
59 | |||
60 | /** |
||
61 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 62 | * Bootstrap util/index.js |
597 | daniel-mar | 63 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
64 | * -------------------------------------------------------------------------- |
||
65 | */ |
||
1056 | daniel-mar | 66 | |
597 | daniel-mar | 67 | const MAX_UID = 1000000; |
68 | const MILLISECONDS_MULTIPLIER = 1000; |
||
1056 | daniel-mar | 69 | const TRANSITION_END = 'transitionend'; |
597 | daniel-mar | 70 | |
1056 | daniel-mar | 71 | /** |
72 | * Properly escape IDs selectors to handle weird IDs |
||
73 | * @param {string} selector |
||
74 | * @returns {string} |
||
75 | */ |
||
76 | const parseSelector = selector => { |
||
77 | if (selector && window.CSS && window.CSS.escape) { |
||
78 | // document.querySelector needs escaping to handle IDs (html5+) containing for instance / |
||
79 | selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`); |
||
80 | } |
||
81 | return selector; |
||
82 | }; |
||
83 | |||
84 | // Shout-out Angus Croll (https://goo.gl/pxwQGp) |
||
846 | daniel-mar | 85 | const toType = object => { |
86 | if (object === null || object === undefined) { |
||
87 | return `${object}`; |
||
597 | daniel-mar | 88 | } |
846 | daniel-mar | 89 | return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase(); |
597 | daniel-mar | 90 | }; |
1056 | daniel-mar | 91 | |
597 | daniel-mar | 92 | /** |
846 | daniel-mar | 93 | * Public Util API |
597 | daniel-mar | 94 | */ |
95 | |||
96 | const getUID = prefix => { |
||
97 | do { |
||
98 | prefix += Math.floor(Math.random() * MAX_UID); |
||
99 | } while (document.getElementById(prefix)); |
||
100 | return prefix; |
||
101 | }; |
||
102 | const getTransitionDurationFromElement = element => { |
||
103 | if (!element) { |
||
104 | return 0; |
||
1056 | daniel-mar | 105 | } |
597 | daniel-mar | 106 | |
1056 | daniel-mar | 107 | // Get transition-duration of the element |
597 | daniel-mar | 108 | let { |
109 | transitionDuration, |
||
110 | transitionDelay |
||
111 | } = window.getComputedStyle(element); |
||
112 | const floatTransitionDuration = Number.parseFloat(transitionDuration); |
||
1056 | daniel-mar | 113 | const floatTransitionDelay = Number.parseFloat(transitionDelay); |
597 | daniel-mar | 114 | |
1056 | daniel-mar | 115 | // Return 0 if element or transition duration is not found |
597 | daniel-mar | 116 | if (!floatTransitionDuration && !floatTransitionDelay) { |
117 | return 0; |
||
1056 | daniel-mar | 118 | } |
597 | daniel-mar | 119 | |
1056 | daniel-mar | 120 | // If multiple durations are defined, take the first |
597 | daniel-mar | 121 | transitionDuration = transitionDuration.split(',')[0]; |
122 | transitionDelay = transitionDelay.split(',')[0]; |
||
123 | return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; |
||
124 | }; |
||
125 | const triggerTransitionEnd = element => { |
||
126 | element.dispatchEvent(new Event(TRANSITION_END)); |
||
127 | }; |
||
846 | daniel-mar | 128 | const isElement$1 = object => { |
129 | if (!object || typeof object !== 'object') { |
||
597 | daniel-mar | 130 | return false; |
131 | } |
||
846 | daniel-mar | 132 | if (typeof object.jquery !== 'undefined') { |
133 | object = object[0]; |
||
597 | daniel-mar | 134 | } |
846 | daniel-mar | 135 | return typeof object.nodeType !== 'undefined'; |
597 | daniel-mar | 136 | }; |
846 | daniel-mar | 137 | const getElement = object => { |
138 | // it's a jQuery object or a node element |
||
139 | if (isElement$1(object)) { |
||
140 | return object.jquery ? object[0] : object; |
||
597 | daniel-mar | 141 | } |
846 | daniel-mar | 142 | if (typeof object === 'string' && object.length > 0) { |
1056 | daniel-mar | 143 | return document.querySelector(parseSelector(object)); |
597 | daniel-mar | 144 | } |
145 | return null; |
||
146 | }; |
||
147 | const isVisible = element => { |
||
637 | daniel-mar | 148 | if (!isElement$1(element) || element.getClientRects().length === 0) { |
597 | daniel-mar | 149 | return false; |
150 | } |
||
1056 | daniel-mar | 151 | const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'; |
152 | // Handle `details` element as its content may falsie appear visible when it is closed |
||
846 | daniel-mar | 153 | const closedDetails = element.closest('details:not([open])'); |
154 | if (!closedDetails) { |
||
155 | return elementIsVisible; |
||
156 | } |
||
157 | if (closedDetails !== element) { |
||
158 | const summary = element.closest('summary'); |
||
159 | if (summary && summary.parentNode !== closedDetails) { |
||
160 | return false; |
||
161 | } |
||
162 | if (summary === null) { |
||
163 | return false; |
||
164 | } |
||
165 | } |
||
166 | return elementIsVisible; |
||
597 | daniel-mar | 167 | }; |
168 | const isDisabled = element => { |
||
169 | if (!element || element.nodeType !== Node.ELEMENT_NODE) { |
||
170 | return true; |
||
171 | } |
||
172 | if (element.classList.contains('disabled')) { |
||
173 | return true; |
||
174 | } |
||
175 | if (typeof element.disabled !== 'undefined') { |
||
176 | return element.disabled; |
||
177 | } |
||
178 | return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; |
||
179 | }; |
||
180 | const findShadowRoot = element => { |
||
181 | if (!document.documentElement.attachShadow) { |
||
182 | return null; |
||
1056 | daniel-mar | 183 | } |
597 | daniel-mar | 184 | |
1056 | daniel-mar | 185 | // Can find the shadow root otherwise it'll return the document |
597 | daniel-mar | 186 | if (typeof element.getRootNode === 'function') { |
187 | const root = element.getRootNode(); |
||
188 | return root instanceof ShadowRoot ? root : null; |
||
189 | } |
||
190 | if (element instanceof ShadowRoot) { |
||
191 | return element; |
||
1056 | daniel-mar | 192 | } |
597 | daniel-mar | 193 | |
1056 | daniel-mar | 194 | // when we don't find a shadow root |
597 | daniel-mar | 195 | if (!element.parentNode) { |
196 | return null; |
||
197 | } |
||
198 | return findShadowRoot(element.parentNode); |
||
199 | }; |
||
1056 | daniel-mar | 200 | const noop = () => {}; |
597 | daniel-mar | 201 | |
637 | daniel-mar | 202 | /** |
203 | * Trick to restart an element's animation |
||
204 | * |
||
205 | * @param {HTMLElement} element |
||
206 | * @return void |
||
207 | * |
||
208 | * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation |
||
209 | */ |
||
210 | const reflow = element => { |
||
846 | daniel-mar | 211 | element.offsetHeight; // eslint-disable-line no-unused-expressions |
637 | daniel-mar | 212 | }; |
213 | |||
597 | daniel-mar | 214 | const getjQuery = () => { |
846 | daniel-mar | 215 | if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { |
216 | return window.jQuery; |
||
597 | daniel-mar | 217 | } |
218 | return null; |
||
219 | }; |
||
637 | daniel-mar | 220 | const DOMContentLoadedCallbacks = []; |
597 | daniel-mar | 221 | const onDOMContentLoaded = callback => { |
222 | if (document.readyState === 'loading') { |
||
637 | daniel-mar | 223 | // add listener on the first call when the document is in loading state |
224 | if (!DOMContentLoadedCallbacks.length) { |
||
225 | document.addEventListener('DOMContentLoaded', () => { |
||
846 | daniel-mar | 226 | for (const callback of DOMContentLoadedCallbacks) { |
227 | callback(); |
||
228 | } |
||
637 | daniel-mar | 229 | }); |
230 | } |
||
231 | DOMContentLoadedCallbacks.push(callback); |
||
597 | daniel-mar | 232 | } else { |
233 | callback(); |
||
234 | } |
||
235 | }; |
||
236 | const isRTL = () => document.documentElement.dir === 'rtl'; |
||
237 | const defineJQueryPlugin = plugin => { |
||
238 | onDOMContentLoaded(() => { |
||
239 | const $ = getjQuery(); |
||
240 | /* istanbul ignore if */ |
||
241 | if ($) { |
||
242 | const name = plugin.NAME; |
||
243 | const JQUERY_NO_CONFLICT = $.fn[name]; |
||
244 | $.fn[name] = plugin.jQueryInterface; |
||
245 | $.fn[name].Constructor = plugin; |
||
246 | $.fn[name].noConflict = () => { |
||
247 | $.fn[name] = JQUERY_NO_CONFLICT; |
||
248 | return plugin.jQueryInterface; |
||
249 | }; |
||
250 | } |
||
251 | }); |
||
252 | }; |
||
1056 | daniel-mar | 253 | const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { |
254 | return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue; |
||
597 | daniel-mar | 255 | }; |
637 | daniel-mar | 256 | const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { |
257 | if (!waitForTransition) { |
||
258 | execute(callback); |
||
259 | return; |
||
260 | } |
||
261 | const durationPadding = 5; |
||
262 | const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding; |
||
263 | let called = false; |
||
264 | const handler = ({ |
||
265 | target |
||
266 | }) => { |
||
267 | if (target !== transitionElement) { |
||
597 | daniel-mar | 268 | return; |
269 | } |
||
637 | daniel-mar | 270 | called = true; |
271 | transitionElement.removeEventListener(TRANSITION_END, handler); |
||
272 | execute(callback); |
||
273 | }; |
||
274 | transitionElement.addEventListener(TRANSITION_END, handler); |
||
275 | setTimeout(() => { |
||
276 | if (!called) { |
||
277 | triggerTransitionEnd(transitionElement); |
||
597 | daniel-mar | 278 | } |
637 | daniel-mar | 279 | }, emulatedDuration); |
280 | }; |
||
1056 | daniel-mar | 281 | |
637 | daniel-mar | 282 | /** |
283 | * Return the previous/next element of a list. |
||
284 | * |
||
285 | * @param {array} list The list of elements |
||
286 | * @param activeElement The active element |
||
287 | * @param shouldGetNext Choose to get next or previous element |
||
288 | * @param isCycleAllowed |
||
289 | * @return {Element|elem} The proper element |
||
290 | */ |
||
291 | const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { |
||
846 | daniel-mar | 292 | const listLength = list.length; |
1056 | daniel-mar | 293 | let index = list.indexOf(activeElement); |
294 | |||
295 | // if the element does not exist in the list return an element |
||
846 | daniel-mar | 296 | // depending on the direction and if cycle is allowed |
637 | daniel-mar | 297 | if (index === -1) { |
846 | daniel-mar | 298 | return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]; |
637 | daniel-mar | 299 | } |
300 | index += shouldGetNext ? 1 : -1; |
||
301 | if (isCycleAllowed) { |
||
302 | index = (index + listLength) % listLength; |
||
597 | daniel-mar | 303 | } |
637 | daniel-mar | 304 | return list[Math.max(0, Math.min(index, listLength - 1))]; |
597 | daniel-mar | 305 | }; |
306 | |||
307 | /** |
||
308 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 309 | * Bootstrap dom/event-handler.js |
597 | daniel-mar | 310 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
311 | * -------------------------------------------------------------------------- |
||
312 | */ |
||
1056 | daniel-mar | 313 | |
1308 | daniel-mar | 314 | |
597 | daniel-mar | 315 | /** |
316 | * Constants |
||
317 | */ |
||
318 | |||
319 | const namespaceRegex = /[^.]*(?=\..*)\.|.*/; |
||
320 | const stripNameRegex = /\..*/; |
||
321 | const stripUidRegex = /::\d+$/; |
||
322 | const eventRegistry = {}; // Events storage |
||
323 | let uidEvent = 1; |
||
324 | const customEvents = { |
||
325 | mouseenter: 'mouseover', |
||
326 | mouseleave: 'mouseout' |
||
327 | }; |
||
328 | const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']); |
||
1056 | daniel-mar | 329 | |
597 | daniel-mar | 330 | /** |
331 | * Private methods |
||
332 | */ |
||
333 | |||
922 | daniel-mar | 334 | function makeEventUid(element, uid) { |
597 | daniel-mar | 335 | return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; |
336 | } |
||
922 | daniel-mar | 337 | function getElementEvents(element) { |
338 | const uid = makeEventUid(element); |
||
597 | daniel-mar | 339 | element.uidEvent = uid; |
340 | eventRegistry[uid] = eventRegistry[uid] || {}; |
||
341 | return eventRegistry[uid]; |
||
342 | } |
||
343 | function bootstrapHandler(element, fn) { |
||
344 | return function handler(event) { |
||
922 | daniel-mar | 345 | hydrateObj(event, { |
346 | delegateTarget: element |
||
347 | }); |
||
597 | daniel-mar | 348 | if (handler.oneOff) { |
349 | EventHandler.off(element, event.type, fn); |
||
350 | } |
||
351 | return fn.apply(element, [event]); |
||
352 | }; |
||
353 | } |
||
354 | function bootstrapDelegationHandler(element, selector, fn) { |
||
355 | return function handler(event) { |
||
356 | const domElements = element.querySelectorAll(selector); |
||
357 | for (let { |
||
358 | target |
||
359 | } = event; target && target !== this; target = target.parentNode) { |
||
846 | daniel-mar | 360 | for (const domElement of domElements) { |
361 | if (domElement !== target) { |
||
362 | continue; |
||
363 | } |
||
922 | daniel-mar | 364 | hydrateObj(event, { |
365 | delegateTarget: target |
||
366 | }); |
||
846 | daniel-mar | 367 | if (handler.oneOff) { |
368 | EventHandler.off(element, event.type, selector, fn); |
||
597 | daniel-mar | 369 | } |
846 | daniel-mar | 370 | return fn.apply(target, [event]); |
597 | daniel-mar | 371 | } |
846 | daniel-mar | 372 | } |
597 | daniel-mar | 373 | }; |
374 | } |
||
922 | daniel-mar | 375 | function findHandler(events, callable, delegationSelector = null) { |
376 | return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector); |
||
597 | daniel-mar | 377 | } |
846 | daniel-mar | 378 | function normalizeParameters(originalTypeEvent, handler, delegationFunction) { |
1056 | daniel-mar | 379 | const isDelegated = typeof handler === 'string'; |
1151 | daniel-mar | 380 | // TODO: tooltip passes `false` instead of selector, so we need to check |
922 | daniel-mar | 381 | const callable = isDelegated ? delegationFunction : handler || delegationFunction; |
597 | daniel-mar | 382 | let typeEvent = getTypeEvent(originalTypeEvent); |
846 | daniel-mar | 383 | if (!nativeEvents.has(typeEvent)) { |
597 | daniel-mar | 384 | typeEvent = originalTypeEvent; |
385 | } |
||
922 | daniel-mar | 386 | return [isDelegated, callable, typeEvent]; |
597 | daniel-mar | 387 | } |
846 | daniel-mar | 388 | function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { |
597 | daniel-mar | 389 | if (typeof originalTypeEvent !== 'string' || !element) { |
390 | return; |
||
391 | } |
||
1056 | daniel-mar | 392 | let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); |
597 | daniel-mar | 393 | |
1056 | daniel-mar | 394 | // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position |
597 | daniel-mar | 395 | // this prevents the handler from being dispatched the same way as mouseover or mouseout does |
846 | daniel-mar | 396 | if (originalTypeEvent in customEvents) { |
397 | const wrapFunction = fn => { |
||
597 | daniel-mar | 398 | return function (event) { |
399 | if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) { |
||
400 | return fn.call(this, event); |
||
401 | } |
||
402 | }; |
||
403 | }; |
||
922 | daniel-mar | 404 | callable = wrapFunction(callable); |
597 | daniel-mar | 405 | } |
922 | daniel-mar | 406 | const events = getElementEvents(element); |
597 | daniel-mar | 407 | const handlers = events[typeEvent] || (events[typeEvent] = {}); |
922 | daniel-mar | 408 | const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null); |
846 | daniel-mar | 409 | if (previousFunction) { |
410 | previousFunction.oneOff = previousFunction.oneOff && oneOff; |
||
597 | daniel-mar | 411 | return; |
412 | } |
||
922 | daniel-mar | 413 | const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, '')); |
414 | const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable); |
||
415 | fn.delegationSelector = isDelegated ? handler : null; |
||
416 | fn.callable = callable; |
||
597 | daniel-mar | 417 | fn.oneOff = oneOff; |
418 | fn.uidEvent = uid; |
||
419 | handlers[uid] = fn; |
||
922 | daniel-mar | 420 | element.addEventListener(typeEvent, fn, isDelegated); |
597 | daniel-mar | 421 | } |
422 | function removeHandler(element, events, typeEvent, handler, delegationSelector) { |
||
423 | const fn = findHandler(events[typeEvent], handler, delegationSelector); |
||
424 | if (!fn) { |
||
425 | return; |
||
426 | } |
||
427 | element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)); |
||
428 | delete events[typeEvent][fn.uidEvent]; |
||
429 | } |
||
430 | function removeNamespacedHandlers(element, events, typeEvent, namespace) { |
||
431 | const storeElementEvent = events[typeEvent] || {}; |
||
1056 | daniel-mar | 432 | for (const [handlerKey, event] of Object.entries(storeElementEvent)) { |
597 | daniel-mar | 433 | if (handlerKey.includes(namespace)) { |
922 | daniel-mar | 434 | removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); |
597 | daniel-mar | 435 | } |
846 | daniel-mar | 436 | } |
597 | daniel-mar | 437 | } |
438 | function getTypeEvent(event) { |
||
439 | // allow to get the native events from namespaced events ('click.bs.button' --> 'click') |
||
440 | event = event.replace(stripNameRegex, ''); |
||
441 | return customEvents[event] || event; |
||
442 | } |
||
443 | const EventHandler = { |
||
846 | daniel-mar | 444 | on(element, event, handler, delegationFunction) { |
445 | addHandler(element, event, handler, delegationFunction, false); |
||
597 | daniel-mar | 446 | }, |
846 | daniel-mar | 447 | one(element, event, handler, delegationFunction) { |
448 | addHandler(element, event, handler, delegationFunction, true); |
||
597 | daniel-mar | 449 | }, |
846 | daniel-mar | 450 | off(element, originalTypeEvent, handler, delegationFunction) { |
597 | daniel-mar | 451 | if (typeof originalTypeEvent !== 'string' || !element) { |
452 | return; |
||
453 | } |
||
922 | daniel-mar | 454 | const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); |
597 | daniel-mar | 455 | const inNamespace = typeEvent !== originalTypeEvent; |
922 | daniel-mar | 456 | const events = getElementEvents(element); |
457 | const storeElementEvent = events[typeEvent] || {}; |
||
597 | daniel-mar | 458 | const isNamespace = originalTypeEvent.startsWith('.'); |
922 | daniel-mar | 459 | if (typeof callable !== 'undefined') { |
597 | daniel-mar | 460 | // Simplest case: handler is passed, remove that listener ONLY. |
922 | daniel-mar | 461 | if (!Object.keys(storeElementEvent).length) { |
597 | daniel-mar | 462 | return; |
463 | } |
||
922 | daniel-mar | 464 | removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null); |
597 | daniel-mar | 465 | return; |
466 | } |
||
467 | if (isNamespace) { |
||
846 | daniel-mar | 468 | for (const elementEvent of Object.keys(events)) { |
597 | daniel-mar | 469 | removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); |
846 | daniel-mar | 470 | } |
597 | daniel-mar | 471 | } |
1056 | daniel-mar | 472 | for (const [keyHandlers, event] of Object.entries(storeElementEvent)) { |
597 | daniel-mar | 473 | const handlerKey = keyHandlers.replace(stripUidRegex, ''); |
474 | if (!inNamespace || originalTypeEvent.includes(handlerKey)) { |
||
922 | daniel-mar | 475 | removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); |
597 | daniel-mar | 476 | } |
846 | daniel-mar | 477 | } |
597 | daniel-mar | 478 | }, |
479 | trigger(element, event, args) { |
||
480 | if (typeof event !== 'string' || !element) { |
||
481 | return null; |
||
482 | } |
||
483 | const $ = getjQuery(); |
||
484 | const typeEvent = getTypeEvent(event); |
||
485 | const inNamespace = event !== typeEvent; |
||
846 | daniel-mar | 486 | let jQueryEvent = null; |
597 | daniel-mar | 487 | let bubbles = true; |
488 | let nativeDispatch = true; |
||
489 | let defaultPrevented = false; |
||
490 | if (inNamespace && $) { |
||
491 | jQueryEvent = $.Event(event, args); |
||
492 | $(element).trigger(jQueryEvent); |
||
493 | bubbles = !jQueryEvent.isPropagationStopped(); |
||
494 | nativeDispatch = !jQueryEvent.isImmediatePropagationStopped(); |
||
495 | defaultPrevented = jQueryEvent.isDefaultPrevented(); |
||
496 | } |
||
1151 | daniel-mar | 497 | const evt = hydrateObj(new Event(event, { |
846 | daniel-mar | 498 | bubbles, |
499 | cancelable: true |
||
1151 | daniel-mar | 500 | }), args); |
597 | daniel-mar | 501 | if (defaultPrevented) { |
502 | evt.preventDefault(); |
||
503 | } |
||
504 | if (nativeDispatch) { |
||
505 | element.dispatchEvent(evt); |
||
506 | } |
||
846 | daniel-mar | 507 | if (evt.defaultPrevented && jQueryEvent) { |
597 | daniel-mar | 508 | jQueryEvent.preventDefault(); |
509 | } |
||
510 | return evt; |
||
511 | } |
||
512 | }; |
||
1056 | daniel-mar | 513 | function hydrateObj(obj, meta = {}) { |
514 | for (const [key, value] of Object.entries(meta)) { |
||
922 | daniel-mar | 515 | try { |
516 | obj[key] = value; |
||
517 | } catch (_unused) { |
||
518 | Object.defineProperty(obj, key, { |
||
519 | configurable: true, |
||
520 | get() { |
||
521 | return value; |
||
522 | } |
||
523 | }); |
||
524 | } |
||
525 | } |
||
526 | return obj; |
||
527 | } |
||
528 | |||
597 | daniel-mar | 529 | /** |
530 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 531 | * Bootstrap dom/manipulator.js |
637 | daniel-mar | 532 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
533 | * -------------------------------------------------------------------------- |
||
534 | */ |
||
1056 | daniel-mar | 535 | |
846 | daniel-mar | 536 | function normalizeData(value) { |
537 | if (value === 'true') { |
||
538 | return true; |
||
539 | } |
||
540 | if (value === 'false') { |
||
541 | return false; |
||
542 | } |
||
543 | if (value === Number(value).toString()) { |
||
544 | return Number(value); |
||
545 | } |
||
546 | if (value === '' || value === 'null') { |
||
547 | return null; |
||
548 | } |
||
549 | if (typeof value !== 'string') { |
||
550 | return value; |
||
551 | } |
||
552 | try { |
||
553 | return JSON.parse(decodeURIComponent(value)); |
||
554 | } catch (_unused) { |
||
555 | return value; |
||
556 | } |
||
557 | } |
||
558 | function normalizeDataKey(key) { |
||
559 | return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`); |
||
560 | } |
||
561 | const Manipulator = { |
||
562 | setDataAttribute(element, key, value) { |
||
563 | element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); |
||
564 | }, |
||
565 | removeDataAttribute(element, key) { |
||
566 | element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); |
||
567 | }, |
||
568 | getDataAttributes(element) { |
||
569 | if (!element) { |
||
570 | return {}; |
||
571 | } |
||
572 | const attributes = {}; |
||
573 | const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig')); |
||
574 | for (const key of bsKeys) { |
||
575 | let pureKey = key.replace(/^bs/, ''); |
||
576 | pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length); |
||
577 | attributes[pureKey] = normalizeData(element.dataset[key]); |
||
578 | } |
||
579 | return attributes; |
||
580 | }, |
||
581 | getDataAttribute(element, key) { |
||
582 | return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); |
||
583 | } |
||
584 | }; |
||
585 | |||
637 | daniel-mar | 586 | /** |
846 | daniel-mar | 587 | * -------------------------------------------------------------------------- |
1134 | daniel-mar | 588 | * Bootstrap util/config.js |
846 | daniel-mar | 589 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
590 | * -------------------------------------------------------------------------- |
||
591 | */ |
||
1056 | daniel-mar | 592 | |
1308 | daniel-mar | 593 | |
846 | daniel-mar | 594 | /** |
595 | * Class definition |
||
596 | */ |
||
597 | |||
598 | class Config { |
||
599 | // Getters |
||
600 | static get Default() { |
||
601 | return {}; |
||
602 | } |
||
603 | static get DefaultType() { |
||
604 | return {}; |
||
605 | } |
||
606 | static get NAME() { |
||
607 | throw new Error('You have to implement the static method "NAME", for each component!'); |
||
608 | } |
||
609 | _getConfig(config) { |
||
610 | config = this._mergeConfigObj(config); |
||
611 | config = this._configAfterMerge(config); |
||
612 | this._typeCheckConfig(config); |
||
613 | return config; |
||
614 | } |
||
615 | _configAfterMerge(config) { |
||
616 | return config; |
||
617 | } |
||
618 | _mergeConfigObj(config, element) { |
||
619 | const jsonConfig = isElement$1(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse |
||
620 | |||
1056 | daniel-mar | 621 | return { |
622 | ...this.constructor.Default, |
||
846 | daniel-mar | 623 | ...(typeof jsonConfig === 'object' ? jsonConfig : {}), |
624 | ...(isElement$1(element) ? Manipulator.getDataAttributes(element) : {}), |
||
625 | ...(typeof config === 'object' ? config : {}) |
||
626 | }; |
||
627 | } |
||
628 | _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { |
||
1056 | daniel-mar | 629 | for (const [property, expectedTypes] of Object.entries(configTypes)) { |
846 | daniel-mar | 630 | const value = config[property]; |
631 | const valueType = isElement$1(value) ? 'element' : toType(value); |
||
632 | if (!new RegExp(expectedTypes).test(valueType)) { |
||
633 | throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); |
||
634 | } |
||
635 | } |
||
636 | } |
||
637 | } |
||
638 | |||
639 | /** |
||
640 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 641 | * Bootstrap base-component.js |
846 | daniel-mar | 642 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
643 | * -------------------------------------------------------------------------- |
||
644 | */ |
||
1056 | daniel-mar | 645 | |
1308 | daniel-mar | 646 | |
846 | daniel-mar | 647 | /** |
637 | daniel-mar | 648 | * Constants |
649 | */ |
||
650 | |||
1308 | daniel-mar | 651 | const VERSION = '5.3.0'; |
1056 | daniel-mar | 652 | |
846 | daniel-mar | 653 | /** |
654 | * Class definition |
||
655 | */ |
||
637 | daniel-mar | 656 | |
846 | daniel-mar | 657 | class BaseComponent extends Config { |
658 | constructor(element, config) { |
||
659 | super(); |
||
597 | daniel-mar | 660 | element = getElement(element); |
661 | if (!element) { |
||
662 | return; |
||
663 | } |
||
664 | this._element = element; |
||
846 | daniel-mar | 665 | this._config = this._getConfig(config); |
597 | daniel-mar | 666 | Data.set(this._element, this.constructor.DATA_KEY, this); |
1056 | daniel-mar | 667 | } |
597 | daniel-mar | 668 | |
1056 | daniel-mar | 669 | // Public |
597 | daniel-mar | 670 | dispose() { |
671 | Data.remove(this._element, this.constructor.DATA_KEY); |
||
672 | EventHandler.off(this._element, this.constructor.EVENT_KEY); |
||
846 | daniel-mar | 673 | for (const propertyName of Object.getOwnPropertyNames(this)) { |
597 | daniel-mar | 674 | this[propertyName] = null; |
846 | daniel-mar | 675 | } |
597 | daniel-mar | 676 | } |
677 | _queueCallback(callback, element, isAnimated = true) { |
||
637 | daniel-mar | 678 | executeAfterTransition(callback, element, isAnimated); |
597 | daniel-mar | 679 | } |
846 | daniel-mar | 680 | _getConfig(config) { |
681 | config = this._mergeConfigObj(config, this._element); |
||
682 | config = this._configAfterMerge(config); |
||
683 | this._typeCheckConfig(config); |
||
684 | return config; |
||
1056 | daniel-mar | 685 | } |
846 | daniel-mar | 686 | |
1056 | daniel-mar | 687 | // Static |
597 | daniel-mar | 688 | static getInstance(element) { |
637 | daniel-mar | 689 | return Data.get(getElement(element), this.DATA_KEY); |
597 | daniel-mar | 690 | } |
637 | daniel-mar | 691 | static getOrCreateInstance(element, config = {}) { |
692 | return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null); |
||
693 | } |
||
597 | daniel-mar | 694 | static get VERSION() { |
695 | return VERSION; |
||
696 | } |
||
697 | static get DATA_KEY() { |
||
698 | return `bs.${this.NAME}`; |
||
699 | } |
||
700 | static get EVENT_KEY() { |
||
701 | return `.${this.DATA_KEY}`; |
||
702 | } |
||
846 | daniel-mar | 703 | static eventName(name) { |
704 | return `${name}${this.EVENT_KEY}`; |
||
705 | } |
||
597 | daniel-mar | 706 | } |
707 | |||
708 | /** |
||
709 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 710 | * Bootstrap dom/selector-engine.js |
597 | daniel-mar | 711 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
712 | * -------------------------------------------------------------------------- |
||
713 | */ |
||
1308 | daniel-mar | 714 | |
1056 | daniel-mar | 715 | const getSelector = element => { |
716 | let selector = element.getAttribute('data-bs-target'); |
||
717 | if (!selector || selector === '#') { |
||
718 | let hrefAttribute = element.getAttribute('href'); |
||
637 | daniel-mar | 719 | |
1056 | daniel-mar | 720 | // The only valid content that could double as a selector are IDs or classes, |
721 | // so everything starting with `#` or `.`. If a "real" URL is used as the selector, |
||
722 | // `document.querySelector` will rightfully complain it is invalid. |
||
723 | // See https://github.com/twbs/bootstrap/issues/32273 |
||
724 | if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) { |
||
725 | return null; |
||
726 | } |
||
727 | |||
728 | // Just in case some CMS puts out a full URL with the anchor appended |
||
729 | if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) { |
||
730 | hrefAttribute = `#${hrefAttribute.split('#')[1]}`; |
||
731 | } |
||
732 | selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null; |
||
733 | } |
||
734 | return parseSelector(selector); |
||
735 | }; |
||
736 | const SelectorEngine = { |
||
737 | find(selector, element = document.documentElement) { |
||
738 | return [].concat(...Element.prototype.querySelectorAll.call(element, selector)); |
||
739 | }, |
||
740 | findOne(selector, element = document.documentElement) { |
||
741 | return Element.prototype.querySelector.call(element, selector); |
||
742 | }, |
||
743 | children(element, selector) { |
||
744 | return [].concat(...element.children).filter(child => child.matches(selector)); |
||
745 | }, |
||
746 | parents(element, selector) { |
||
747 | const parents = []; |
||
748 | let ancestor = element.parentNode.closest(selector); |
||
749 | while (ancestor) { |
||
750 | parents.push(ancestor); |
||
751 | ancestor = ancestor.parentNode.closest(selector); |
||
752 | } |
||
753 | return parents; |
||
754 | }, |
||
755 | prev(element, selector) { |
||
756 | let previous = element.previousElementSibling; |
||
757 | while (previous) { |
||
758 | if (previous.matches(selector)) { |
||
759 | return [previous]; |
||
760 | } |
||
761 | previous = previous.previousElementSibling; |
||
762 | } |
||
763 | return []; |
||
764 | }, |
||
765 | // TODO: this is now unused; remove later along with prev() |
||
766 | next(element, selector) { |
||
767 | let next = element.nextElementSibling; |
||
768 | while (next) { |
||
769 | if (next.matches(selector)) { |
||
770 | return [next]; |
||
771 | } |
||
772 | next = next.nextElementSibling; |
||
773 | } |
||
774 | return []; |
||
775 | }, |
||
776 | focusableChildren(element) { |
||
777 | const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable="true"]'].map(selector => `${selector}:not([tabindex^="-"])`).join(','); |
||
778 | return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el)); |
||
779 | }, |
||
780 | getSelectorFromElement(element) { |
||
781 | const selector = getSelector(element); |
||
782 | if (selector) { |
||
783 | return SelectorEngine.findOne(selector) ? selector : null; |
||
784 | } |
||
785 | return null; |
||
786 | }, |
||
787 | getElementFromSelector(element) { |
||
788 | const selector = getSelector(element); |
||
789 | return selector ? SelectorEngine.findOne(selector) : null; |
||
790 | }, |
||
791 | getMultipleElementsFromSelector(element) { |
||
792 | const selector = getSelector(element); |
||
793 | return selector ? SelectorEngine.find(selector) : []; |
||
794 | } |
||
795 | }; |
||
796 | |||
797 | /** |
||
798 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 799 | * Bootstrap util/component-functions.js |
1056 | daniel-mar | 800 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
801 | * -------------------------------------------------------------------------- |
||
802 | */ |
||
1308 | daniel-mar | 803 | |
637 | daniel-mar | 804 | const enableDismissTrigger = (component, method = 'hide') => { |
805 | const clickEvent = `click.dismiss${component.EVENT_KEY}`; |
||
806 | const name = component.NAME; |
||
807 | EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) { |
||
808 | if (['A', 'AREA'].includes(this.tagName)) { |
||
809 | event.preventDefault(); |
||
810 | } |
||
811 | if (isDisabled(this)) { |
||
812 | return; |
||
813 | } |
||
1056 | daniel-mar | 814 | const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`); |
815 | const instance = component.getOrCreateInstance(target); |
||
637 | daniel-mar | 816 | |
1056 | daniel-mar | 817 | // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method |
637 | daniel-mar | 818 | instance[method](); |
819 | }); |
||
820 | }; |
||
821 | |||
597 | daniel-mar | 822 | /** |
637 | daniel-mar | 823 | * -------------------------------------------------------------------------- |
1134 | daniel-mar | 824 | * Bootstrap alert.js |
637 | daniel-mar | 825 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
826 | * -------------------------------------------------------------------------- |
||
827 | */ |
||
1056 | daniel-mar | 828 | |
1308 | daniel-mar | 829 | |
637 | daniel-mar | 830 | /** |
597 | daniel-mar | 831 | * Constants |
832 | */ |
||
833 | |||
846 | daniel-mar | 834 | const NAME$f = 'alert'; |
835 | const DATA_KEY$a = 'bs.alert'; |
||
836 | const EVENT_KEY$b = `.${DATA_KEY$a}`; |
||
837 | const EVENT_CLOSE = `close${EVENT_KEY$b}`; |
||
838 | const EVENT_CLOSED = `closed${EVENT_KEY$b}`; |
||
637 | daniel-mar | 839 | const CLASS_NAME_FADE$5 = 'fade'; |
840 | const CLASS_NAME_SHOW$8 = 'show'; |
||
1056 | daniel-mar | 841 | |
597 | daniel-mar | 842 | /** |
846 | daniel-mar | 843 | * Class definition |
597 | daniel-mar | 844 | */ |
845 | |||
846 | class Alert extends BaseComponent { |
||
847 | // Getters |
||
848 | static get NAME() { |
||
846 | daniel-mar | 849 | return NAME$f; |
1056 | daniel-mar | 850 | } |
597 | daniel-mar | 851 | |
1056 | daniel-mar | 852 | // Public |
637 | daniel-mar | 853 | close() { |
854 | const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE); |
||
855 | if (closeEvent.defaultPrevented) { |
||
597 | daniel-mar | 856 | return; |
857 | } |
||
637 | daniel-mar | 858 | this._element.classList.remove(CLASS_NAME_SHOW$8); |
859 | const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$5); |
||
860 | this._queueCallback(() => this._destroyElement(), this._element, isAnimated); |
||
1056 | daniel-mar | 861 | } |
597 | daniel-mar | 862 | |
1056 | daniel-mar | 863 | // Private |
637 | daniel-mar | 864 | _destroyElement() { |
865 | this._element.remove(); |
||
866 | EventHandler.trigger(this._element, EVENT_CLOSED); |
||
867 | this.dispose(); |
||
1056 | daniel-mar | 868 | } |
597 | daniel-mar | 869 | |
1056 | daniel-mar | 870 | // Static |
597 | daniel-mar | 871 | static jQueryInterface(config) { |
872 | return this.each(function () { |
||
637 | daniel-mar | 873 | const data = Alert.getOrCreateInstance(this); |
874 | if (typeof config !== 'string') { |
||
875 | return; |
||
597 | daniel-mar | 876 | } |
637 | daniel-mar | 877 | if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { |
878 | throw new TypeError(`No method named "${config}"`); |
||
597 | daniel-mar | 879 | } |
637 | daniel-mar | 880 | data[config](this); |
597 | daniel-mar | 881 | }); |
882 | } |
||
1056 | daniel-mar | 883 | } |
597 | daniel-mar | 884 | |
885 | /** |
||
846 | daniel-mar | 886 | * Data API implementation |
597 | daniel-mar | 887 | */ |
888 | |||
1056 | daniel-mar | 889 | enableDismissTrigger(Alert, 'close'); |
597 | daniel-mar | 890 | |
891 | /** |
||
892 | * jQuery |
||
893 | */ |
||
894 | |||
895 | defineJQueryPlugin(Alert); |
||
896 | |||
897 | /** |
||
898 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 899 | * Bootstrap button.js |
597 | daniel-mar | 900 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
901 | * -------------------------------------------------------------------------- |
||
902 | */ |
||
1056 | daniel-mar | 903 | |
1308 | daniel-mar | 904 | |
597 | daniel-mar | 905 | /** |
906 | * Constants |
||
907 | */ |
||
908 | |||
846 | daniel-mar | 909 | const NAME$e = 'button'; |
910 | const DATA_KEY$9 = 'bs.button'; |
||
911 | const EVENT_KEY$a = `.${DATA_KEY$9}`; |
||
912 | const DATA_API_KEY$6 = '.data-api'; |
||
597 | daniel-mar | 913 | const CLASS_NAME_ACTIVE$3 = 'active'; |
914 | const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle="button"]'; |
||
846 | daniel-mar | 915 | const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`; |
1056 | daniel-mar | 916 | |
597 | daniel-mar | 917 | /** |
846 | daniel-mar | 918 | * Class definition |
597 | daniel-mar | 919 | */ |
920 | |||
921 | class Button extends BaseComponent { |
||
922 | // Getters |
||
923 | static get NAME() { |
||
846 | daniel-mar | 924 | return NAME$e; |
1056 | daniel-mar | 925 | } |
597 | daniel-mar | 926 | |
1056 | daniel-mar | 927 | // Public |
597 | daniel-mar | 928 | toggle() { |
929 | // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method |
||
930 | this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3)); |
||
1056 | daniel-mar | 931 | } |
597 | daniel-mar | 932 | |
1056 | daniel-mar | 933 | // Static |
597 | daniel-mar | 934 | static jQueryInterface(config) { |
935 | return this.each(function () { |
||
637 | daniel-mar | 936 | const data = Button.getOrCreateInstance(this); |
597 | daniel-mar | 937 | if (config === 'toggle') { |
938 | data[config](); |
||
939 | } |
||
940 | }); |
||
941 | } |
||
1056 | daniel-mar | 942 | } |
597 | daniel-mar | 943 | |
944 | /** |
||
846 | daniel-mar | 945 | * Data API implementation |
597 | daniel-mar | 946 | */ |
947 | |||
948 | EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => { |
||
949 | event.preventDefault(); |
||
950 | const button = event.target.closest(SELECTOR_DATA_TOGGLE$5); |
||
637 | daniel-mar | 951 | const data = Button.getOrCreateInstance(button); |
597 | daniel-mar | 952 | data.toggle(); |
953 | }); |
||
1056 | daniel-mar | 954 | |
597 | daniel-mar | 955 | /** |
956 | * jQuery |
||
957 | */ |
||
958 | |||
959 | defineJQueryPlugin(Button); |
||
960 | |||
961 | /** |
||
962 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 963 | * Bootstrap util/swipe.js |
597 | daniel-mar | 964 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
965 | * -------------------------------------------------------------------------- |
||
966 | */ |
||
846 | daniel-mar | 967 | |
1308 | daniel-mar | 968 | |
597 | daniel-mar | 969 | /** |
970 | * Constants |
||
971 | */ |
||
972 | |||
846 | daniel-mar | 973 | const NAME$d = 'swipe'; |
974 | const EVENT_KEY$9 = '.bs.swipe'; |
||
975 | const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`; |
||
976 | const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`; |
||
977 | const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`; |
||
978 | const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`; |
||
979 | const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`; |
||
980 | const POINTER_TYPE_TOUCH = 'touch'; |
||
981 | const POINTER_TYPE_PEN = 'pen'; |
||
982 | const CLASS_NAME_POINTER_EVENT = 'pointer-event'; |
||
597 | daniel-mar | 983 | const SWIPE_THRESHOLD = 40; |
846 | daniel-mar | 984 | const Default$c = { |
922 | daniel-mar | 985 | endCallback: null, |
846 | daniel-mar | 986 | leftCallback: null, |
922 | daniel-mar | 987 | rightCallback: null |
597 | daniel-mar | 988 | }; |
846 | daniel-mar | 989 | const DefaultType$c = { |
922 | daniel-mar | 990 | endCallback: '(function|null)', |
846 | daniel-mar | 991 | leftCallback: '(function|null)', |
922 | daniel-mar | 992 | rightCallback: '(function|null)' |
597 | daniel-mar | 993 | }; |
1056 | daniel-mar | 994 | |
846 | daniel-mar | 995 | /** |
996 | * Class definition |
||
997 | */ |
||
998 | |||
999 | class Swipe extends Config { |
||
1000 | constructor(element, config) { |
||
1001 | super(); |
||
1002 | this._element = element; |
||
1003 | if (!element || !Swipe.isSupported()) { |
||
1004 | return; |
||
1005 | } |
||
1006 | this._config = this._getConfig(config); |
||
1007 | this._deltaX = 0; |
||
1008 | this._supportPointerEvents = Boolean(window.PointerEvent); |
||
1009 | this._initEvents(); |
||
1056 | daniel-mar | 1010 | } |
846 | daniel-mar | 1011 | |
1056 | daniel-mar | 1012 | // Getters |
846 | daniel-mar | 1013 | static get Default() { |
1014 | return Default$c; |
||
1015 | } |
||
1016 | static get DefaultType() { |
||
1017 | return DefaultType$c; |
||
1018 | } |
||
1019 | static get NAME() { |
||
1020 | return NAME$d; |
||
1056 | daniel-mar | 1021 | } |
846 | daniel-mar | 1022 | |
1056 | daniel-mar | 1023 | // Public |
846 | daniel-mar | 1024 | dispose() { |
1025 | EventHandler.off(this._element, EVENT_KEY$9); |
||
1056 | daniel-mar | 1026 | } |
846 | daniel-mar | 1027 | |
1056 | daniel-mar | 1028 | // Private |
846 | daniel-mar | 1029 | _start(event) { |
1030 | if (!this._supportPointerEvents) { |
||
1031 | this._deltaX = event.touches[0].clientX; |
||
1032 | return; |
||
1033 | } |
||
1034 | if (this._eventIsPointerPenTouch(event)) { |
||
1035 | this._deltaX = event.clientX; |
||
1036 | } |
||
1037 | } |
||
1038 | _end(event) { |
||
1039 | if (this._eventIsPointerPenTouch(event)) { |
||
1040 | this._deltaX = event.clientX - this._deltaX; |
||
1041 | } |
||
1042 | this._handleSwipe(); |
||
1043 | execute(this._config.endCallback); |
||
1044 | } |
||
1045 | _move(event) { |
||
1046 | this._deltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this._deltaX; |
||
1047 | } |
||
1048 | _handleSwipe() { |
||
1049 | const absDeltaX = Math.abs(this._deltaX); |
||
1050 | if (absDeltaX <= SWIPE_THRESHOLD) { |
||
1051 | return; |
||
1052 | } |
||
1053 | const direction = absDeltaX / this._deltaX; |
||
1054 | this._deltaX = 0; |
||
1055 | if (!direction) { |
||
1056 | return; |
||
1057 | } |
||
1058 | execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback); |
||
1059 | } |
||
1060 | _initEvents() { |
||
1061 | if (this._supportPointerEvents) { |
||
1062 | EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event)); |
||
1063 | EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event)); |
||
1064 | this._element.classList.add(CLASS_NAME_POINTER_EVENT); |
||
1065 | } else { |
||
1066 | EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event)); |
||
1067 | EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event)); |
||
1068 | EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event)); |
||
1069 | } |
||
1070 | } |
||
1071 | _eventIsPointerPenTouch(event) { |
||
1072 | return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH); |
||
1056 | daniel-mar | 1073 | } |
846 | daniel-mar | 1074 | |
1056 | daniel-mar | 1075 | // Static |
846 | daniel-mar | 1076 | static isSupported() { |
1077 | return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; |
||
1078 | } |
||
1079 | } |
||
1080 | |||
1081 | /** |
||
1082 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 1083 | * Bootstrap carousel.js |
846 | daniel-mar | 1084 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
1085 | * -------------------------------------------------------------------------- |
||
1086 | */ |
||
1056 | daniel-mar | 1087 | |
1308 | daniel-mar | 1088 | |
846 | daniel-mar | 1089 | /** |
1090 | * Constants |
||
1091 | */ |
||
1092 | |||
1093 | const NAME$c = 'carousel'; |
||
1094 | const DATA_KEY$8 = 'bs.carousel'; |
||
1095 | const EVENT_KEY$8 = `.${DATA_KEY$8}`; |
||
1096 | const DATA_API_KEY$5 = '.data-api'; |
||
1097 | const ARROW_LEFT_KEY$1 = 'ArrowLeft'; |
||
1098 | const ARROW_RIGHT_KEY$1 = 'ArrowRight'; |
||
1099 | const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch |
||
1100 | |||
597 | daniel-mar | 1101 | const ORDER_NEXT = 'next'; |
1102 | const ORDER_PREV = 'prev'; |
||
1103 | const DIRECTION_LEFT = 'left'; |
||
1104 | const DIRECTION_RIGHT = 'right'; |
||
846 | daniel-mar | 1105 | const EVENT_SLIDE = `slide${EVENT_KEY$8}`; |
1106 | const EVENT_SLID = `slid${EVENT_KEY$8}`; |
||
1107 | const EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`; |
||
1108 | const EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`; |
||
1109 | const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`; |
||
1110 | const EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`; |
||
1111 | const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`; |
||
1112 | const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`; |
||
597 | daniel-mar | 1113 | const CLASS_NAME_CAROUSEL = 'carousel'; |
1114 | const CLASS_NAME_ACTIVE$2 = 'active'; |
||
1115 | const CLASS_NAME_SLIDE = 'slide'; |
||
1116 | const CLASS_NAME_END = 'carousel-item-end'; |
||
1117 | const CLASS_NAME_START = 'carousel-item-start'; |
||
1118 | const CLASS_NAME_NEXT = 'carousel-item-next'; |
||
1119 | const CLASS_NAME_PREV = 'carousel-item-prev'; |
||
846 | daniel-mar | 1120 | const SELECTOR_ACTIVE = '.active'; |
597 | daniel-mar | 1121 | const SELECTOR_ITEM = '.carousel-item'; |
846 | daniel-mar | 1122 | const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM; |
597 | daniel-mar | 1123 | const SELECTOR_ITEM_IMG = '.carousel-item img'; |
1124 | const SELECTOR_INDICATORS = '.carousel-indicators'; |
||
1125 | const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'; |
||
1126 | const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'; |
||
846 | daniel-mar | 1127 | const KEY_TO_DIRECTION = { |
1128 | [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT, |
||
1129 | [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT |
||
1130 | }; |
||
1131 | const Default$b = { |
||
1132 | interval: 5000, |
||
1133 | keyboard: true, |
||
1134 | pause: 'hover', |
||
1135 | ride: false, |
||
1136 | touch: true, |
||
1137 | wrap: true |
||
1138 | }; |
||
1139 | const DefaultType$b = { |
||
1140 | interval: '(number|boolean)', |
||
922 | daniel-mar | 1141 | // TODO:v6 remove boolean support |
846 | daniel-mar | 1142 | keyboard: 'boolean', |
922 | daniel-mar | 1143 | pause: '(string|boolean)', |
846 | daniel-mar | 1144 | ride: '(boolean|string)', |
1145 | touch: 'boolean', |
||
1146 | wrap: 'boolean' |
||
1147 | }; |
||
1056 | daniel-mar | 1148 | |
597 | daniel-mar | 1149 | /** |
846 | daniel-mar | 1150 | * Class definition |
597 | daniel-mar | 1151 | */ |
1152 | |||
1153 | class Carousel extends BaseComponent { |
||
1154 | constructor(element, config) { |
||
846 | daniel-mar | 1155 | super(element, config); |
597 | daniel-mar | 1156 | this._interval = null; |
1157 | this._activeElement = null; |
||
1158 | this._isSliding = false; |
||
1159 | this.touchTimeout = null; |
||
846 | daniel-mar | 1160 | this._swipeHelper = null; |
597 | daniel-mar | 1161 | this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element); |
1162 | this._addEventListeners(); |
||
846 | daniel-mar | 1163 | if (this._config.ride === CLASS_NAME_CAROUSEL) { |
1164 | this.cycle(); |
||
1165 | } |
||
1056 | daniel-mar | 1166 | } |
597 | daniel-mar | 1167 | |
1056 | daniel-mar | 1168 | // Getters |
597 | daniel-mar | 1169 | static get Default() { |
846 | daniel-mar | 1170 | return Default$b; |
597 | daniel-mar | 1171 | } |
846 | daniel-mar | 1172 | static get DefaultType() { |
1173 | return DefaultType$b; |
||
1174 | } |
||
597 | daniel-mar | 1175 | static get NAME() { |
846 | daniel-mar | 1176 | return NAME$c; |
1056 | daniel-mar | 1177 | } |
597 | daniel-mar | 1178 | |
1056 | daniel-mar | 1179 | // Public |
597 | daniel-mar | 1180 | next() { |
637 | daniel-mar | 1181 | this._slide(ORDER_NEXT); |
597 | daniel-mar | 1182 | } |
1183 | nextWhenVisible() { |
||
846 | daniel-mar | 1184 | // FIXME TODO use `document.visibilityState` |
597 | daniel-mar | 1185 | // Don't call next when the page isn't visible |
1186 | // or the carousel or its parent isn't visible |
||
1187 | if (!document.hidden && isVisible(this._element)) { |
||
1188 | this.next(); |
||
1189 | } |
||
1190 | } |
||
1191 | prev() { |
||
637 | daniel-mar | 1192 | this._slide(ORDER_PREV); |
597 | daniel-mar | 1193 | } |
846 | daniel-mar | 1194 | pause() { |
1195 | if (this._isSliding) { |
||
597 | daniel-mar | 1196 | triggerTransitionEnd(this._element); |
1197 | } |
||
846 | daniel-mar | 1198 | this._clearInterval(); |
597 | daniel-mar | 1199 | } |
846 | daniel-mar | 1200 | cycle() { |
1201 | this._clearInterval(); |
||
1202 | this._updateInterval(); |
||
1203 | this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval); |
||
1204 | } |
||
1205 | _maybeEnableCycle() { |
||
1206 | if (!this._config.ride) { |
||
1207 | return; |
||
597 | daniel-mar | 1208 | } |
846 | daniel-mar | 1209 | if (this._isSliding) { |
1210 | EventHandler.one(this._element, EVENT_SLID, () => this.cycle()); |
||
1211 | return; |
||
597 | daniel-mar | 1212 | } |
846 | daniel-mar | 1213 | this.cycle(); |
597 | daniel-mar | 1214 | } |
1215 | to(index) { |
||
846 | daniel-mar | 1216 | const items = this._getItems(); |
1217 | if (index > items.length - 1 || index < 0) { |
||
597 | daniel-mar | 1218 | return; |
1219 | } |
||
1220 | if (this._isSliding) { |
||
1221 | EventHandler.one(this._element, EVENT_SLID, () => this.to(index)); |
||
1222 | return; |
||
1223 | } |
||
846 | daniel-mar | 1224 | const activeIndex = this._getItemIndex(this._getActive()); |
597 | daniel-mar | 1225 | if (activeIndex === index) { |
1226 | return; |
||
1227 | } |
||
1228 | const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV; |
||
846 | daniel-mar | 1229 | this._slide(order, items[index]); |
597 | daniel-mar | 1230 | } |
846 | daniel-mar | 1231 | dispose() { |
1232 | if (this._swipeHelper) { |
||
1233 | this._swipeHelper.dispose(); |
||
597 | daniel-mar | 1234 | } |
846 | daniel-mar | 1235 | super.dispose(); |
1056 | daniel-mar | 1236 | } |
597 | daniel-mar | 1237 | |
1056 | daniel-mar | 1238 | // Private |
846 | daniel-mar | 1239 | _configAfterMerge(config) { |
1240 | config.defaultInterval = config.interval; |
||
1241 | return config; |
||
597 | daniel-mar | 1242 | } |
1243 | _addEventListeners() { |
||
1244 | if (this._config.keyboard) { |
||
846 | daniel-mar | 1245 | EventHandler.on(this._element, EVENT_KEYDOWN$1, event => this._keydown(event)); |
597 | daniel-mar | 1246 | } |
1247 | if (this._config.pause === 'hover') { |
||
846 | daniel-mar | 1248 | EventHandler.on(this._element, EVENT_MOUSEENTER$1, () => this.pause()); |
1249 | EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle()); |
||
597 | daniel-mar | 1250 | } |
846 | daniel-mar | 1251 | if (this._config.touch && Swipe.isSupported()) { |
597 | daniel-mar | 1252 | this._addTouchEventListeners(); |
1253 | } |
||
1254 | } |
||
1255 | _addTouchEventListeners() { |
||
846 | daniel-mar | 1256 | for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) { |
1257 | EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault()); |
||
1258 | } |
||
1259 | const endCallBack = () => { |
||
1260 | if (this._config.pause !== 'hover') { |
||
1261 | return; |
||
1056 | daniel-mar | 1262 | } |
1263 | |||
1264 | // If it's a touch-enabled device, mouseenter/leave are fired as |
||
846 | daniel-mar | 1265 | // part of the mouse compatibility events on first tap - the carousel |
1266 | // would stop cycling until user tapped out of it; |
||
1267 | // here, we listen for touchend, explicitly pause the carousel |
||
1268 | // (as if it's the second time we tap on it, mouseenter compat event |
||
1269 | // is NOT fired) and after a timeout (to allow for mouse compatibility |
||
1270 | // events to fire) we explicitly restart cycling |
||
597 | daniel-mar | 1271 | |
846 | daniel-mar | 1272 | this.pause(); |
1273 | if (this.touchTimeout) { |
||
1274 | clearTimeout(this.touchTimeout); |
||
597 | daniel-mar | 1275 | } |
846 | daniel-mar | 1276 | this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval); |
1277 | }; |
||
1278 | const swipeConfig = { |
||
1279 | leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)), |
||
1280 | rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)), |
||
1281 | endCallback: endCallBack |
||
597 | daniel-mar | 1282 | }; |
846 | daniel-mar | 1283 | this._swipeHelper = new Swipe(this._element, swipeConfig); |
597 | daniel-mar | 1284 | } |
1285 | _keydown(event) { |
||
1286 | if (/input|textarea/i.test(event.target.tagName)) { |
||
1287 | return; |
||
1288 | } |
||
637 | daniel-mar | 1289 | const direction = KEY_TO_DIRECTION[event.key]; |
1290 | if (direction) { |
||
597 | daniel-mar | 1291 | event.preventDefault(); |
846 | daniel-mar | 1292 | this._slide(this._directionToOrder(direction)); |
597 | daniel-mar | 1293 | } |
1294 | } |
||
1295 | _getItemIndex(element) { |
||
846 | daniel-mar | 1296 | return this._getItems().indexOf(element); |
597 | daniel-mar | 1297 | } |
846 | daniel-mar | 1298 | _setActiveIndicatorElement(index) { |
1299 | if (!this._indicatorsElement) { |
||
1300 | return; |
||
1301 | } |
||
1302 | const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement); |
||
1303 | activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2); |
||
1304 | activeIndicator.removeAttribute('aria-current'); |
||
1305 | const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement); |
||
1306 | if (newActiveIndicator) { |
||
1307 | newActiveIndicator.classList.add(CLASS_NAME_ACTIVE$2); |
||
1308 | newActiveIndicator.setAttribute('aria-current', 'true'); |
||
597 | daniel-mar | 1309 | } |
1310 | } |
||
1311 | _updateInterval() { |
||
846 | daniel-mar | 1312 | const element = this._activeElement || this._getActive(); |
597 | daniel-mar | 1313 | if (!element) { |
1314 | return; |
||
1315 | } |
||
1316 | const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10); |
||
846 | daniel-mar | 1317 | this._config.interval = elementInterval || this._config.defaultInterval; |
1318 | } |
||
1319 | _slide(order, element = null) { |
||
1320 | if (this._isSliding) { |
||
1321 | return; |
||
597 | daniel-mar | 1322 | } |
846 | daniel-mar | 1323 | const activeElement = this._getActive(); |
597 | daniel-mar | 1324 | const isNext = order === ORDER_NEXT; |
846 | daniel-mar | 1325 | const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap); |
1326 | if (nextElement === activeElement) { |
||
597 | daniel-mar | 1327 | return; |
1328 | } |
||
846 | daniel-mar | 1329 | const nextElementIndex = this._getItemIndex(nextElement); |
1330 | const triggerEvent = eventName => { |
||
1331 | return EventHandler.trigger(this._element, eventName, { |
||
1332 | relatedTarget: nextElement, |
||
1333 | direction: this._orderToDirection(order), |
||
1334 | from: this._getItemIndex(activeElement), |
||
1335 | to: nextElementIndex |
||
1336 | }); |
||
1337 | }; |
||
1338 | const slideEvent = triggerEvent(EVENT_SLIDE); |
||
597 | daniel-mar | 1339 | if (slideEvent.defaultPrevented) { |
1340 | return; |
||
1341 | } |
||
1342 | if (!activeElement || !nextElement) { |
||
1343 | // Some weirdness is happening, so we bail |
||
1151 | daniel-mar | 1344 | // TODO: change tests that use empty divs to avoid this check |
597 | daniel-mar | 1345 | return; |
1346 | } |
||
846 | daniel-mar | 1347 | const isCycling = Boolean(this._interval); |
1348 | this.pause(); |
||
597 | daniel-mar | 1349 | this._isSliding = true; |
846 | daniel-mar | 1350 | this._setActiveIndicatorElement(nextElementIndex); |
597 | daniel-mar | 1351 | this._activeElement = nextElement; |
846 | daniel-mar | 1352 | const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END; |
1353 | const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV; |
||
1354 | nextElement.classList.add(orderClassName); |
||
1355 | reflow(nextElement); |
||
1356 | activeElement.classList.add(directionalClassName); |
||
1357 | nextElement.classList.add(directionalClassName); |
||
1358 | const completeCallBack = () => { |
||
1359 | nextElement.classList.remove(directionalClassName, orderClassName); |
||
1360 | nextElement.classList.add(CLASS_NAME_ACTIVE$2); |
||
1361 | activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName); |
||
1362 | this._isSliding = false; |
||
1363 | triggerEvent(EVENT_SLID); |
||
597 | daniel-mar | 1364 | }; |
846 | daniel-mar | 1365 | this._queueCallback(completeCallBack, activeElement, this._isAnimated()); |
597 | daniel-mar | 1366 | if (isCycling) { |
1367 | this.cycle(); |
||
1368 | } |
||
1369 | } |
||
846 | daniel-mar | 1370 | _isAnimated() { |
1371 | return this._element.classList.contains(CLASS_NAME_SLIDE); |
||
1372 | } |
||
1373 | _getActive() { |
||
1374 | return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); |
||
1375 | } |
||
1376 | _getItems() { |
||
1377 | return SelectorEngine.find(SELECTOR_ITEM, this._element); |
||
1378 | } |
||
1379 | _clearInterval() { |
||
1380 | if (this._interval) { |
||
1381 | clearInterval(this._interval); |
||
1382 | this._interval = null; |
||
597 | daniel-mar | 1383 | } |
846 | daniel-mar | 1384 | } |
1385 | _directionToOrder(direction) { |
||
597 | daniel-mar | 1386 | if (isRTL()) { |
1387 | return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT; |
||
1388 | } |
||
1389 | return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV; |
||
1390 | } |
||
1391 | _orderToDirection(order) { |
||
1392 | if (isRTL()) { |
||
1393 | return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT; |
||
1394 | } |
||
1395 | return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT; |
||
1056 | daniel-mar | 1396 | } |
597 | daniel-mar | 1397 | |
1056 | daniel-mar | 1398 | // Static |
846 | daniel-mar | 1399 | static jQueryInterface(config) { |
1400 | return this.each(function () { |
||
1401 | const data = Carousel.getOrCreateInstance(this, config); |
||
1402 | if (typeof config === 'number') { |
||
1403 | data.to(config); |
||
1404 | return; |
||
1405 | } |
||
1406 | if (typeof config === 'string') { |
||
1407 | if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { |
||
1408 | throw new TypeError(`No method named "${config}"`); |
||
1409 | } |
||
1410 | data[config](); |
||
597 | daniel-mar | 1411 | } |
846 | daniel-mar | 1412 | }); |
597 | daniel-mar | 1413 | } |
1056 | daniel-mar | 1414 | } |
597 | daniel-mar | 1415 | |
846 | daniel-mar | 1416 | /** |
1417 | * Data API implementation |
||
1418 | */ |
||
1419 | |||
1420 | EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, function (event) { |
||
1056 | daniel-mar | 1421 | const target = SelectorEngine.getElementFromSelector(this); |
846 | daniel-mar | 1422 | if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) { |
1423 | return; |
||
597 | daniel-mar | 1424 | } |
846 | daniel-mar | 1425 | event.preventDefault(); |
1426 | const carousel = Carousel.getOrCreateInstance(target); |
||
1427 | const slideIndex = this.getAttribute('data-bs-slide-to'); |
||
1428 | if (slideIndex) { |
||
1429 | carousel.to(slideIndex); |
||
1430 | carousel._maybeEnableCycle(); |
||
1431 | return; |
||
1432 | } |
||
1433 | if (Manipulator.getDataAttribute(this, 'slide') === 'next') { |
||
1434 | carousel.next(); |
||
1435 | carousel._maybeEnableCycle(); |
||
1436 | return; |
||
597 | daniel-mar | 1437 | } |
846 | daniel-mar | 1438 | carousel.prev(); |
1439 | carousel._maybeEnableCycle(); |
||
1440 | }); |
||
1441 | EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => { |
||
597 | daniel-mar | 1442 | const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE); |
846 | daniel-mar | 1443 | for (const carousel of carousels) { |
1444 | Carousel.getOrCreateInstance(carousel); |
||
597 | daniel-mar | 1445 | } |
1446 | }); |
||
1056 | daniel-mar | 1447 | |
597 | daniel-mar | 1448 | /** |
1449 | * jQuery |
||
1450 | */ |
||
1451 | |||
1452 | defineJQueryPlugin(Carousel); |
||
1453 | |||
1454 | /** |
||
1455 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 1456 | * Bootstrap collapse.js |
597 | daniel-mar | 1457 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
1458 | * -------------------------------------------------------------------------- |
||
1459 | */ |
||
1056 | daniel-mar | 1460 | |
1308 | daniel-mar | 1461 | |
597 | daniel-mar | 1462 | /** |
1463 | * Constants |
||
1464 | */ |
||
1465 | |||
846 | daniel-mar | 1466 | const NAME$b = 'collapse'; |
1467 | const DATA_KEY$7 = 'bs.collapse'; |
||
1468 | const EVENT_KEY$7 = `.${DATA_KEY$7}`; |
||
1469 | const DATA_API_KEY$4 = '.data-api'; |
||
1470 | const EVENT_SHOW$6 = `show${EVENT_KEY$7}`; |
||
1471 | const EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`; |
||
1472 | const EVENT_HIDE$6 = `hide${EVENT_KEY$7}`; |
||
1473 | const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`; |
||
1474 | const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`; |
||
637 | daniel-mar | 1475 | const CLASS_NAME_SHOW$7 = 'show'; |
597 | daniel-mar | 1476 | const CLASS_NAME_COLLAPSE = 'collapse'; |
1477 | const CLASS_NAME_COLLAPSING = 'collapsing'; |
||
1478 | const CLASS_NAME_COLLAPSED = 'collapsed'; |
||
679 | daniel-mar | 1479 | const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`; |
637 | daniel-mar | 1480 | const CLASS_NAME_HORIZONTAL = 'collapse-horizontal'; |
597 | daniel-mar | 1481 | const WIDTH = 'width'; |
1482 | const HEIGHT = 'height'; |
||
637 | daniel-mar | 1483 | const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing'; |
597 | daniel-mar | 1484 | const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle="collapse"]'; |
846 | daniel-mar | 1485 | const Default$a = { |
922 | daniel-mar | 1486 | parent: null, |
1487 | toggle: true |
||
846 | daniel-mar | 1488 | }; |
1489 | const DefaultType$a = { |
||
922 | daniel-mar | 1490 | parent: '(null|element)', |
1491 | toggle: 'boolean' |
||
846 | daniel-mar | 1492 | }; |
1056 | daniel-mar | 1493 | |
597 | daniel-mar | 1494 | /** |
846 | daniel-mar | 1495 | * Class definition |
597 | daniel-mar | 1496 | */ |
1497 | |||
1498 | class Collapse extends BaseComponent { |
||
1499 | constructor(element, config) { |
||
846 | daniel-mar | 1500 | super(element, config); |
597 | daniel-mar | 1501 | this._isTransitioning = false; |
637 | daniel-mar | 1502 | this._triggerArray = []; |
597 | daniel-mar | 1503 | const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4); |
846 | daniel-mar | 1504 | for (const elem of toggleList) { |
1056 | daniel-mar | 1505 | const selector = SelectorEngine.getSelectorFromElement(elem); |
846 | daniel-mar | 1506 | const filterElement = SelectorEngine.find(selector).filter(foundElement => foundElement === this._element); |
597 | daniel-mar | 1507 | if (selector !== null && filterElement.length) { |
1508 | this._triggerArray.push(elem); |
||
1509 | } |
||
1510 | } |
||
637 | daniel-mar | 1511 | this._initializeChildren(); |
597 | daniel-mar | 1512 | if (!this._config.parent) { |
637 | daniel-mar | 1513 | this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()); |
597 | daniel-mar | 1514 | } |
1515 | if (this._config.toggle) { |
||
1516 | this.toggle(); |
||
1517 | } |
||
1056 | daniel-mar | 1518 | } |
597 | daniel-mar | 1519 | |
1056 | daniel-mar | 1520 | // Getters |
597 | daniel-mar | 1521 | static get Default() { |
846 | daniel-mar | 1522 | return Default$a; |
597 | daniel-mar | 1523 | } |
846 | daniel-mar | 1524 | static get DefaultType() { |
1525 | return DefaultType$a; |
||
1526 | } |
||
597 | daniel-mar | 1527 | static get NAME() { |
846 | daniel-mar | 1528 | return NAME$b; |
1056 | daniel-mar | 1529 | } |
597 | daniel-mar | 1530 | |
1056 | daniel-mar | 1531 | // Public |
597 | daniel-mar | 1532 | toggle() { |
637 | daniel-mar | 1533 | if (this._isShown()) { |
597 | daniel-mar | 1534 | this.hide(); |
1535 | } else { |
||
1536 | this.show(); |
||
1537 | } |
||
1538 | } |
||
1539 | show() { |
||
637 | daniel-mar | 1540 | if (this._isTransitioning || this._isShown()) { |
597 | daniel-mar | 1541 | return; |
1542 | } |
||
1056 | daniel-mar | 1543 | let activeChildren = []; |
597 | daniel-mar | 1544 | |
1056 | daniel-mar | 1545 | // find active children |
637 | daniel-mar | 1546 | if (this._config.parent) { |
846 | daniel-mar | 1547 | activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, { |
1548 | toggle: false |
||
1549 | })); |
||
597 | daniel-mar | 1550 | } |
846 | daniel-mar | 1551 | if (activeChildren.length && activeChildren[0]._isTransitioning) { |
1552 | return; |
||
597 | daniel-mar | 1553 | } |
846 | daniel-mar | 1554 | const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$6); |
597 | daniel-mar | 1555 | if (startEvent.defaultPrevented) { |
1556 | return; |
||
1557 | } |
||
846 | daniel-mar | 1558 | for (const activeInstance of activeChildren) { |
1559 | activeInstance.hide(); |
||
1560 | } |
||
597 | daniel-mar | 1561 | const dimension = this._getDimension(); |
1562 | this._element.classList.remove(CLASS_NAME_COLLAPSE); |
||
1563 | this._element.classList.add(CLASS_NAME_COLLAPSING); |
||
1564 | this._element.style[dimension] = 0; |
||
637 | daniel-mar | 1565 | this._addAriaAndCollapsedClass(this._triggerArray, true); |
1566 | this._isTransitioning = true; |
||
597 | daniel-mar | 1567 | const complete = () => { |
637 | daniel-mar | 1568 | this._isTransitioning = false; |
597 | daniel-mar | 1569 | this._element.classList.remove(CLASS_NAME_COLLAPSING); |
637 | daniel-mar | 1570 | this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); |
597 | daniel-mar | 1571 | this._element.style[dimension] = ''; |
846 | daniel-mar | 1572 | EventHandler.trigger(this._element, EVENT_SHOWN$6); |
597 | daniel-mar | 1573 | }; |
1574 | const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); |
||
1575 | const scrollSize = `scroll${capitalizedDimension}`; |
||
1576 | this._queueCallback(complete, this._element, true); |
||
1577 | this._element.style[dimension] = `${this._element[scrollSize]}px`; |
||
1578 | } |
||
1579 | hide() { |
||
637 | daniel-mar | 1580 | if (this._isTransitioning || !this._isShown()) { |
597 | daniel-mar | 1581 | return; |
1582 | } |
||
846 | daniel-mar | 1583 | const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$6); |
597 | daniel-mar | 1584 | if (startEvent.defaultPrevented) { |
1585 | return; |
||
1586 | } |
||
1587 | const dimension = this._getDimension(); |
||
1588 | this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`; |
||
1589 | reflow(this._element); |
||
1590 | this._element.classList.add(CLASS_NAME_COLLAPSING); |
||
637 | daniel-mar | 1591 | this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); |
846 | daniel-mar | 1592 | for (const trigger of this._triggerArray) { |
1056 | daniel-mar | 1593 | const element = SelectorEngine.getElementFromSelector(trigger); |
846 | daniel-mar | 1594 | if (element && !this._isShown(element)) { |
637 | daniel-mar | 1595 | this._addAriaAndCollapsedClass([trigger], false); |
597 | daniel-mar | 1596 | } |
1597 | } |
||
637 | daniel-mar | 1598 | this._isTransitioning = true; |
597 | daniel-mar | 1599 | const complete = () => { |
637 | daniel-mar | 1600 | this._isTransitioning = false; |
597 | daniel-mar | 1601 | this._element.classList.remove(CLASS_NAME_COLLAPSING); |
1602 | this._element.classList.add(CLASS_NAME_COLLAPSE); |
||
846 | daniel-mar | 1603 | EventHandler.trigger(this._element, EVENT_HIDDEN$6); |
597 | daniel-mar | 1604 | }; |
1605 | this._element.style[dimension] = ''; |
||
1606 | this._queueCallback(complete, this._element, true); |
||
1607 | } |
||
637 | daniel-mar | 1608 | _isShown(element = this._element) { |
1609 | return element.classList.contains(CLASS_NAME_SHOW$7); |
||
1056 | daniel-mar | 1610 | } |
597 | daniel-mar | 1611 | |
1056 | daniel-mar | 1612 | // Private |
846 | daniel-mar | 1613 | _configAfterMerge(config) { |
597 | daniel-mar | 1614 | config.toggle = Boolean(config.toggle); // Coerce string values |
637 | daniel-mar | 1615 | config.parent = getElement(config.parent); |
597 | daniel-mar | 1616 | return config; |
1617 | } |
||
1618 | _getDimension() { |
||
637 | daniel-mar | 1619 | return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT; |
597 | daniel-mar | 1620 | } |
637 | daniel-mar | 1621 | _initializeChildren() { |
1622 | if (!this._config.parent) { |
||
1623 | return; |
||
1624 | } |
||
846 | daniel-mar | 1625 | const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$4); |
1626 | for (const element of children) { |
||
1056 | daniel-mar | 1627 | const selected = SelectorEngine.getElementFromSelector(element); |
637 | daniel-mar | 1628 | if (selected) { |
1629 | this._addAriaAndCollapsedClass([element], this._isShown(selected)); |
||
1630 | } |
||
846 | daniel-mar | 1631 | } |
597 | daniel-mar | 1632 | } |
846 | daniel-mar | 1633 | _getFirstLevelChildren(selector) { |
1056 | daniel-mar | 1634 | const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent); |
1635 | // remove children if greater depth |
||
846 | daniel-mar | 1636 | return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element)); |
1637 | } |
||
637 | daniel-mar | 1638 | _addAriaAndCollapsedClass(triggerArray, isOpen) { |
1639 | if (!triggerArray.length) { |
||
597 | daniel-mar | 1640 | return; |
1641 | } |
||
846 | daniel-mar | 1642 | for (const element of triggerArray) { |
1643 | element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen); |
||
1644 | element.setAttribute('aria-expanded', isOpen); |
||
1645 | } |
||
1056 | daniel-mar | 1646 | } |
597 | daniel-mar | 1647 | |
1056 | daniel-mar | 1648 | // Static |
637 | daniel-mar | 1649 | static jQueryInterface(config) { |
846 | daniel-mar | 1650 | const _config = {}; |
1651 | if (typeof config === 'string' && /show|hide/.test(config)) { |
||
1652 | _config.toggle = false; |
||
1653 | } |
||
1654 | return this.each(function () { |
||
637 | daniel-mar | 1655 | const data = Collapse.getOrCreateInstance(this, _config); |
1656 | if (typeof config === 'string') { |
||
1657 | if (typeof data[config] === 'undefined') { |
||
1658 | throw new TypeError(`No method named "${config}"`); |
||
1659 | } |
||
1660 | data[config](); |
||
597 | daniel-mar | 1661 | } |
1662 | }); |
||
1663 | } |
||
1056 | daniel-mar | 1664 | } |
597 | daniel-mar | 1665 | |
1666 | /** |
||
846 | daniel-mar | 1667 | * Data API implementation |
597 | daniel-mar | 1668 | */ |
1669 | |||
1670 | EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) { |
||
1671 | // preventDefault only for <a> elements (which change the URL) not inside the collapsible element |
||
1672 | if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') { |
||
1673 | event.preventDefault(); |
||
1674 | } |
||
1056 | daniel-mar | 1675 | for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) { |
637 | daniel-mar | 1676 | Collapse.getOrCreateInstance(element, { |
1677 | toggle: false |
||
1678 | }).toggle(); |
||
846 | daniel-mar | 1679 | } |
597 | daniel-mar | 1680 | }); |
1056 | daniel-mar | 1681 | |
597 | daniel-mar | 1682 | /** |
1683 | * jQuery |
||
1684 | */ |
||
1685 | |||
1686 | defineJQueryPlugin(Collapse); |
||
1687 | |||
1688 | var top = 'top'; |
||
1689 | var bottom = 'bottom'; |
||
1690 | var right = 'right'; |
||
1691 | var left = 'left'; |
||
1692 | var auto = 'auto'; |
||
1693 | var basePlacements = [top, bottom, right, left]; |
||
1694 | var start = 'start'; |
||
1695 | var end = 'end'; |
||
1696 | var clippingParents = 'clippingParents'; |
||
1697 | var viewport = 'viewport'; |
||
1698 | var popper = 'popper'; |
||
1699 | var reference = 'reference'; |
||
1700 | var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) { |
||
1701 | return acc.concat([placement + "-" + start, placement + "-" + end]); |
||
1702 | }, []); |
||
1703 | var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) { |
||
1704 | return acc.concat([placement, placement + "-" + start, placement + "-" + end]); |
||
1705 | }, []); // modifiers that need to read the DOM |
||
1706 | |||
1707 | var beforeRead = 'beforeRead'; |
||
1708 | var read = 'read'; |
||
1709 | var afterRead = 'afterRead'; // pure-logic modifiers |
||
1710 | |||
1711 | var beforeMain = 'beforeMain'; |
||
1712 | var main = 'main'; |
||
1713 | var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state) |
||
1714 | |||
1715 | var beforeWrite = 'beforeWrite'; |
||
1716 | var write = 'write'; |
||
1717 | var afterWrite = 'afterWrite'; |
||
1718 | var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite]; |
||
1719 | |||
1720 | function getNodeName(element) { |
||
1721 | return element ? (element.nodeName || '').toLowerCase() : null; |
||
1722 | } |
||
1723 | |||
1724 | function getWindow(node) { |
||
1725 | if (node == null) { |
||
1726 | return window; |
||
1727 | } |
||
1728 | |||
1729 | if (node.toString() !== '[object Window]') { |
||
1730 | var ownerDocument = node.ownerDocument; |
||
1731 | return ownerDocument ? ownerDocument.defaultView || window : window; |
||
1732 | } |
||
1733 | |||
1734 | return node; |
||
1735 | } |
||
1736 | |||
1737 | function isElement(node) { |
||
1738 | var OwnElement = getWindow(node).Element; |
||
1739 | return node instanceof OwnElement || node instanceof Element; |
||
1740 | } |
||
1741 | |||
1742 | function isHTMLElement(node) { |
||
1743 | var OwnElement = getWindow(node).HTMLElement; |
||
1744 | return node instanceof OwnElement || node instanceof HTMLElement; |
||
1745 | } |
||
1746 | |||
1747 | function isShadowRoot(node) { |
||
1748 | // IE 11 has no ShadowRoot |
||
1749 | if (typeof ShadowRoot === 'undefined') { |
||
1750 | return false; |
||
1751 | } |
||
1752 | |||
1753 | var OwnElement = getWindow(node).ShadowRoot; |
||
1754 | return node instanceof OwnElement || node instanceof ShadowRoot; |
||
1755 | } |
||
1756 | |||
1757 | // and applies them to the HTMLElements such as popper and arrow |
||
1758 | |||
1759 | function applyStyles(_ref) { |
||
1760 | var state = _ref.state; |
||
1761 | Object.keys(state.elements).forEach(function (name) { |
||
1762 | var style = state.styles[name] || {}; |
||
1763 | var attributes = state.attributes[name] || {}; |
||
1764 | var element = state.elements[name]; // arrow is optional + virtual elements |
||
1765 | |||
1766 | if (!isHTMLElement(element) || !getNodeName(element)) { |
||
1767 | return; |
||
1768 | } // Flow doesn't support to extend this property, but it's the most |
||
1769 | // effective way to apply styles to an HTMLElement |
||
1770 | // $FlowFixMe[cannot-write] |
||
1771 | |||
1772 | |||
1773 | Object.assign(element.style, style); |
||
1774 | Object.keys(attributes).forEach(function (name) { |
||
1775 | var value = attributes[name]; |
||
1776 | |||
1777 | if (value === false) { |
||
1778 | element.removeAttribute(name); |
||
1779 | } else { |
||
1780 | element.setAttribute(name, value === true ? '' : value); |
||
1781 | } |
||
1782 | }); |
||
1783 | }); |
||
1784 | } |
||
1785 | |||
1786 | function effect$2(_ref2) { |
||
1787 | var state = _ref2.state; |
||
1788 | var initialStyles = { |
||
1789 | popper: { |
||
1790 | position: state.options.strategy, |
||
1791 | left: '0', |
||
1792 | top: '0', |
||
1793 | margin: '0' |
||
1794 | }, |
||
1795 | arrow: { |
||
1796 | position: 'absolute' |
||
1797 | }, |
||
1798 | reference: {} |
||
1799 | }; |
||
1800 | Object.assign(state.elements.popper.style, initialStyles.popper); |
||
1801 | state.styles = initialStyles; |
||
1802 | |||
1803 | if (state.elements.arrow) { |
||
1804 | Object.assign(state.elements.arrow.style, initialStyles.arrow); |
||
1805 | } |
||
1806 | |||
1807 | return function () { |
||
1808 | Object.keys(state.elements).forEach(function (name) { |
||
1809 | var element = state.elements[name]; |
||
1810 | var attributes = state.attributes[name] || {}; |
||
1811 | var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them |
||
1812 | |||
1813 | var style = styleProperties.reduce(function (style, property) { |
||
1814 | style[property] = ''; |
||
1815 | return style; |
||
1816 | }, {}); // arrow is optional + virtual elements |
||
1817 | |||
1818 | if (!isHTMLElement(element) || !getNodeName(element)) { |
||
1819 | return; |
||
1820 | } |
||
1821 | |||
1822 | Object.assign(element.style, style); |
||
1823 | Object.keys(attributes).forEach(function (attribute) { |
||
1824 | element.removeAttribute(attribute); |
||
1825 | }); |
||
1826 | }); |
||
1827 | }; |
||
1828 | } // eslint-disable-next-line import/no-unused-modules |
||
1829 | |||
1830 | |||
679 | daniel-mar | 1831 | const applyStyles$1 = { |
597 | daniel-mar | 1832 | name: 'applyStyles', |
1833 | enabled: true, |
||
1834 | phase: 'write', |
||
1835 | fn: applyStyles, |
||
1836 | effect: effect$2, |
||
1837 | requires: ['computeStyles'] |
||
1838 | }; |
||
1839 | |||
1840 | function getBasePlacement(placement) { |
||
1841 | return placement.split('-')[0]; |
||
1842 | } |
||
1843 | |||
846 | daniel-mar | 1844 | var max = Math.max; |
1845 | var min = Math.min; |
||
1846 | var round = Math.round; |
||
637 | daniel-mar | 1847 | |
931 | daniel-mar | 1848 | function getUAString() { |
1849 | var uaData = navigator.userAgentData; |
||
1850 | |||
1151 | daniel-mar | 1851 | if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) { |
931 | daniel-mar | 1852 | return uaData.brands.map(function (item) { |
1853 | return item.brand + "/" + item.version; |
||
1854 | }).join(' '); |
||
1855 | } |
||
1856 | |||
1857 | return navigator.userAgent; |
||
1858 | } |
||
1859 | |||
1860 | function isLayoutViewport() { |
||
1861 | return !/^((?!chrome|android).)*safari/i.test(getUAString()); |
||
1862 | } |
||
1863 | |||
1864 | function getBoundingClientRect(element, includeScale, isFixedStrategy) { |
||
846 | daniel-mar | 1865 | if (includeScale === void 0) { |
1866 | includeScale = false; |
||
1867 | } |
||
1868 | |||
931 | daniel-mar | 1869 | if (isFixedStrategy === void 0) { |
1870 | isFixedStrategy = false; |
||
1871 | } |
||
1872 | |||
1873 | var clientRect = element.getBoundingClientRect(); |
||
637 | daniel-mar | 1874 | var scaleX = 1; |
846 | daniel-mar | 1875 | var scaleY = 1; |
637 | daniel-mar | 1876 | |
931 | daniel-mar | 1877 | if (includeScale && isHTMLElement(element)) { |
1878 | scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1; |
||
1879 | scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1; |
||
1880 | } |
||
846 | daniel-mar | 1881 | |
931 | daniel-mar | 1882 | var _ref = isElement(element) ? getWindow(element) : window, |
1883 | visualViewport = _ref.visualViewport; |
||
846 | daniel-mar | 1884 | |
931 | daniel-mar | 1885 | var addVisualOffsets = !isLayoutViewport() && isFixedStrategy; |
1886 | var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX; |
||
1887 | var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY; |
||
1888 | var width = clientRect.width / scaleX; |
||
1889 | var height = clientRect.height / scaleY; |
||
597 | daniel-mar | 1890 | return { |
931 | daniel-mar | 1891 | width: width, |
1892 | height: height, |
||
1893 | top: y, |
||
1894 | right: x + width, |
||
1895 | bottom: y + height, |
||
1896 | left: x, |
||
1897 | x: x, |
||
1898 | y: y |
||
597 | daniel-mar | 1899 | }; |
1900 | } |
||
1901 | |||
1902 | // means it doesn't take into account transforms. |
||
1903 | |||
1904 | function getLayoutRect(element) { |
||
1905 | var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed. |
||
1906 | // Fixes https://github.com/popperjs/popper-core/issues/1223 |
||
1907 | |||
1908 | var width = element.offsetWidth; |
||
1909 | var height = element.offsetHeight; |
||
1910 | |||
1911 | if (Math.abs(clientRect.width - width) <= 1) { |
||
1912 | width = clientRect.width; |
||
1913 | } |
||
1914 | |||
1915 | if (Math.abs(clientRect.height - height) <= 1) { |
||
1916 | height = clientRect.height; |
||
1917 | } |
||
1918 | |||
1919 | return { |
||
1920 | x: element.offsetLeft, |
||
1921 | y: element.offsetTop, |
||
1922 | width: width, |
||
1923 | height: height |
||
1924 | }; |
||
1925 | } |
||
1926 | |||
1927 | function contains(parent, child) { |
||
1928 | var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method |
||
1929 | |||
1930 | if (parent.contains(child)) { |
||
1931 | return true; |
||
1932 | } // then fallback to custom implementation with Shadow DOM support |
||
1933 | else if (rootNode && isShadowRoot(rootNode)) { |
||
1934 | var next = child; |
||
1935 | |||
1936 | do { |
||
1937 | if (next && parent.isSameNode(next)) { |
||
1938 | return true; |
||
1939 | } // $FlowFixMe[prop-missing]: need a better way to handle this... |
||
1940 | |||
1941 | |||
1942 | next = next.parentNode || next.host; |
||
1943 | } while (next); |
||
1944 | } // Give up, the result is false |
||
1945 | |||
1946 | |||
1947 | return false; |
||
1948 | } |
||
1949 | |||
1950 | function getComputedStyle$1(element) { |
||
1951 | return getWindow(element).getComputedStyle(element); |
||
1952 | } |
||
1953 | |||
1954 | function isTableElement(element) { |
||
1955 | return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0; |
||
1956 | } |
||
1957 | |||
1958 | function getDocumentElement(element) { |
||
1959 | // $FlowFixMe[incompatible-return]: assume body is always available |
||
1960 | return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing] |
||
1961 | element.document) || window.document).documentElement; |
||
1962 | } |
||
1963 | |||
1964 | function getParentNode(element) { |
||
1965 | if (getNodeName(element) === 'html') { |
||
1966 | return element; |
||
1967 | } |
||
1968 | |||
1969 | return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle |
||
1970 | // $FlowFixMe[incompatible-return] |
||
1971 | // $FlowFixMe[prop-missing] |
||
1972 | element.assignedSlot || // step into the shadow DOM of the parent of a slotted node |
||
1973 | element.parentNode || ( // DOM Element detected |
||
1974 | isShadowRoot(element) ? element.host : null) || // ShadowRoot detected |
||
1975 | // $FlowFixMe[incompatible-call]: HTMLElement is a Node |
||
1976 | getDocumentElement(element) // fallback |
||
1977 | |||
1978 | ); |
||
1979 | } |
||
1980 | |||
1981 | function getTrueOffsetParent(element) { |
||
1982 | if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837 |
||
1983 | getComputedStyle$1(element).position === 'fixed') { |
||
1984 | return null; |
||
1985 | } |
||
1986 | |||
1987 | return element.offsetParent; |
||
1988 | } // `.offsetParent` reports `null` for fixed elements, while absolute elements |
||
1989 | // return the containing block |
||
1990 | |||
1991 | |||
1992 | function getContainingBlock(element) { |
||
931 | daniel-mar | 1993 | var isFirefox = /firefox/i.test(getUAString()); |
1994 | var isIE = /Trident/i.test(getUAString()); |
||
597 | daniel-mar | 1995 | |
1996 | if (isIE && isHTMLElement(element)) { |
||
1997 | // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport |
||
1998 | var elementCss = getComputedStyle$1(element); |
||
1999 | |||
2000 | if (elementCss.position === 'fixed') { |
||
2001 | return null; |
||
2002 | } |
||
2003 | } |
||
2004 | |||
2005 | var currentNode = getParentNode(element); |
||
2006 | |||
846 | daniel-mar | 2007 | if (isShadowRoot(currentNode)) { |
2008 | currentNode = currentNode.host; |
||
2009 | } |
||
2010 | |||
597 | daniel-mar | 2011 | while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) { |
2012 | var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that |
||
2013 | // create a containing block. |
||
2014 | // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block |
||
2015 | |||
2016 | if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') { |
||
2017 | return currentNode; |
||
2018 | } else { |
||
2019 | currentNode = currentNode.parentNode; |
||
2020 | } |
||
2021 | } |
||
2022 | |||
2023 | return null; |
||
2024 | } // Gets the closest ancestor positioned element. Handles some edge cases, |
||
2025 | // such as table ancestors and cross browser bugs. |
||
2026 | |||
2027 | |||
2028 | function getOffsetParent(element) { |
||
2029 | var window = getWindow(element); |
||
2030 | var offsetParent = getTrueOffsetParent(element); |
||
2031 | |||
2032 | while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') { |
||
2033 | offsetParent = getTrueOffsetParent(offsetParent); |
||
2034 | } |
||
2035 | |||
2036 | if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static')) { |
||
2037 | return window; |
||
2038 | } |
||
2039 | |||
2040 | return offsetParent || getContainingBlock(element) || window; |
||
2041 | } |
||
2042 | |||
2043 | function getMainAxisFromPlacement(placement) { |
||
2044 | return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y'; |
||
2045 | } |
||
2046 | |||
2047 | function within(min$1, value, max$1) { |
||
2048 | return max(min$1, min(value, max$1)); |
||
2049 | } |
||
846 | daniel-mar | 2050 | function withinMaxClamp(min, value, max) { |
2051 | var v = within(min, value, max); |
||
2052 | return v > max ? max : v; |
||
2053 | } |
||
597 | daniel-mar | 2054 | |
2055 | function getFreshSideObject() { |
||
2056 | return { |
||
2057 | top: 0, |
||
2058 | right: 0, |
||
2059 | bottom: 0, |
||
2060 | left: 0 |
||
2061 | }; |
||
2062 | } |
||
2063 | |||
2064 | function mergePaddingObject(paddingObject) { |
||
2065 | return Object.assign({}, getFreshSideObject(), paddingObject); |
||
2066 | } |
||
2067 | |||
2068 | function expandToHashMap(value, keys) { |
||
2069 | return keys.reduce(function (hashMap, key) { |
||
2070 | hashMap[key] = value; |
||
2071 | return hashMap; |
||
2072 | }, {}); |
||
2073 | } |
||
2074 | |||
2075 | var toPaddingObject = function toPaddingObject(padding, state) { |
||
2076 | padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, { |
||
2077 | placement: state.placement |
||
2078 | })) : padding; |
||
2079 | return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); |
||
2080 | }; |
||
2081 | |||
2082 | function arrow(_ref) { |
||
2083 | var _state$modifiersData$; |
||
2084 | |||
2085 | var state = _ref.state, |
||
2086 | name = _ref.name, |
||
2087 | options = _ref.options; |
||
2088 | var arrowElement = state.elements.arrow; |
||
2089 | var popperOffsets = state.modifiersData.popperOffsets; |
||
2090 | var basePlacement = getBasePlacement(state.placement); |
||
2091 | var axis = getMainAxisFromPlacement(basePlacement); |
||
2092 | var isVertical = [left, right].indexOf(basePlacement) >= 0; |
||
2093 | var len = isVertical ? 'height' : 'width'; |
||
2094 | |||
2095 | if (!arrowElement || !popperOffsets) { |
||
2096 | return; |
||
2097 | } |
||
2098 | |||
2099 | var paddingObject = toPaddingObject(options.padding, state); |
||
2100 | var arrowRect = getLayoutRect(arrowElement); |
||
2101 | var minProp = axis === 'y' ? top : left; |
||
2102 | var maxProp = axis === 'y' ? bottom : right; |
||
2103 | var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len]; |
||
2104 | var startDiff = popperOffsets[axis] - state.rects.reference[axis]; |
||
2105 | var arrowOffsetParent = getOffsetParent(arrowElement); |
||
2106 | var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0; |
||
2107 | var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is |
||
2108 | // outside of the popper bounds |
||
2109 | |||
2110 | var min = paddingObject[minProp]; |
||
2111 | var max = clientSize - arrowRect[len] - paddingObject[maxProp]; |
||
2112 | var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference; |
||
2113 | var offset = within(min, center, max); // Prevents breaking syntax highlighting... |
||
2114 | |||
2115 | var axisProp = axis; |
||
2116 | state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$); |
||
2117 | } |
||
2118 | |||
2119 | function effect$1(_ref2) { |
||
2120 | var state = _ref2.state, |
||
2121 | options = _ref2.options; |
||
2122 | var _options$element = options.element, |
||
2123 | arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element; |
||
2124 | |||
2125 | if (arrowElement == null) { |
||
2126 | return; |
||
2127 | } // CSS selector |
||
2128 | |||
2129 | |||
2130 | if (typeof arrowElement === 'string') { |
||
2131 | arrowElement = state.elements.popper.querySelector(arrowElement); |
||
2132 | |||
2133 | if (!arrowElement) { |
||
2134 | return; |
||
2135 | } |
||
2136 | } |
||
2137 | |||
2138 | if (!contains(state.elements.popper, arrowElement)) { |
||
2139 | return; |
||
2140 | } |
||
2141 | |||
2142 | state.elements.arrow = arrowElement; |
||
2143 | } // eslint-disable-next-line import/no-unused-modules |
||
2144 | |||
2145 | |||
679 | daniel-mar | 2146 | const arrow$1 = { |
597 | daniel-mar | 2147 | name: 'arrow', |
2148 | enabled: true, |
||
2149 | phase: 'main', |
||
2150 | fn: arrow, |
||
2151 | effect: effect$1, |
||
2152 | requires: ['popperOffsets'], |
||
2153 | requiresIfExists: ['preventOverflow'] |
||
2154 | }; |
||
2155 | |||
637 | daniel-mar | 2156 | function getVariation(placement) { |
2157 | return placement.split('-')[1]; |
||
2158 | } |
||
2159 | |||
597 | daniel-mar | 2160 | var unsetSides = { |
2161 | top: 'auto', |
||
2162 | right: 'auto', |
||
2163 | bottom: 'auto', |
||
2164 | left: 'auto' |
||
2165 | }; // Round the offsets to the nearest suitable subpixel based on the DPR. |
||
2166 | // Zooming can change the DPR, but it seems to report a value that will |
||
2167 | // cleanly divide the values into the appropriate subpixels. |
||
2168 | |||
1151 | daniel-mar | 2169 | function roundOffsetsByDPR(_ref, win) { |
597 | daniel-mar | 2170 | var x = _ref.x, |
2171 | y = _ref.y; |
||
2172 | var dpr = win.devicePixelRatio || 1; |
||
2173 | return { |
||
846 | daniel-mar | 2174 | x: round(x * dpr) / dpr || 0, |
2175 | y: round(y * dpr) / dpr || 0 |
||
597 | daniel-mar | 2176 | }; |
2177 | } |
||
2178 | |||
2179 | function mapToStyles(_ref2) { |
||
2180 | var _Object$assign2; |
||
2181 | |||
2182 | var popper = _ref2.popper, |
||
2183 | popperRect = _ref2.popperRect, |
||
2184 | placement = _ref2.placement, |
||
637 | daniel-mar | 2185 | variation = _ref2.variation, |
597 | daniel-mar | 2186 | offsets = _ref2.offsets, |
2187 | position = _ref2.position, |
||
2188 | gpuAcceleration = _ref2.gpuAcceleration, |
||
2189 | adaptive = _ref2.adaptive, |
||
846 | daniel-mar | 2190 | roundOffsets = _ref2.roundOffsets, |
2191 | isFixed = _ref2.isFixed; |
||
2192 | var _offsets$x = offsets.x, |
||
2193 | x = _offsets$x === void 0 ? 0 : _offsets$x, |
||
2194 | _offsets$y = offsets.y, |
||
2195 | y = _offsets$y === void 0 ? 0 : _offsets$y; |
||
597 | daniel-mar | 2196 | |
846 | daniel-mar | 2197 | var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({ |
2198 | x: x, |
||
2199 | y: y |
||
2200 | }) : { |
||
2201 | x: x, |
||
2202 | y: y |
||
2203 | }; |
||
597 | daniel-mar | 2204 | |
846 | daniel-mar | 2205 | x = _ref3.x; |
2206 | y = _ref3.y; |
||
597 | daniel-mar | 2207 | var hasX = offsets.hasOwnProperty('x'); |
2208 | var hasY = offsets.hasOwnProperty('y'); |
||
2209 | var sideX = left; |
||
2210 | var sideY = top; |
||
2211 | var win = window; |
||
2212 | |||
2213 | if (adaptive) { |
||
2214 | var offsetParent = getOffsetParent(popper); |
||
2215 | var heightProp = 'clientHeight'; |
||
2216 | var widthProp = 'clientWidth'; |
||
2217 | |||
2218 | if (offsetParent === getWindow(popper)) { |
||
2219 | offsetParent = getDocumentElement(popper); |
||
2220 | |||
637 | daniel-mar | 2221 | if (getComputedStyle$1(offsetParent).position !== 'static' && position === 'absolute') { |
597 | daniel-mar | 2222 | heightProp = 'scrollHeight'; |
2223 | widthProp = 'scrollWidth'; |
||
2224 | } |
||
2225 | } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it |
||
2226 | |||
2227 | |||
2228 | offsetParent = offsetParent; |
||
2229 | |||
637 | daniel-mar | 2230 | if (placement === top || (placement === left || placement === right) && variation === end) { |
846 | daniel-mar | 2231 | sideY = bottom; |
2232 | var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing] |
||
2233 | offsetParent[heightProp]; |
||
2234 | y -= offsetY - popperRect.height; |
||
597 | daniel-mar | 2235 | y *= gpuAcceleration ? 1 : -1; |
2236 | } |
||
2237 | |||
637 | daniel-mar | 2238 | if (placement === left || (placement === top || placement === bottom) && variation === end) { |
846 | daniel-mar | 2239 | sideX = right; |
2240 | var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing] |
||
2241 | offsetParent[widthProp]; |
||
2242 | x -= offsetX - popperRect.width; |
||
597 | daniel-mar | 2243 | x *= gpuAcceleration ? 1 : -1; |
2244 | } |
||
2245 | } |
||
2246 | |||
2247 | var commonStyles = Object.assign({ |
||
2248 | position: position |
||
2249 | }, adaptive && unsetSides); |
||
2250 | |||
846 | daniel-mar | 2251 | var _ref4 = roundOffsets === true ? roundOffsetsByDPR({ |
2252 | x: x, |
||
2253 | y: y |
||
1151 | daniel-mar | 2254 | }, getWindow(popper)) : { |
846 | daniel-mar | 2255 | x: x, |
2256 | y: y |
||
2257 | }; |
||
2258 | |||
2259 | x = _ref4.x; |
||
2260 | y = _ref4.y; |
||
2261 | |||
597 | daniel-mar | 2262 | if (gpuAcceleration) { |
2263 | var _Object$assign; |
||
2264 | |||
637 | daniel-mar | 2265 | return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign)); |
597 | daniel-mar | 2266 | } |
2267 | |||
2268 | return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2)); |
||
2269 | } |
||
2270 | |||
846 | daniel-mar | 2271 | function computeStyles(_ref5) { |
2272 | var state = _ref5.state, |
||
2273 | options = _ref5.options; |
||
597 | daniel-mar | 2274 | var _options$gpuAccelerat = options.gpuAcceleration, |
2275 | gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, |
||
2276 | _options$adaptive = options.adaptive, |
||
2277 | adaptive = _options$adaptive === void 0 ? true : _options$adaptive, |
||
2278 | _options$roundOffsets = options.roundOffsets, |
||
2279 | roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets; |
||
2280 | var commonStyles = { |
||
2281 | placement: getBasePlacement(state.placement), |
||
637 | daniel-mar | 2282 | variation: getVariation(state.placement), |
597 | daniel-mar | 2283 | popper: state.elements.popper, |
2284 | popperRect: state.rects.popper, |
||
846 | daniel-mar | 2285 | gpuAcceleration: gpuAcceleration, |
2286 | isFixed: state.options.strategy === 'fixed' |
||
597 | daniel-mar | 2287 | }; |
2288 | |||
2289 | if (state.modifiersData.popperOffsets != null) { |
||
2290 | state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, { |
||
2291 | offsets: state.modifiersData.popperOffsets, |
||
2292 | position: state.options.strategy, |
||
2293 | adaptive: adaptive, |
||
2294 | roundOffsets: roundOffsets |
||
2295 | }))); |
||
2296 | } |
||
2297 | |||
2298 | if (state.modifiersData.arrow != null) { |
||
2299 | state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, { |
||
2300 | offsets: state.modifiersData.arrow, |
||
2301 | position: 'absolute', |
||
2302 | adaptive: false, |
||
2303 | roundOffsets: roundOffsets |
||
2304 | }))); |
||
2305 | } |
||
2306 | |||
2307 | state.attributes.popper = Object.assign({}, state.attributes.popper, { |
||
2308 | 'data-popper-placement': state.placement |
||
2309 | }); |
||
2310 | } // eslint-disable-next-line import/no-unused-modules |
||
2311 | |||
2312 | |||
679 | daniel-mar | 2313 | const computeStyles$1 = { |
597 | daniel-mar | 2314 | name: 'computeStyles', |
2315 | enabled: true, |
||
2316 | phase: 'beforeWrite', |
||
2317 | fn: computeStyles, |
||
2318 | data: {} |
||
2319 | }; |
||
2320 | |||
2321 | var passive = { |
||
2322 | passive: true |
||
2323 | }; |
||
2324 | |||
2325 | function effect(_ref) { |
||
2326 | var state = _ref.state, |
||
2327 | instance = _ref.instance, |
||
2328 | options = _ref.options; |
||
2329 | var _options$scroll = options.scroll, |
||
2330 | scroll = _options$scroll === void 0 ? true : _options$scroll, |
||
2331 | _options$resize = options.resize, |
||
2332 | resize = _options$resize === void 0 ? true : _options$resize; |
||
2333 | var window = getWindow(state.elements.popper); |
||
2334 | var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper); |
||
2335 | |||
2336 | if (scroll) { |
||
2337 | scrollParents.forEach(function (scrollParent) { |
||
2338 | scrollParent.addEventListener('scroll', instance.update, passive); |
||
2339 | }); |
||
2340 | } |
||
2341 | |||
2342 | if (resize) { |
||
2343 | window.addEventListener('resize', instance.update, passive); |
||
2344 | } |
||
2345 | |||
2346 | return function () { |
||
2347 | if (scroll) { |
||
2348 | scrollParents.forEach(function (scrollParent) { |
||
2349 | scrollParent.removeEventListener('scroll', instance.update, passive); |
||
2350 | }); |
||
2351 | } |
||
2352 | |||
2353 | if (resize) { |
||
2354 | window.removeEventListener('resize', instance.update, passive); |
||
2355 | } |
||
2356 | }; |
||
2357 | } // eslint-disable-next-line import/no-unused-modules |
||
2358 | |||
2359 | |||
679 | daniel-mar | 2360 | const eventListeners = { |
597 | daniel-mar | 2361 | name: 'eventListeners', |
2362 | enabled: true, |
||
2363 | phase: 'write', |
||
2364 | fn: function fn() {}, |
||
2365 | effect: effect, |
||
2366 | data: {} |
||
2367 | }; |
||
2368 | |||
2369 | var hash$1 = { |
||
2370 | left: 'right', |
||
2371 | right: 'left', |
||
2372 | bottom: 'top', |
||
2373 | top: 'bottom' |
||
2374 | }; |
||
2375 | function getOppositePlacement(placement) { |
||
2376 | return placement.replace(/left|right|bottom|top/g, function (matched) { |
||
2377 | return hash$1[matched]; |
||
2378 | }); |
||
2379 | } |
||
2380 | |||
2381 | var hash = { |
||
2382 | start: 'end', |
||
2383 | end: 'start' |
||
2384 | }; |
||
2385 | function getOppositeVariationPlacement(placement) { |
||
2386 | return placement.replace(/start|end/g, function (matched) { |
||
2387 | return hash[matched]; |
||
2388 | }); |
||
2389 | } |
||
2390 | |||
2391 | function getWindowScroll(node) { |
||
2392 | var win = getWindow(node); |
||
2393 | var scrollLeft = win.pageXOffset; |
||
2394 | var scrollTop = win.pageYOffset; |
||
2395 | return { |
||
2396 | scrollLeft: scrollLeft, |
||
2397 | scrollTop: scrollTop |
||
2398 | }; |
||
2399 | } |
||
2400 | |||
2401 | function getWindowScrollBarX(element) { |
||
2402 | // If <html> has a CSS width greater than the viewport, then this will be |
||
2403 | // incorrect for RTL. |
||
2404 | // Popper 1 is broken in this case and never had a bug report so let's assume |
||
2405 | // it's not an issue. I don't think anyone ever specifies width on <html> |
||
2406 | // anyway. |
||
2407 | // Browsers where the left scrollbar doesn't cause an issue report `0` for |
||
2408 | // this (e.g. Edge 2019, IE11, Safari) |
||
2409 | return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft; |
||
2410 | } |
||
2411 | |||
931 | daniel-mar | 2412 | function getViewportRect(element, strategy) { |
597 | daniel-mar | 2413 | var win = getWindow(element); |
2414 | var html = getDocumentElement(element); |
||
2415 | var visualViewport = win.visualViewport; |
||
2416 | var width = html.clientWidth; |
||
2417 | var height = html.clientHeight; |
||
2418 | var x = 0; |
||
931 | daniel-mar | 2419 | var y = 0; |
597 | daniel-mar | 2420 | |
2421 | if (visualViewport) { |
||
2422 | width = visualViewport.width; |
||
931 | daniel-mar | 2423 | height = visualViewport.height; |
2424 | var layoutViewport = isLayoutViewport(); |
||
597 | daniel-mar | 2425 | |
931 | daniel-mar | 2426 | if (layoutViewport || !layoutViewport && strategy === 'fixed') { |
597 | daniel-mar | 2427 | x = visualViewport.offsetLeft; |
2428 | y = visualViewport.offsetTop; |
||
2429 | } |
||
2430 | } |
||
2431 | |||
2432 | return { |
||
2433 | width: width, |
||
2434 | height: height, |
||
2435 | x: x + getWindowScrollBarX(element), |
||
2436 | y: y |
||
2437 | }; |
||
2438 | } |
||
2439 | |||
2440 | // of the `<html>` and `<body>` rect bounds if horizontally scrollable |
||
2441 | |||
2442 | function getDocumentRect(element) { |
||
2443 | var _element$ownerDocumen; |
||
2444 | |||
2445 | var html = getDocumentElement(element); |
||
2446 | var winScroll = getWindowScroll(element); |
||
2447 | var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body; |
||
2448 | var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0); |
||
2449 | var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0); |
||
2450 | var x = -winScroll.scrollLeft + getWindowScrollBarX(element); |
||
2451 | var y = -winScroll.scrollTop; |
||
2452 | |||
2453 | if (getComputedStyle$1(body || html).direction === 'rtl') { |
||
2454 | x += max(html.clientWidth, body ? body.clientWidth : 0) - width; |
||
2455 | } |
||
2456 | |||
2457 | return { |
||
2458 | width: width, |
||
2459 | height: height, |
||
2460 | x: x, |
||
2461 | y: y |
||
2462 | }; |
||
2463 | } |
||
2464 | |||
2465 | function isScrollParent(element) { |
||
2466 | // Firefox wants us to check `-x` and `-y` variations as well |
||
2467 | var _getComputedStyle = getComputedStyle$1(element), |
||
2468 | overflow = _getComputedStyle.overflow, |
||
2469 | overflowX = _getComputedStyle.overflowX, |
||
2470 | overflowY = _getComputedStyle.overflowY; |
||
2471 | |||
2472 | return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX); |
||
2473 | } |
||
2474 | |||
2475 | function getScrollParent(node) { |
||
2476 | if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) { |
||
2477 | // $FlowFixMe[incompatible-return]: assume body is always available |
||
2478 | return node.ownerDocument.body; |
||
2479 | } |
||
2480 | |||
2481 | if (isHTMLElement(node) && isScrollParent(node)) { |
||
2482 | return node; |
||
2483 | } |
||
2484 | |||
2485 | return getScrollParent(getParentNode(node)); |
||
2486 | } |
||
2487 | |||
2488 | /* |
||
2489 | given a DOM element, return the list of all scroll parents, up the list of ancesors |
||
2490 | until we get to the top window object. This list is what we attach scroll listeners |
||
2491 | to, because if any of these parent elements scroll, we'll need to re-calculate the |
||
2492 | reference element's position. |
||
2493 | */ |
||
2494 | |||
2495 | function listScrollParents(element, list) { |
||
2496 | var _element$ownerDocumen; |
||
2497 | |||
2498 | if (list === void 0) { |
||
2499 | list = []; |
||
2500 | } |
||
2501 | |||
2502 | var scrollParent = getScrollParent(element); |
||
2503 | var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body); |
||
2504 | var win = getWindow(scrollParent); |
||
2505 | var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent; |
||
2506 | var updatedList = list.concat(target); |
||
2507 | return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here |
||
2508 | updatedList.concat(listScrollParents(getParentNode(target))); |
||
2509 | } |
||
2510 | |||
2511 | function rectToClientRect(rect) { |
||
2512 | return Object.assign({}, rect, { |
||
2513 | left: rect.x, |
||
2514 | top: rect.y, |
||
2515 | right: rect.x + rect.width, |
||
2516 | bottom: rect.y + rect.height |
||
2517 | }); |
||
2518 | } |
||
2519 | |||
931 | daniel-mar | 2520 | function getInnerBoundingClientRect(element, strategy) { |
2521 | var rect = getBoundingClientRect(element, false, strategy === 'fixed'); |
||
597 | daniel-mar | 2522 | rect.top = rect.top + element.clientTop; |
2523 | rect.left = rect.left + element.clientLeft; |
||
2524 | rect.bottom = rect.top + element.clientHeight; |
||
2525 | rect.right = rect.left + element.clientWidth; |
||
2526 | rect.width = element.clientWidth; |
||
2527 | rect.height = element.clientHeight; |
||
2528 | rect.x = rect.left; |
||
2529 | rect.y = rect.top; |
||
2530 | return rect; |
||
2531 | } |
||
2532 | |||
931 | daniel-mar | 2533 | function getClientRectFromMixedType(element, clippingParent, strategy) { |
2534 | return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element))); |
||
597 | daniel-mar | 2535 | } // A "clipping parent" is an overflowable container with the characteristic of |
2536 | // clipping (or hiding) overflowing elements with a position different from |
||
2537 | // `initial` |
||
2538 | |||
2539 | |||
2540 | function getClippingParents(element) { |
||
2541 | var clippingParents = listScrollParents(getParentNode(element)); |
||
2542 | var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle$1(element).position) >= 0; |
||
2543 | var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element; |
||
2544 | |||
2545 | if (!isElement(clipperElement)) { |
||
2546 | return []; |
||
2547 | } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414 |
||
2548 | |||
2549 | |||
2550 | return clippingParents.filter(function (clippingParent) { |
||
2551 | return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body'; |
||
2552 | }); |
||
2553 | } // Gets the maximum area that the element is visible in due to any number of |
||
2554 | // clipping parents |
||
2555 | |||
2556 | |||
931 | daniel-mar | 2557 | function getClippingRect(element, boundary, rootBoundary, strategy) { |
597 | daniel-mar | 2558 | var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary); |
2559 | var clippingParents = [].concat(mainClippingParents, [rootBoundary]); |
||
2560 | var firstClippingParent = clippingParents[0]; |
||
2561 | var clippingRect = clippingParents.reduce(function (accRect, clippingParent) { |
||
931 | daniel-mar | 2562 | var rect = getClientRectFromMixedType(element, clippingParent, strategy); |
597 | daniel-mar | 2563 | accRect.top = max(rect.top, accRect.top); |
2564 | accRect.right = min(rect.right, accRect.right); |
||
2565 | accRect.bottom = min(rect.bottom, accRect.bottom); |
||
2566 | accRect.left = max(rect.left, accRect.left); |
||
2567 | return accRect; |
||
931 | daniel-mar | 2568 | }, getClientRectFromMixedType(element, firstClippingParent, strategy)); |
597 | daniel-mar | 2569 | clippingRect.width = clippingRect.right - clippingRect.left; |
2570 | clippingRect.height = clippingRect.bottom - clippingRect.top; |
||
2571 | clippingRect.x = clippingRect.left; |
||
2572 | clippingRect.y = clippingRect.top; |
||
2573 | return clippingRect; |
||
2574 | } |
||
2575 | |||
2576 | function computeOffsets(_ref) { |
||
2577 | var reference = _ref.reference, |
||
2578 | element = _ref.element, |
||
2579 | placement = _ref.placement; |
||
2580 | var basePlacement = placement ? getBasePlacement(placement) : null; |
||
2581 | var variation = placement ? getVariation(placement) : null; |
||
2582 | var commonX = reference.x + reference.width / 2 - element.width / 2; |
||
2583 | var commonY = reference.y + reference.height / 2 - element.height / 2; |
||
2584 | var offsets; |
||
2585 | |||
2586 | switch (basePlacement) { |
||
2587 | case top: |
||
2588 | offsets = { |
||
2589 | x: commonX, |
||
2590 | y: reference.y - element.height |
||
2591 | }; |
||
2592 | break; |
||
2593 | |||
2594 | case bottom: |
||
2595 | offsets = { |
||
2596 | x: commonX, |
||
2597 | y: reference.y + reference.height |
||
2598 | }; |
||
2599 | break; |
||
2600 | |||
2601 | case right: |
||
2602 | offsets = { |
||
2603 | x: reference.x + reference.width, |
||
2604 | y: commonY |
||
2605 | }; |
||
2606 | break; |
||
2607 | |||
2608 | case left: |
||
2609 | offsets = { |
||
2610 | x: reference.x - element.width, |
||
2611 | y: commonY |
||
2612 | }; |
||
2613 | break; |
||
2614 | |||
2615 | default: |
||
2616 | offsets = { |
||
2617 | x: reference.x, |
||
2618 | y: reference.y |
||
2619 | }; |
||
2620 | } |
||
2621 | |||
2622 | var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null; |
||
2623 | |||
2624 | if (mainAxis != null) { |
||
2625 | var len = mainAxis === 'y' ? 'height' : 'width'; |
||
2626 | |||
2627 | switch (variation) { |
||
2628 | case start: |
||
2629 | offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2); |
||
2630 | break; |
||
2631 | |||
2632 | case end: |
||
2633 | offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2); |
||
2634 | break; |
||
2635 | } |
||
2636 | } |
||
2637 | |||
2638 | return offsets; |
||
2639 | } |
||
2640 | |||
2641 | function detectOverflow(state, options) { |
||
2642 | if (options === void 0) { |
||
2643 | options = {}; |
||
2644 | } |
||
2645 | |||
2646 | var _options = options, |
||
2647 | _options$placement = _options.placement, |
||
2648 | placement = _options$placement === void 0 ? state.placement : _options$placement, |
||
931 | daniel-mar | 2649 | _options$strategy = _options.strategy, |
2650 | strategy = _options$strategy === void 0 ? state.strategy : _options$strategy, |
||
597 | daniel-mar | 2651 | _options$boundary = _options.boundary, |
2652 | boundary = _options$boundary === void 0 ? clippingParents : _options$boundary, |
||
2653 | _options$rootBoundary = _options.rootBoundary, |
||
2654 | rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary, |
||
2655 | _options$elementConte = _options.elementContext, |
||
2656 | elementContext = _options$elementConte === void 0 ? popper : _options$elementConte, |
||
2657 | _options$altBoundary = _options.altBoundary, |
||
2658 | altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary, |
||
2659 | _options$padding = _options.padding, |
||
2660 | padding = _options$padding === void 0 ? 0 : _options$padding; |
||
2661 | var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); |
||
2662 | var altContext = elementContext === popper ? reference : popper; |
||
2663 | var popperRect = state.rects.popper; |
||
2664 | var element = state.elements[altBoundary ? altContext : elementContext]; |
||
931 | daniel-mar | 2665 | var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy); |
637 | daniel-mar | 2666 | var referenceClientRect = getBoundingClientRect(state.elements.reference); |
597 | daniel-mar | 2667 | var popperOffsets = computeOffsets({ |
2668 | reference: referenceClientRect, |
||
2669 | element: popperRect, |
||
2670 | strategy: 'absolute', |
||
2671 | placement: placement |
||
2672 | }); |
||
2673 | var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets)); |
||
2674 | var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect |
||
2675 | // 0 or negative = within the clipping rect |
||
2676 | |||
2677 | var overflowOffsets = { |
||
2678 | top: clippingClientRect.top - elementClientRect.top + paddingObject.top, |
||
2679 | bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom, |
||
2680 | left: clippingClientRect.left - elementClientRect.left + paddingObject.left, |
||
2681 | right: elementClientRect.right - clippingClientRect.right + paddingObject.right |
||
2682 | }; |
||
2683 | var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element |
||
2684 | |||
2685 | if (elementContext === popper && offsetData) { |
||
2686 | var offset = offsetData[placement]; |
||
2687 | Object.keys(overflowOffsets).forEach(function (key) { |
||
2688 | var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1; |
||
2689 | var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x'; |
||
2690 | overflowOffsets[key] += offset[axis] * multiply; |
||
2691 | }); |
||
2692 | } |
||
2693 | |||
2694 | return overflowOffsets; |
||
2695 | } |
||
2696 | |||
2697 | function computeAutoPlacement(state, options) { |
||
2698 | if (options === void 0) { |
||
2699 | options = {}; |
||
2700 | } |
||
2701 | |||
2702 | var _options = options, |
||
2703 | placement = _options.placement, |
||
2704 | boundary = _options.boundary, |
||
2705 | rootBoundary = _options.rootBoundary, |
||
2706 | padding = _options.padding, |
||
2707 | flipVariations = _options.flipVariations, |
||
2708 | _options$allowedAutoP = _options.allowedAutoPlacements, |
||
2709 | allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP; |
||
2710 | var variation = getVariation(placement); |
||
2711 | var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) { |
||
2712 | return getVariation(placement) === variation; |
||
2713 | }) : basePlacements; |
||
2714 | var allowedPlacements = placements$1.filter(function (placement) { |
||
2715 | return allowedAutoPlacements.indexOf(placement) >= 0; |
||
2716 | }); |
||
2717 | |||
2718 | if (allowedPlacements.length === 0) { |
||
2719 | allowedPlacements = placements$1; |
||
2720 | } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions... |
||
2721 | |||
2722 | |||
2723 | var overflows = allowedPlacements.reduce(function (acc, placement) { |
||
2724 | acc[placement] = detectOverflow(state, { |
||
2725 | placement: placement, |
||
2726 | boundary: boundary, |
||
2727 | rootBoundary: rootBoundary, |
||
2728 | padding: padding |
||
2729 | })[getBasePlacement(placement)]; |
||
2730 | return acc; |
||
2731 | }, {}); |
||
2732 | return Object.keys(overflows).sort(function (a, b) { |
||
2733 | return overflows[a] - overflows[b]; |
||
2734 | }); |
||
2735 | } |
||
2736 | |||
2737 | function getExpandedFallbackPlacements(placement) { |
||
2738 | if (getBasePlacement(placement) === auto) { |
||
2739 | return []; |
||
2740 | } |
||
2741 | |||
2742 | var oppositePlacement = getOppositePlacement(placement); |
||
2743 | return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)]; |
||
2744 | } |
||
2745 | |||
2746 | function flip(_ref) { |
||
2747 | var state = _ref.state, |
||
2748 | options = _ref.options, |
||
2749 | name = _ref.name; |
||
2750 | |||
2751 | if (state.modifiersData[name]._skip) { |
||
2752 | return; |
||
2753 | } |
||
2754 | |||
2755 | var _options$mainAxis = options.mainAxis, |
||
2756 | checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, |
||
2757 | _options$altAxis = options.altAxis, |
||
2758 | checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis, |
||
2759 | specifiedFallbackPlacements = options.fallbackPlacements, |
||
2760 | padding = options.padding, |
||
2761 | boundary = options.boundary, |
||
2762 | rootBoundary = options.rootBoundary, |
||
2763 | altBoundary = options.altBoundary, |
||
2764 | _options$flipVariatio = options.flipVariations, |
||
2765 | flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio, |
||
2766 | allowedAutoPlacements = options.allowedAutoPlacements; |
||
2767 | var preferredPlacement = state.options.placement; |
||
2768 | var basePlacement = getBasePlacement(preferredPlacement); |
||
2769 | var isBasePlacement = basePlacement === preferredPlacement; |
||
2770 | var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement)); |
||
2771 | var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) { |
||
2772 | return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, { |
||
2773 | placement: placement, |
||
2774 | boundary: boundary, |
||
2775 | rootBoundary: rootBoundary, |
||
2776 | padding: padding, |
||
2777 | flipVariations: flipVariations, |
||
2778 | allowedAutoPlacements: allowedAutoPlacements |
||
2779 | }) : placement); |
||
2780 | }, []); |
||
2781 | var referenceRect = state.rects.reference; |
||
2782 | var popperRect = state.rects.popper; |
||
2783 | var checksMap = new Map(); |
||
2784 | var makeFallbackChecks = true; |
||
2785 | var firstFittingPlacement = placements[0]; |
||
2786 | |||
2787 | for (var i = 0; i < placements.length; i++) { |
||
2788 | var placement = placements[i]; |
||
2789 | |||
2790 | var _basePlacement = getBasePlacement(placement); |
||
2791 | |||
2792 | var isStartVariation = getVariation(placement) === start; |
||
2793 | var isVertical = [top, bottom].indexOf(_basePlacement) >= 0; |
||
2794 | var len = isVertical ? 'width' : 'height'; |
||
2795 | var overflow = detectOverflow(state, { |
||
2796 | placement: placement, |
||
2797 | boundary: boundary, |
||
2798 | rootBoundary: rootBoundary, |
||
2799 | altBoundary: altBoundary, |
||
2800 | padding: padding |
||
2801 | }); |
||
2802 | var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top; |
||
2803 | |||
2804 | if (referenceRect[len] > popperRect[len]) { |
||
2805 | mainVariationSide = getOppositePlacement(mainVariationSide); |
||
2806 | } |
||
2807 | |||
2808 | var altVariationSide = getOppositePlacement(mainVariationSide); |
||
2809 | var checks = []; |
||
2810 | |||
2811 | if (checkMainAxis) { |
||
2812 | checks.push(overflow[_basePlacement] <= 0); |
||
2813 | } |
||
2814 | |||
2815 | if (checkAltAxis) { |
||
2816 | checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0); |
||
2817 | } |
||
2818 | |||
2819 | if (checks.every(function (check) { |
||
2820 | return check; |
||
2821 | })) { |
||
2822 | firstFittingPlacement = placement; |
||
2823 | makeFallbackChecks = false; |
||
2824 | break; |
||
2825 | } |
||
2826 | |||
2827 | checksMap.set(placement, checks); |
||
2828 | } |
||
2829 | |||
2830 | if (makeFallbackChecks) { |
||
2831 | // `2` may be desired in some cases – research later |
||
2832 | var numberOfChecks = flipVariations ? 3 : 1; |
||
2833 | |||
2834 | var _loop = function _loop(_i) { |
||
2835 | var fittingPlacement = placements.find(function (placement) { |
||
2836 | var checks = checksMap.get(placement); |
||
2837 | |||
2838 | if (checks) { |
||
2839 | return checks.slice(0, _i).every(function (check) { |
||
2840 | return check; |
||
2841 | }); |
||
2842 | } |
||
2843 | }); |
||
2844 | |||
2845 | if (fittingPlacement) { |
||
2846 | firstFittingPlacement = fittingPlacement; |
||
2847 | return "break"; |
||
2848 | } |
||
2849 | }; |
||
2850 | |||
2851 | for (var _i = numberOfChecks; _i > 0; _i--) { |
||
2852 | var _ret = _loop(_i); |
||
2853 | |||
2854 | if (_ret === "break") break; |
||
2855 | } |
||
2856 | } |
||
2857 | |||
2858 | if (state.placement !== firstFittingPlacement) { |
||
2859 | state.modifiersData[name]._skip = true; |
||
2860 | state.placement = firstFittingPlacement; |
||
2861 | state.reset = true; |
||
2862 | } |
||
2863 | } // eslint-disable-next-line import/no-unused-modules |
||
2864 | |||
2865 | |||
679 | daniel-mar | 2866 | const flip$1 = { |
597 | daniel-mar | 2867 | name: 'flip', |
2868 | enabled: true, |
||
2869 | phase: 'main', |
||
2870 | fn: flip, |
||
2871 | requiresIfExists: ['offset'], |
||
2872 | data: { |
||
2873 | _skip: false |
||
2874 | } |
||
2875 | }; |
||
2876 | |||
2877 | function getSideOffsets(overflow, rect, preventedOffsets) { |
||
2878 | if (preventedOffsets === void 0) { |
||
2879 | preventedOffsets = { |
||
2880 | x: 0, |
||
2881 | y: 0 |
||
2882 | }; |
||
2883 | } |
||
2884 | |||
2885 | return { |
||
2886 | top: overflow.top - rect.height - preventedOffsets.y, |
||
2887 | right: overflow.right - rect.width + preventedOffsets.x, |
||
2888 | bottom: overflow.bottom - rect.height + preventedOffsets.y, |
||
2889 | left: overflow.left - rect.width - preventedOffsets.x |
||
2890 | }; |
||
2891 | } |
||
2892 | |||
2893 | function isAnySideFullyClipped(overflow) { |
||
2894 | return [top, right, bottom, left].some(function (side) { |
||
2895 | return overflow[side] >= 0; |
||
2896 | }); |
||
2897 | } |
||
2898 | |||
637 | daniel-mar | 2899 | function hide(_ref) { |
597 | daniel-mar | 2900 | var state = _ref.state, |
2901 | name = _ref.name; |
||
2902 | var referenceRect = state.rects.reference; |
||
2903 | var popperRect = state.rects.popper; |
||
2904 | var preventedOffsets = state.modifiersData.preventOverflow; |
||
2905 | var referenceOverflow = detectOverflow(state, { |
||
2906 | elementContext: 'reference' |
||
2907 | }); |
||
2908 | var popperAltOverflow = detectOverflow(state, { |
||
2909 | altBoundary: true |
||
2910 | }); |
||
2911 | var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect); |
||
2912 | var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets); |
||
2913 | var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets); |
||
2914 | var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets); |
||
2915 | state.modifiersData[name] = { |
||
2916 | referenceClippingOffsets: referenceClippingOffsets, |
||
2917 | popperEscapeOffsets: popperEscapeOffsets, |
||
2918 | isReferenceHidden: isReferenceHidden, |
||
2919 | hasPopperEscaped: hasPopperEscaped |
||
2920 | }; |
||
2921 | state.attributes.popper = Object.assign({}, state.attributes.popper, { |
||
2922 | 'data-popper-reference-hidden': isReferenceHidden, |
||
2923 | 'data-popper-escaped': hasPopperEscaped |
||
2924 | }); |
||
2925 | } // eslint-disable-next-line import/no-unused-modules |
||
2926 | |||
2927 | |||
679 | daniel-mar | 2928 | const hide$1 = { |
597 | daniel-mar | 2929 | name: 'hide', |
2930 | enabled: true, |
||
2931 | phase: 'main', |
||
2932 | requiresIfExists: ['preventOverflow'], |
||
637 | daniel-mar | 2933 | fn: hide |
597 | daniel-mar | 2934 | }; |
2935 | |||
2936 | function distanceAndSkiddingToXY(placement, rects, offset) { |
||
2937 | var basePlacement = getBasePlacement(placement); |
||
2938 | var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1; |
||
2939 | |||
2940 | var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, { |
||
2941 | placement: placement |
||
2942 | })) : offset, |
||
2943 | skidding = _ref[0], |
||
2944 | distance = _ref[1]; |
||
2945 | |||
2946 | skidding = skidding || 0; |
||
2947 | distance = (distance || 0) * invertDistance; |
||
2948 | return [left, right].indexOf(basePlacement) >= 0 ? { |
||
2949 | x: distance, |
||
2950 | y: skidding |
||
2951 | } : { |
||
2952 | x: skidding, |
||
2953 | y: distance |
||
2954 | }; |
||
2955 | } |
||
2956 | |||
2957 | function offset(_ref2) { |
||
2958 | var state = _ref2.state, |
||
2959 | options = _ref2.options, |
||
2960 | name = _ref2.name; |
||
2961 | var _options$offset = options.offset, |
||
2962 | offset = _options$offset === void 0 ? [0, 0] : _options$offset; |
||
2963 | var data = placements.reduce(function (acc, placement) { |
||
2964 | acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset); |
||
2965 | return acc; |
||
2966 | }, {}); |
||
2967 | var _data$state$placement = data[state.placement], |
||
2968 | x = _data$state$placement.x, |
||
2969 | y = _data$state$placement.y; |
||
2970 | |||
2971 | if (state.modifiersData.popperOffsets != null) { |
||
2972 | state.modifiersData.popperOffsets.x += x; |
||
2973 | state.modifiersData.popperOffsets.y += y; |
||
2974 | } |
||
2975 | |||
2976 | state.modifiersData[name] = data; |
||
2977 | } // eslint-disable-next-line import/no-unused-modules |
||
2978 | |||
2979 | |||
679 | daniel-mar | 2980 | const offset$1 = { |
597 | daniel-mar | 2981 | name: 'offset', |
2982 | enabled: true, |
||
2983 | phase: 'main', |
||
2984 | requires: ['popperOffsets'], |
||
2985 | fn: offset |
||
2986 | }; |
||
2987 | |||
2988 | function popperOffsets(_ref) { |
||
2989 | var state = _ref.state, |
||
2990 | name = _ref.name; |
||
2991 | // Offsets are the actual position the popper needs to have to be |
||
2992 | // properly positioned near its reference element |
||
2993 | // This is the most basic placement, and will be adjusted by |
||
2994 | // the modifiers in the next step |
||
2995 | state.modifiersData[name] = computeOffsets({ |
||
2996 | reference: state.rects.reference, |
||
2997 | element: state.rects.popper, |
||
2998 | strategy: 'absolute', |
||
2999 | placement: state.placement |
||
3000 | }); |
||
3001 | } // eslint-disable-next-line import/no-unused-modules |
||
3002 | |||
3003 | |||
679 | daniel-mar | 3004 | const popperOffsets$1 = { |
597 | daniel-mar | 3005 | name: 'popperOffsets', |
3006 | enabled: true, |
||
3007 | phase: 'read', |
||
3008 | fn: popperOffsets, |
||
3009 | data: {} |
||
3010 | }; |
||
3011 | |||
3012 | function getAltAxis(axis) { |
||
3013 | return axis === 'x' ? 'y' : 'x'; |
||
3014 | } |
||
3015 | |||
3016 | function preventOverflow(_ref) { |
||
3017 | var state = _ref.state, |
||
3018 | options = _ref.options, |
||
3019 | name = _ref.name; |
||
3020 | var _options$mainAxis = options.mainAxis, |
||
3021 | checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, |
||
3022 | _options$altAxis = options.altAxis, |
||
3023 | checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis, |
||
3024 | boundary = options.boundary, |
||
3025 | rootBoundary = options.rootBoundary, |
||
3026 | altBoundary = options.altBoundary, |
||
3027 | padding = options.padding, |
||
3028 | _options$tether = options.tether, |
||
3029 | tether = _options$tether === void 0 ? true : _options$tether, |
||
3030 | _options$tetherOffset = options.tetherOffset, |
||
3031 | tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset; |
||
3032 | var overflow = detectOverflow(state, { |
||
3033 | boundary: boundary, |
||
3034 | rootBoundary: rootBoundary, |
||
3035 | padding: padding, |
||
3036 | altBoundary: altBoundary |
||
3037 | }); |
||
3038 | var basePlacement = getBasePlacement(state.placement); |
||
3039 | var variation = getVariation(state.placement); |
||
3040 | var isBasePlacement = !variation; |
||
3041 | var mainAxis = getMainAxisFromPlacement(basePlacement); |
||
3042 | var altAxis = getAltAxis(mainAxis); |
||
3043 | var popperOffsets = state.modifiersData.popperOffsets; |
||
3044 | var referenceRect = state.rects.reference; |
||
3045 | var popperRect = state.rects.popper; |
||
3046 | var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, { |
||
3047 | placement: state.placement |
||
3048 | })) : tetherOffset; |
||
846 | daniel-mar | 3049 | var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? { |
3050 | mainAxis: tetherOffsetValue, |
||
3051 | altAxis: tetherOffsetValue |
||
3052 | } : Object.assign({ |
||
3053 | mainAxis: 0, |
||
3054 | altAxis: 0 |
||
3055 | }, tetherOffsetValue); |
||
3056 | var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null; |
||
597 | daniel-mar | 3057 | var data = { |
3058 | x: 0, |
||
3059 | y: 0 |
||
3060 | }; |
||
3061 | |||
3062 | if (!popperOffsets) { |
||
3063 | return; |
||
3064 | } |
||
3065 | |||
846 | daniel-mar | 3066 | if (checkMainAxis) { |
3067 | var _offsetModifierState$; |
||
3068 | |||
597 | daniel-mar | 3069 | var mainSide = mainAxis === 'y' ? top : left; |
3070 | var altSide = mainAxis === 'y' ? bottom : right; |
||
3071 | var len = mainAxis === 'y' ? 'height' : 'width'; |
||
3072 | var offset = popperOffsets[mainAxis]; |
||
846 | daniel-mar | 3073 | var min$1 = offset + overflow[mainSide]; |
3074 | var max$1 = offset - overflow[altSide]; |
||
597 | daniel-mar | 3075 | var additive = tether ? -popperRect[len] / 2 : 0; |
3076 | var minLen = variation === start ? referenceRect[len] : popperRect[len]; |
||
3077 | var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go |
||
3078 | // outside the reference bounds |
||
3079 | |||
3080 | var arrowElement = state.elements.arrow; |
||
3081 | var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : { |
||
3082 | width: 0, |
||
3083 | height: 0 |
||
3084 | }; |
||
3085 | var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject(); |
||
3086 | var arrowPaddingMin = arrowPaddingObject[mainSide]; |
||
3087 | var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want |
||
3088 | // to include its full size in the calculation. If the reference is small |
||
3089 | // and near the edge of a boundary, the popper can overflow even if the |
||
3090 | // reference is not overflowing as well (e.g. virtual elements with no |
||
3091 | // width or height) |
||
3092 | |||
3093 | var arrowLen = within(0, referenceRect[len], arrowRect[len]); |
||
846 | daniel-mar | 3094 | var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis; |
3095 | var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis; |
||
597 | daniel-mar | 3096 | var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow); |
3097 | var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0; |
||
846 | daniel-mar | 3098 | var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0; |
3099 | var tetherMin = offset + minOffset - offsetModifierValue - clientOffset; |
||
3100 | var tetherMax = offset + maxOffset - offsetModifierValue; |
||
3101 | var preventedOffset = within(tether ? min(min$1, tetherMin) : min$1, offset, tether ? max(max$1, tetherMax) : max$1); |
||
3102 | popperOffsets[mainAxis] = preventedOffset; |
||
3103 | data[mainAxis] = preventedOffset - offset; |
||
3104 | } |
||
597 | daniel-mar | 3105 | |
846 | daniel-mar | 3106 | if (checkAltAxis) { |
3107 | var _offsetModifierState$2; |
||
597 | daniel-mar | 3108 | |
846 | daniel-mar | 3109 | var _mainSide = mainAxis === 'x' ? top : left; |
597 | daniel-mar | 3110 | |
846 | daniel-mar | 3111 | var _altSide = mainAxis === 'x' ? bottom : right; |
597 | daniel-mar | 3112 | |
846 | daniel-mar | 3113 | var _offset = popperOffsets[altAxis]; |
597 | daniel-mar | 3114 | |
846 | daniel-mar | 3115 | var _len = altAxis === 'y' ? 'height' : 'width'; |
597 | daniel-mar | 3116 | |
846 | daniel-mar | 3117 | var _min = _offset + overflow[_mainSide]; |
597 | daniel-mar | 3118 | |
846 | daniel-mar | 3119 | var _max = _offset - overflow[_altSide]; |
597 | daniel-mar | 3120 | |
846 | daniel-mar | 3121 | var isOriginSide = [top, left].indexOf(basePlacement) !== -1; |
3122 | |||
3123 | var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0; |
||
3124 | |||
3125 | var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis; |
||
3126 | |||
3127 | var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max; |
||
3128 | |||
3129 | var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max); |
||
3130 | |||
3131 | popperOffsets[altAxis] = _preventedOffset; |
||
3132 | data[altAxis] = _preventedOffset - _offset; |
||
597 | daniel-mar | 3133 | } |
3134 | |||
3135 | state.modifiersData[name] = data; |
||
3136 | } // eslint-disable-next-line import/no-unused-modules |
||
3137 | |||
3138 | |||
679 | daniel-mar | 3139 | const preventOverflow$1 = { |
597 | daniel-mar | 3140 | name: 'preventOverflow', |
3141 | enabled: true, |
||
3142 | phase: 'main', |
||
3143 | fn: preventOverflow, |
||
3144 | requiresIfExists: ['offset'] |
||
3145 | }; |
||
3146 | |||
3147 | function getHTMLElementScroll(element) { |
||
3148 | return { |
||
3149 | scrollLeft: element.scrollLeft, |
||
3150 | scrollTop: element.scrollTop |
||
3151 | }; |
||
3152 | } |
||
3153 | |||
3154 | function getNodeScroll(node) { |
||
3155 | if (node === getWindow(node) || !isHTMLElement(node)) { |
||
3156 | return getWindowScroll(node); |
||
3157 | } else { |
||
3158 | return getHTMLElementScroll(node); |
||
3159 | } |
||
3160 | } |
||
3161 | |||
637 | daniel-mar | 3162 | function isElementScaled(element) { |
3163 | var rect = element.getBoundingClientRect(); |
||
846 | daniel-mar | 3164 | var scaleX = round(rect.width) / element.offsetWidth || 1; |
3165 | var scaleY = round(rect.height) / element.offsetHeight || 1; |
||
637 | daniel-mar | 3166 | return scaleX !== 1 || scaleY !== 1; |
3167 | } // Returns the composite rect of an element relative to its offsetParent. |
||
597 | daniel-mar | 3168 | // Composite means it takes into account transforms as well as layout. |
3169 | |||
637 | daniel-mar | 3170 | |
597 | daniel-mar | 3171 | function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) { |
3172 | if (isFixed === void 0) { |
||
3173 | isFixed = false; |
||
3174 | } |
||
3175 | |||
637 | daniel-mar | 3176 | var isOffsetParentAnElement = isHTMLElement(offsetParent); |
846 | daniel-mar | 3177 | var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent); |
597 | daniel-mar | 3178 | var documentElement = getDocumentElement(offsetParent); |
931 | daniel-mar | 3179 | var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed); |
597 | daniel-mar | 3180 | var scroll = { |
3181 | scrollLeft: 0, |
||
3182 | scrollTop: 0 |
||
3183 | }; |
||
3184 | var offsets = { |
||
3185 | x: 0, |
||
3186 | y: 0 |
||
3187 | }; |
||
3188 | |||
3189 | if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { |
||
3190 | if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078 |
||
3191 | isScrollParent(documentElement)) { |
||
3192 | scroll = getNodeScroll(offsetParent); |
||
3193 | } |
||
3194 | |||
3195 | if (isHTMLElement(offsetParent)) { |
||
846 | daniel-mar | 3196 | offsets = getBoundingClientRect(offsetParent, true); |
597 | daniel-mar | 3197 | offsets.x += offsetParent.clientLeft; |
3198 | offsets.y += offsetParent.clientTop; |
||
3199 | } else if (documentElement) { |
||
3200 | offsets.x = getWindowScrollBarX(documentElement); |
||
3201 | } |
||
3202 | } |
||
3203 | |||
3204 | return { |
||
3205 | x: rect.left + scroll.scrollLeft - offsets.x, |
||
3206 | y: rect.top + scroll.scrollTop - offsets.y, |
||
3207 | width: rect.width, |
||
3208 | height: rect.height |
||
3209 | }; |
||
3210 | } |
||
3211 | |||
3212 | function order(modifiers) { |
||
3213 | var map = new Map(); |
||
3214 | var visited = new Set(); |
||
3215 | var result = []; |
||
3216 | modifiers.forEach(function (modifier) { |
||
3217 | map.set(modifier.name, modifier); |
||
3218 | }); // On visiting object, check for its dependencies and visit them recursively |
||
3219 | |||
3220 | function sort(modifier) { |
||
3221 | visited.add(modifier.name); |
||
3222 | var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []); |
||
3223 | requires.forEach(function (dep) { |
||
3224 | if (!visited.has(dep)) { |
||
3225 | var depModifier = map.get(dep); |
||
3226 | |||
3227 | if (depModifier) { |
||
3228 | sort(depModifier); |
||
3229 | } |
||
3230 | } |
||
3231 | }); |
||
3232 | result.push(modifier); |
||
3233 | } |
||
3234 | |||
3235 | modifiers.forEach(function (modifier) { |
||
3236 | if (!visited.has(modifier.name)) { |
||
3237 | // check for visited object |
||
3238 | sort(modifier); |
||
3239 | } |
||
3240 | }); |
||
3241 | return result; |
||
3242 | } |
||
3243 | |||
3244 | function orderModifiers(modifiers) { |
||
3245 | // order based on dependencies |
||
3246 | var orderedModifiers = order(modifiers); // order based on phase |
||
3247 | |||
3248 | return modifierPhases.reduce(function (acc, phase) { |
||
3249 | return acc.concat(orderedModifiers.filter(function (modifier) { |
||
3250 | return modifier.phase === phase; |
||
3251 | })); |
||
3252 | }, []); |
||
3253 | } |
||
3254 | |||
3255 | function debounce(fn) { |
||
3256 | var pending; |
||
3257 | return function () { |
||
3258 | if (!pending) { |
||
3259 | pending = new Promise(function (resolve) { |
||
3260 | Promise.resolve().then(function () { |
||
3261 | pending = undefined; |
||
3262 | resolve(fn()); |
||
3263 | }); |
||
3264 | }); |
||
3265 | } |
||
3266 | |||
3267 | return pending; |
||
3268 | }; |
||
3269 | } |
||
3270 | |||
3271 | function mergeByName(modifiers) { |
||
3272 | var merged = modifiers.reduce(function (merged, current) { |
||
3273 | var existing = merged[current.name]; |
||
3274 | merged[current.name] = existing ? Object.assign({}, existing, current, { |
||
3275 | options: Object.assign({}, existing.options, current.options), |
||
3276 | data: Object.assign({}, existing.data, current.data) |
||
3277 | }) : current; |
||
3278 | return merged; |
||
3279 | }, {}); // IE11 does not support Object.values |
||
3280 | |||
3281 | return Object.keys(merged).map(function (key) { |
||
3282 | return merged[key]; |
||
3283 | }); |
||
3284 | } |
||
3285 | |||
3286 | var DEFAULT_OPTIONS = { |
||
3287 | placement: 'bottom', |
||
3288 | modifiers: [], |
||
3289 | strategy: 'absolute' |
||
3290 | }; |
||
3291 | |||
3292 | function areValidElements() { |
||
3293 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { |
||
3294 | args[_key] = arguments[_key]; |
||
3295 | } |
||
3296 | |||
3297 | return !args.some(function (element) { |
||
3298 | return !(element && typeof element.getBoundingClientRect === 'function'); |
||
3299 | }); |
||
3300 | } |
||
3301 | |||
3302 | function popperGenerator(generatorOptions) { |
||
3303 | if (generatorOptions === void 0) { |
||
3304 | generatorOptions = {}; |
||
3305 | } |
||
3306 | |||
3307 | var _generatorOptions = generatorOptions, |
||
3308 | _generatorOptions$def = _generatorOptions.defaultModifiers, |
||
3309 | defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, |
||
3310 | _generatorOptions$def2 = _generatorOptions.defaultOptions, |
||
3311 | defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2; |
||
3312 | return function createPopper(reference, popper, options) { |
||
3313 | if (options === void 0) { |
||
3314 | options = defaultOptions; |
||
3315 | } |
||
3316 | |||
3317 | var state = { |
||
3318 | placement: 'bottom', |
||
3319 | orderedModifiers: [], |
||
3320 | options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions), |
||
3321 | modifiersData: {}, |
||
3322 | elements: { |
||
3323 | reference: reference, |
||
3324 | popper: popper |
||
3325 | }, |
||
3326 | attributes: {}, |
||
3327 | styles: {} |
||
3328 | }; |
||
3329 | var effectCleanupFns = []; |
||
3330 | var isDestroyed = false; |
||
3331 | var instance = { |
||
3332 | state: state, |
||
637 | daniel-mar | 3333 | setOptions: function setOptions(setOptionsAction) { |
3334 | var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction; |
||
597 | daniel-mar | 3335 | cleanupModifierEffects(); |
3336 | state.options = Object.assign({}, defaultOptions, state.options, options); |
||
3337 | state.scrollParents = { |
||
3338 | reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [], |
||
3339 | popper: listScrollParents(popper) |
||
3340 | }; // Orders the modifiers based on their dependencies and `phase` |
||
3341 | // properties |
||
3342 | |||
3343 | var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers |
||
3344 | |||
3345 | state.orderedModifiers = orderedModifiers.filter(function (m) { |
||
3346 | return m.enabled; |
||
1308 | daniel-mar | 3347 | }); |
597 | daniel-mar | 3348 | runModifierEffects(); |
3349 | return instance.update(); |
||
3350 | }, |
||
3351 | // Sync update – it will always be executed, even if not necessary. This |
||
3352 | // is useful for low frequency updates where sync behavior simplifies the |
||
3353 | // logic. |
||
3354 | // For high frequency updates (e.g. `resize` and `scroll` events), always |
||
3355 | // prefer the async Popper#update method |
||
3356 | forceUpdate: function forceUpdate() { |
||
3357 | if (isDestroyed) { |
||
3358 | return; |
||
3359 | } |
||
3360 | |||
3361 | var _state$elements = state.elements, |
||
3362 | reference = _state$elements.reference, |
||
3363 | popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements |
||
3364 | // anymore |
||
3365 | |||
3366 | if (!areValidElements(reference, popper)) { |
||
3367 | return; |
||
3368 | } // Store the reference and popper rects to be read by modifiers |
||
3369 | |||
3370 | |||
3371 | state.rects = { |
||
3372 | reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'), |
||
3373 | popper: getLayoutRect(popper) |
||
3374 | }; // Modifiers have the ability to reset the current update cycle. The |
||
3375 | // most common use case for this is the `flip` modifier changing the |
||
3376 | // placement, which then needs to re-run all the modifiers, because the |
||
3377 | // logic was previously ran for the previous placement and is therefore |
||
3378 | // stale/incorrect |
||
3379 | |||
3380 | state.reset = false; |
||
3381 | state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier |
||
3382 | // is filled with the initial data specified by the modifier. This means |
||
3383 | // it doesn't persist and is fresh on each update. |
||
3384 | // To ensure persistent data, use `${name}#persistent` |
||
3385 | |||
3386 | state.orderedModifiers.forEach(function (modifier) { |
||
3387 | return state.modifiersData[modifier.name] = Object.assign({}, modifier.data); |
||
3388 | }); |
||
3389 | |||
3390 | for (var index = 0; index < state.orderedModifiers.length; index++) { |
||
3391 | if (state.reset === true) { |
||
3392 | state.reset = false; |
||
3393 | index = -1; |
||
3394 | continue; |
||
3395 | } |
||
3396 | |||
3397 | var _state$orderedModifie = state.orderedModifiers[index], |
||
3398 | fn = _state$orderedModifie.fn, |
||
3399 | _state$orderedModifie2 = _state$orderedModifie.options, |
||
3400 | _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, |
||
3401 | name = _state$orderedModifie.name; |
||
3402 | |||
3403 | if (typeof fn === 'function') { |
||
3404 | state = fn({ |
||
3405 | state: state, |
||
3406 | options: _options, |
||
3407 | name: name, |
||
3408 | instance: instance |
||
3409 | }) || state; |
||
3410 | } |
||
3411 | } |
||
3412 | }, |
||
3413 | // Async and optimistically optimized update – it will not be executed if |
||
3414 | // not necessary (debounced to run at most once-per-tick) |
||
3415 | update: debounce(function () { |
||
3416 | return new Promise(function (resolve) { |
||
3417 | instance.forceUpdate(); |
||
3418 | resolve(state); |
||
3419 | }); |
||
3420 | }), |
||
3421 | destroy: function destroy() { |
||
3422 | cleanupModifierEffects(); |
||
3423 | isDestroyed = true; |
||
3424 | } |
||
3425 | }; |
||
3426 | |||
3427 | if (!areValidElements(reference, popper)) { |
||
3428 | return instance; |
||
3429 | } |
||
3430 | |||
3431 | instance.setOptions(options).then(function (state) { |
||
3432 | if (!isDestroyed && options.onFirstUpdate) { |
||
3433 | options.onFirstUpdate(state); |
||
3434 | } |
||
3435 | }); // Modifiers have the ability to execute arbitrary code before the first |
||
3436 | // update cycle runs. They will be executed in the same order as the update |
||
3437 | // cycle. This is useful when a modifier adds some persistent data that |
||
3438 | // other modifiers need to use, but the modifier is run after the dependent |
||
3439 | // one. |
||
3440 | |||
3441 | function runModifierEffects() { |
||
1308 | daniel-mar | 3442 | state.orderedModifiers.forEach(function (_ref) { |
3443 | var name = _ref.name, |
||
3444 | _ref$options = _ref.options, |
||
3445 | options = _ref$options === void 0 ? {} : _ref$options, |
||
3446 | effect = _ref.effect; |
||
597 | daniel-mar | 3447 | |
3448 | if (typeof effect === 'function') { |
||
3449 | var cleanupFn = effect({ |
||
3450 | state: state, |
||
3451 | name: name, |
||
3452 | instance: instance, |
||
3453 | options: options |
||
3454 | }); |
||
3455 | |||
3456 | var noopFn = function noopFn() {}; |
||
3457 | |||
3458 | effectCleanupFns.push(cleanupFn || noopFn); |
||
3459 | } |
||
3460 | }); |
||
3461 | } |
||
3462 | |||
3463 | function cleanupModifierEffects() { |
||
3464 | effectCleanupFns.forEach(function (fn) { |
||
3465 | return fn(); |
||
3466 | }); |
||
3467 | effectCleanupFns = []; |
||
3468 | } |
||
3469 | |||
3470 | return instance; |
||
3471 | }; |
||
3472 | } |
||
3473 | var createPopper$2 = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules |
||
3474 | |||
3475 | var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1]; |
||
3476 | var createPopper$1 = /*#__PURE__*/popperGenerator({ |
||
3477 | defaultModifiers: defaultModifiers$1 |
||
3478 | }); // eslint-disable-next-line import/no-unused-modules |
||
3479 | |||
637 | daniel-mar | 3480 | var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1]; |
597 | daniel-mar | 3481 | var createPopper = /*#__PURE__*/popperGenerator({ |
3482 | defaultModifiers: defaultModifiers |
||
3483 | }); // eslint-disable-next-line import/no-unused-modules |
||
3484 | |||
846 | daniel-mar | 3485 | const Popper = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({ |
597 | daniel-mar | 3486 | __proto__: null, |
1134 | daniel-mar | 3487 | afterMain, |
3488 | afterRead, |
||
3489 | afterWrite, |
||
3490 | applyStyles: applyStyles$1, |
||
3491 | arrow: arrow$1, |
||
679 | daniel-mar | 3492 | auto, |
3493 | basePlacements, |
||
1134 | daniel-mar | 3494 | beforeMain, |
679 | daniel-mar | 3495 | beforeRead, |
3496 | beforeWrite, |
||
1134 | daniel-mar | 3497 | bottom, |
3498 | clippingParents, |
||
597 | daniel-mar | 3499 | computeStyles: computeStyles$1, |
1134 | daniel-mar | 3500 | createPopper, |
3501 | createPopperBase: createPopper$2, |
||
3502 | createPopperLite: createPopper$1, |
||
3503 | detectOverflow, |
||
3504 | end, |
||
679 | daniel-mar | 3505 | eventListeners, |
597 | daniel-mar | 3506 | flip: flip$1, |
637 | daniel-mar | 3507 | hide: hide$1, |
1134 | daniel-mar | 3508 | left, |
3509 | main, |
||
3510 | modifierPhases, |
||
597 | daniel-mar | 3511 | offset: offset$1, |
1134 | daniel-mar | 3512 | placements, |
3513 | popper, |
||
3514 | popperGenerator, |
||
597 | daniel-mar | 3515 | popperOffsets: popperOffsets$1, |
1134 | daniel-mar | 3516 | preventOverflow: preventOverflow$1, |
3517 | read, |
||
3518 | reference, |
||
3519 | right, |
||
3520 | start, |
||
3521 | top, |
||
3522 | variationPlacements, |
||
3523 | viewport, |
||
3524 | write |
||
846 | daniel-mar | 3525 | }, Symbol.toStringTag, { value: 'Module' })); |
597 | daniel-mar | 3526 | |
3527 | /** |
||
3528 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 3529 | * Bootstrap dropdown.js |
597 | daniel-mar | 3530 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
3531 | * -------------------------------------------------------------------------- |
||
3532 | */ |
||
1056 | daniel-mar | 3533 | |
1308 | daniel-mar | 3534 | |
597 | daniel-mar | 3535 | /** |
3536 | * Constants |
||
3537 | */ |
||
3538 | |||
846 | daniel-mar | 3539 | const NAME$a = 'dropdown'; |
3540 | const DATA_KEY$6 = 'bs.dropdown'; |
||
3541 | const EVENT_KEY$6 = `.${DATA_KEY$6}`; |
||
3542 | const DATA_API_KEY$3 = '.data-api'; |
||
597 | daniel-mar | 3543 | const ESCAPE_KEY$2 = 'Escape'; |
637 | daniel-mar | 3544 | const TAB_KEY$1 = 'Tab'; |
846 | daniel-mar | 3545 | const ARROW_UP_KEY$1 = 'ArrowUp'; |
3546 | const ARROW_DOWN_KEY$1 = 'ArrowDown'; |
||
597 | daniel-mar | 3547 | const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button |
3548 | |||
846 | daniel-mar | 3549 | const EVENT_HIDE$5 = `hide${EVENT_KEY$6}`; |
3550 | const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`; |
||
3551 | const EVENT_SHOW$5 = `show${EVENT_KEY$6}`; |
||
3552 | const EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`; |
||
3553 | const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`; |
||
3554 | const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`; |
||
3555 | const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`; |
||
637 | daniel-mar | 3556 | const CLASS_NAME_SHOW$6 = 'show'; |
597 | daniel-mar | 3557 | const CLASS_NAME_DROPUP = 'dropup'; |
3558 | const CLASS_NAME_DROPEND = 'dropend'; |
||
3559 | const CLASS_NAME_DROPSTART = 'dropstart'; |
||
846 | daniel-mar | 3560 | const CLASS_NAME_DROPUP_CENTER = 'dropup-center'; |
3561 | const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center'; |
||
3562 | const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)'; |
||
3563 | const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`; |
||
597 | daniel-mar | 3564 | const SELECTOR_MENU = '.dropdown-menu'; |
846 | daniel-mar | 3565 | const SELECTOR_NAVBAR = '.navbar'; |
597 | daniel-mar | 3566 | const SELECTOR_NAVBAR_NAV = '.navbar-nav'; |
3567 | const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'; |
||
3568 | const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'; |
||
3569 | const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'; |
||
3570 | const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'; |
||
3571 | const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'; |
||
3572 | const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'; |
||
3573 | const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'; |
||
846 | daniel-mar | 3574 | const PLACEMENT_TOPCENTER = 'top'; |
3575 | const PLACEMENT_BOTTOMCENTER = 'bottom'; |
||
3576 | const Default$9 = { |
||
922 | daniel-mar | 3577 | autoClose: true, |
597 | daniel-mar | 3578 | boundary: 'clippingParents', |
3579 | display: 'dynamic', |
||
922 | daniel-mar | 3580 | offset: [0, 2], |
597 | daniel-mar | 3581 | popperConfig: null, |
922 | daniel-mar | 3582 | reference: 'toggle' |
597 | daniel-mar | 3583 | }; |
846 | daniel-mar | 3584 | const DefaultType$9 = { |
922 | daniel-mar | 3585 | autoClose: '(boolean|string)', |
597 | daniel-mar | 3586 | boundary: '(string|element)', |
3587 | display: 'string', |
||
922 | daniel-mar | 3588 | offset: '(array|string|function)', |
597 | daniel-mar | 3589 | popperConfig: '(null|object|function)', |
922 | daniel-mar | 3590 | reference: '(string|element|object)' |
597 | daniel-mar | 3591 | }; |
1056 | daniel-mar | 3592 | |
597 | daniel-mar | 3593 | /** |
846 | daniel-mar | 3594 | * Class definition |
597 | daniel-mar | 3595 | */ |
3596 | |||
3597 | class Dropdown extends BaseComponent { |
||
3598 | constructor(element, config) { |
||
846 | daniel-mar | 3599 | super(element, config); |
597 | daniel-mar | 3600 | this._popper = null; |
846 | daniel-mar | 3601 | this._parent = this._element.parentNode; // dropdown wrapper |
1151 | daniel-mar | 3602 | // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/ |
981 | daniel-mar | 3603 | this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent); |
597 | daniel-mar | 3604 | this._inNavbar = this._detectNavbar(); |
1056 | daniel-mar | 3605 | } |
597 | daniel-mar | 3606 | |
1056 | daniel-mar | 3607 | // Getters |
597 | daniel-mar | 3608 | static get Default() { |
846 | daniel-mar | 3609 | return Default$9; |
597 | daniel-mar | 3610 | } |
3611 | static get DefaultType() { |
||
846 | daniel-mar | 3612 | return DefaultType$9; |
597 | daniel-mar | 3613 | } |
3614 | static get NAME() { |
||
846 | daniel-mar | 3615 | return NAME$a; |
1056 | daniel-mar | 3616 | } |
597 | daniel-mar | 3617 | |
1056 | daniel-mar | 3618 | // Public |
597 | daniel-mar | 3619 | toggle() { |
637 | daniel-mar | 3620 | return this._isShown() ? this.hide() : this.show(); |
597 | daniel-mar | 3621 | } |
3622 | show() { |
||
846 | daniel-mar | 3623 | if (isDisabled(this._element) || this._isShown()) { |
597 | daniel-mar | 3624 | return; |
3625 | } |
||
3626 | const relatedTarget = { |
||
3627 | relatedTarget: this._element |
||
3628 | }; |
||
846 | daniel-mar | 3629 | const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, relatedTarget); |
597 | daniel-mar | 3630 | if (showEvent.defaultPrevented) { |
3631 | return; |
||
637 | daniel-mar | 3632 | } |
1056 | daniel-mar | 3633 | this._createPopper(); |
597 | daniel-mar | 3634 | |
1056 | daniel-mar | 3635 | // If this is a touch-enabled device we add extra |
597 | daniel-mar | 3636 | // empty mouseover listeners to the body's immediate children; |
3637 | // only needed because of broken event delegation on iOS |
||
3638 | // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html |
||
846 | daniel-mar | 3639 | if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) { |
3640 | for (const element of [].concat(...document.body.children)) { |
||
3641 | EventHandler.on(element, 'mouseover', noop); |
||
3642 | } |
||
597 | daniel-mar | 3643 | } |
3644 | this._element.focus(); |
||
3645 | this._element.setAttribute('aria-expanded', true); |
||
637 | daniel-mar | 3646 | this._menu.classList.add(CLASS_NAME_SHOW$6); |
3647 | this._element.classList.add(CLASS_NAME_SHOW$6); |
||
846 | daniel-mar | 3648 | EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget); |
597 | daniel-mar | 3649 | } |
3650 | hide() { |
||
846 | daniel-mar | 3651 | if (isDisabled(this._element) || !this._isShown()) { |
597 | daniel-mar | 3652 | return; |
3653 | } |
||
3654 | const relatedTarget = { |
||
3655 | relatedTarget: this._element |
||
3656 | }; |
||
3657 | this._completeHide(relatedTarget); |
||
3658 | } |
||
3659 | dispose() { |
||
3660 | if (this._popper) { |
||
3661 | this._popper.destroy(); |
||
3662 | } |
||
3663 | super.dispose(); |
||
3664 | } |
||
3665 | update() { |
||
3666 | this._inNavbar = this._detectNavbar(); |
||
3667 | if (this._popper) { |
||
3668 | this._popper.update(); |
||
3669 | } |
||
1056 | daniel-mar | 3670 | } |
597 | daniel-mar | 3671 | |
1056 | daniel-mar | 3672 | // Private |
597 | daniel-mar | 3673 | _completeHide(relatedTarget) { |
846 | daniel-mar | 3674 | const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget); |
597 | daniel-mar | 3675 | if (hideEvent.defaultPrevented) { |
3676 | return; |
||
1056 | daniel-mar | 3677 | } |
3678 | |||
3679 | // If this is a touch-enabled device we remove the extra |
||
597 | daniel-mar | 3680 | // empty mouseover listeners we added for iOS support |
3681 | if ('ontouchstart' in document.documentElement) { |
||
846 | daniel-mar | 3682 | for (const element of [].concat(...document.body.children)) { |
3683 | EventHandler.off(element, 'mouseover', noop); |
||
3684 | } |
||
597 | daniel-mar | 3685 | } |
3686 | if (this._popper) { |
||
3687 | this._popper.destroy(); |
||
3688 | } |
||
637 | daniel-mar | 3689 | this._menu.classList.remove(CLASS_NAME_SHOW$6); |
3690 | this._element.classList.remove(CLASS_NAME_SHOW$6); |
||
597 | daniel-mar | 3691 | this._element.setAttribute('aria-expanded', 'false'); |
3692 | Manipulator.removeDataAttribute(this._menu, 'popper'); |
||
846 | daniel-mar | 3693 | EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget); |
597 | daniel-mar | 3694 | } |
3695 | _getConfig(config) { |
||
846 | daniel-mar | 3696 | config = super._getConfig(config); |
597 | daniel-mar | 3697 | if (typeof config.reference === 'object' && !isElement$1(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') { |
3698 | // Popper virtual elements require a getBoundingClientRect method |
||
846 | daniel-mar | 3699 | throw new TypeError(`${NAME$a.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); |
597 | daniel-mar | 3700 | } |
3701 | return config; |
||
3702 | } |
||
846 | daniel-mar | 3703 | _createPopper() { |
637 | daniel-mar | 3704 | if (typeof Popper === 'undefined') { |
3705 | throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)'); |
||
3706 | } |
||
3707 | let referenceElement = this._element; |
||
3708 | if (this._config.reference === 'parent') { |
||
846 | daniel-mar | 3709 | referenceElement = this._parent; |
637 | daniel-mar | 3710 | } else if (isElement$1(this._config.reference)) { |
3711 | referenceElement = getElement(this._config.reference); |
||
3712 | } else if (typeof this._config.reference === 'object') { |
||
3713 | referenceElement = this._config.reference; |
||
3714 | } |
||
3715 | const popperConfig = this._getPopperConfig(); |
||
3716 | this._popper = createPopper(referenceElement, this._menu, popperConfig); |
||
3717 | } |
||
846 | daniel-mar | 3718 | _isShown() { |
3719 | return this._menu.classList.contains(CLASS_NAME_SHOW$6); |
||
637 | daniel-mar | 3720 | } |
597 | daniel-mar | 3721 | _getPlacement() { |
846 | daniel-mar | 3722 | const parentDropdown = this._parent; |
597 | daniel-mar | 3723 | if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) { |
3724 | return PLACEMENT_RIGHT; |
||
3725 | } |
||
3726 | if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) { |
||
3727 | return PLACEMENT_LEFT; |
||
846 | daniel-mar | 3728 | } |
3729 | if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) { |
||
3730 | return PLACEMENT_TOPCENTER; |
||
3731 | } |
||
3732 | if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) { |
||
3733 | return PLACEMENT_BOTTOMCENTER; |
||
1056 | daniel-mar | 3734 | } |
597 | daniel-mar | 3735 | |
1056 | daniel-mar | 3736 | // We need to trim the value because custom properties can also include spaces |
597 | daniel-mar | 3737 | const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'; |
3738 | if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { |
||
3739 | return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP; |
||
3740 | } |
||
3741 | return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM; |
||
3742 | } |
||
3743 | _detectNavbar() { |
||
846 | daniel-mar | 3744 | return this._element.closest(SELECTOR_NAVBAR) !== null; |
597 | daniel-mar | 3745 | } |
3746 | _getOffset() { |
||
3747 | const { |
||
3748 | offset |
||
3749 | } = this._config; |
||
3750 | if (typeof offset === 'string') { |
||
846 | daniel-mar | 3751 | return offset.split(',').map(value => Number.parseInt(value, 10)); |
597 | daniel-mar | 3752 | } |
3753 | if (typeof offset === 'function') { |
||
3754 | return popperData => offset(popperData, this._element); |
||
3755 | } |
||
3756 | return offset; |
||
3757 | } |
||
3758 | _getPopperConfig() { |
||
3759 | const defaultBsPopperConfig = { |
||
3760 | placement: this._getPlacement(), |
||
3761 | modifiers: [{ |
||
3762 | name: 'preventOverflow', |
||
3763 | options: { |
||
3764 | boundary: this._config.boundary |
||
3765 | } |
||
3766 | }, { |
||
3767 | name: 'offset', |
||
3768 | options: { |
||
3769 | offset: this._getOffset() |
||
3770 | } |
||
3771 | }] |
||
1056 | daniel-mar | 3772 | }; |
597 | daniel-mar | 3773 | |
1056 | daniel-mar | 3774 | // Disable Popper if we have a static display or Dropdown is in Navbar |
846 | daniel-mar | 3775 | if (this._inNavbar || this._config.display === 'static') { |
1151 | daniel-mar | 3776 | Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // TODO: v6 remove |
597 | daniel-mar | 3777 | defaultBsPopperConfig.modifiers = [{ |
3778 | name: 'applyStyles', |
||
3779 | enabled: false |
||
3780 | }]; |
||
3781 | } |
||
1056 | daniel-mar | 3782 | return { |
3783 | ...defaultBsPopperConfig, |
||
3784 | ...execute(this._config.popperConfig, [defaultBsPopperConfig]) |
||
597 | daniel-mar | 3785 | }; |
3786 | } |
||
637 | daniel-mar | 3787 | _selectMenuItem({ |
3788 | key, |
||
3789 | target |
||
3790 | }) { |
||
846 | daniel-mar | 3791 | const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element)); |
597 | daniel-mar | 3792 | if (!items.length) { |
3793 | return; |
||
1056 | daniel-mar | 3794 | } |
3795 | |||
3796 | // if target isn't included in items (e.g. when expanding the dropdown) |
||
637 | daniel-mar | 3797 | // allow cycling to get the last item in case key equals ARROW_UP_KEY |
846 | daniel-mar | 3798 | getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus(); |
1056 | daniel-mar | 3799 | } |
597 | daniel-mar | 3800 | |
1056 | daniel-mar | 3801 | // Static |
637 | daniel-mar | 3802 | static jQueryInterface(config) { |
3803 | return this.each(function () { |
||
3804 | const data = Dropdown.getOrCreateInstance(this, config); |
||
3805 | if (typeof config !== 'string') { |
||
3806 | return; |
||
3807 | } |
||
597 | daniel-mar | 3808 | if (typeof data[config] === 'undefined') { |
3809 | throw new TypeError(`No method named "${config}"`); |
||
3810 | } |
||
3811 | data[config](); |
||
3812 | }); |
||
3813 | } |
||
3814 | static clearMenus(event) { |
||
846 | daniel-mar | 3815 | if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) { |
597 | daniel-mar | 3816 | return; |
3817 | } |
||
846 | daniel-mar | 3818 | const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN); |
3819 | for (const toggle of openToggles) { |
||
3820 | const context = Dropdown.getInstance(toggle); |
||
597 | daniel-mar | 3821 | if (!context || context._config.autoClose === false) { |
3822 | continue; |
||
3823 | } |
||
846 | daniel-mar | 3824 | const composedPath = event.composedPath(); |
3825 | const isMenuTarget = composedPath.includes(context._menu); |
||
3826 | if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) { |
||
597 | daniel-mar | 3827 | continue; |
1056 | daniel-mar | 3828 | } |
846 | daniel-mar | 3829 | |
1056 | daniel-mar | 3830 | // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu |
846 | daniel-mar | 3831 | if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName))) { |
3832 | continue; |
||
597 | daniel-mar | 3833 | } |
3834 | const relatedTarget = { |
||
3835 | relatedTarget: context._element |
||
3836 | }; |
||
846 | daniel-mar | 3837 | if (event.type === 'click') { |
3838 | relatedTarget.clickEvent = event; |
||
597 | daniel-mar | 3839 | } |
3840 | context._completeHide(relatedTarget); |
||
3841 | } |
||
3842 | } |
||
846 | daniel-mar | 3843 | static dataApiKeydownHandler(event) { |
3844 | // If not an UP | DOWN | ESCAPE key => not a dropdown command |
||
3845 | // If input/textarea && if key is other than ESCAPE => not a dropdown command |
||
1056 | daniel-mar | 3846 | |
846 | daniel-mar | 3847 | const isInput = /input|textarea/i.test(event.target.tagName); |
3848 | const isEscapeEvent = event.key === ESCAPE_KEY$2; |
||
3849 | const isUpOrDownEvent = [ARROW_UP_KEY$1, ARROW_DOWN_KEY$1].includes(event.key); |
||
3850 | if (!isUpOrDownEvent && !isEscapeEvent) { |
||
597 | daniel-mar | 3851 | return; |
3852 | } |
||
846 | daniel-mar | 3853 | if (isInput && !isEscapeEvent) { |
597 | daniel-mar | 3854 | return; |
3855 | } |
||
1056 | daniel-mar | 3856 | event.preventDefault(); |
597 | daniel-mar | 3857 | |
1151 | daniel-mar | 3858 | // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/ |
981 | daniel-mar | 3859 | const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$3, event.delegateTarget.parentNode); |
637 | daniel-mar | 3860 | const instance = Dropdown.getOrCreateInstance(getToggleButton); |
846 | daniel-mar | 3861 | if (isUpOrDownEvent) { |
3862 | event.stopPropagation(); |
||
3863 | instance.show(); |
||
637 | daniel-mar | 3864 | instance._selectMenuItem(event); |
597 | daniel-mar | 3865 | return; |
3866 | } |
||
846 | daniel-mar | 3867 | if (instance._isShown()) { |
3868 | // else is escape and we check if it is shown |
||
3869 | event.stopPropagation(); |
||
3870 | instance.hide(); |
||
3871 | getToggleButton.focus(); |
||
597 | daniel-mar | 3872 | } |
3873 | } |
||
1056 | daniel-mar | 3874 | } |
597 | daniel-mar | 3875 | |
3876 | /** |
||
846 | daniel-mar | 3877 | * Data API implementation |
597 | daniel-mar | 3878 | */ |
3879 | |||
3880 | EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler); |
||
3881 | EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler); |
||
3882 | EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus); |
||
3883 | EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); |
||
3884 | EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) { |
||
3885 | event.preventDefault(); |
||
637 | daniel-mar | 3886 | Dropdown.getOrCreateInstance(this).toggle(); |
597 | daniel-mar | 3887 | }); |
1056 | daniel-mar | 3888 | |
597 | daniel-mar | 3889 | /** |
3890 | * jQuery |
||
3891 | */ |
||
3892 | |||
3893 | defineJQueryPlugin(Dropdown); |
||
3894 | |||
3895 | /** |
||
3896 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 3897 | * Bootstrap util/backdrop.js |
679 | daniel-mar | 3898 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
597 | daniel-mar | 3899 | * -------------------------------------------------------------------------- |
3900 | */ |
||
1056 | daniel-mar | 3901 | |
1308 | daniel-mar | 3902 | |
846 | daniel-mar | 3903 | /** |
3904 | * Constants |
||
3905 | */ |
||
3906 | |||
3907 | const NAME$9 = 'backdrop'; |
||
3908 | const CLASS_NAME_FADE$4 = 'fade'; |
||
3909 | const CLASS_NAME_SHOW$5 = 'show'; |
||
3910 | const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`; |
||
3911 | const Default$8 = { |
||
637 | daniel-mar | 3912 | className: 'modal-backdrop', |
922 | daniel-mar | 3913 | clickCallback: null, |
3914 | isAnimated: false, |
||
597 | daniel-mar | 3915 | isVisible: true, |
3916 | // if false, we use the backdrop helper without adding any element to the dom |
||
922 | daniel-mar | 3917 | rootElement: 'body' // give the choice to place backdrop under different elements |
1056 | daniel-mar | 3918 | }; |
922 | daniel-mar | 3919 | |
846 | daniel-mar | 3920 | const DefaultType$8 = { |
637 | daniel-mar | 3921 | className: 'string', |
922 | daniel-mar | 3922 | clickCallback: '(function|null)', |
3923 | isAnimated: 'boolean', |
||
597 | daniel-mar | 3924 | isVisible: 'boolean', |
922 | daniel-mar | 3925 | rootElement: '(element|string)' |
597 | daniel-mar | 3926 | }; |
1056 | daniel-mar | 3927 | |
846 | daniel-mar | 3928 | /** |
3929 | * Class definition |
||
3930 | */ |
||
597 | daniel-mar | 3931 | |
846 | daniel-mar | 3932 | class Backdrop extends Config { |
597 | daniel-mar | 3933 | constructor(config) { |
846 | daniel-mar | 3934 | super(); |
597 | daniel-mar | 3935 | this._config = this._getConfig(config); |
3936 | this._isAppended = false; |
||
3937 | this._element = null; |
||
1056 | daniel-mar | 3938 | } |
846 | daniel-mar | 3939 | |
1056 | daniel-mar | 3940 | // Getters |
846 | daniel-mar | 3941 | static get Default() { |
3942 | return Default$8; |
||
597 | daniel-mar | 3943 | } |
846 | daniel-mar | 3944 | static get DefaultType() { |
3945 | return DefaultType$8; |
||
3946 | } |
||
3947 | static get NAME() { |
||
3948 | return NAME$9; |
||
1056 | daniel-mar | 3949 | } |
846 | daniel-mar | 3950 | |
1056 | daniel-mar | 3951 | // Public |
597 | daniel-mar | 3952 | show(callback) { |
3953 | if (!this._config.isVisible) { |
||
3954 | execute(callback); |
||
3955 | return; |
||
3956 | } |
||
3957 | this._append(); |
||
846 | daniel-mar | 3958 | const element = this._getElement(); |
597 | daniel-mar | 3959 | if (this._config.isAnimated) { |
846 | daniel-mar | 3960 | reflow(element); |
597 | daniel-mar | 3961 | } |
846 | daniel-mar | 3962 | element.classList.add(CLASS_NAME_SHOW$5); |
597 | daniel-mar | 3963 | this._emulateAnimation(() => { |
3964 | execute(callback); |
||
3965 | }); |
||
3966 | } |
||
3967 | hide(callback) { |
||
3968 | if (!this._config.isVisible) { |
||
3969 | execute(callback); |
||
3970 | return; |
||
3971 | } |
||
637 | daniel-mar | 3972 | this._getElement().classList.remove(CLASS_NAME_SHOW$5); |
597 | daniel-mar | 3973 | this._emulateAnimation(() => { |
3974 | this.dispose(); |
||
3975 | execute(callback); |
||
3976 | }); |
||
846 | daniel-mar | 3977 | } |
3978 | dispose() { |
||
3979 | if (!this._isAppended) { |
||
3980 | return; |
||
3981 | } |
||
3982 | EventHandler.off(this._element, EVENT_MOUSEDOWN); |
||
3983 | this._element.remove(); |
||
3984 | this._isAppended = false; |
||
1056 | daniel-mar | 3985 | } |
597 | daniel-mar | 3986 | |
1056 | daniel-mar | 3987 | // Private |
597 | daniel-mar | 3988 | _getElement() { |
3989 | if (!this._element) { |
||
3990 | const backdrop = document.createElement('div'); |
||
637 | daniel-mar | 3991 | backdrop.className = this._config.className; |
597 | daniel-mar | 3992 | if (this._config.isAnimated) { |
637 | daniel-mar | 3993 | backdrop.classList.add(CLASS_NAME_FADE$4); |
597 | daniel-mar | 3994 | } |
3995 | this._element = backdrop; |
||
3996 | } |
||
3997 | return this._element; |
||
3998 | } |
||
846 | daniel-mar | 3999 | _configAfterMerge(config) { |
4000 | // use getElement() with the default "body" to get a fresh Element on each instantiation |
||
637 | daniel-mar | 4001 | config.rootElement = getElement(config.rootElement); |
597 | daniel-mar | 4002 | return config; |
4003 | } |
||
4004 | _append() { |
||
4005 | if (this._isAppended) { |
||
4006 | return; |
||
4007 | } |
||
846 | daniel-mar | 4008 | const element = this._getElement(); |
4009 | this._config.rootElement.append(element); |
||
4010 | EventHandler.on(element, EVENT_MOUSEDOWN, () => { |
||
597 | daniel-mar | 4011 | execute(this._config.clickCallback); |
4012 | }); |
||
4013 | this._isAppended = true; |
||
4014 | } |
||
4015 | _emulateAnimation(callback) { |
||
637 | daniel-mar | 4016 | executeAfterTransition(callback, this._getElement(), this._config.isAnimated); |
4017 | } |
||
4018 | } |
||
4019 | |||
4020 | /** |
||
4021 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 4022 | * Bootstrap util/focustrap.js |
679 | daniel-mar | 4023 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
637 | daniel-mar | 4024 | * -------------------------------------------------------------------------- |
4025 | */ |
||
1056 | daniel-mar | 4026 | |
1308 | daniel-mar | 4027 | |
846 | daniel-mar | 4028 | /** |
4029 | * Constants |
||
4030 | */ |
||
4031 | |||
4032 | const NAME$8 = 'focustrap'; |
||
4033 | const DATA_KEY$5 = 'bs.focustrap'; |
||
4034 | const EVENT_KEY$5 = `.${DATA_KEY$5}`; |
||
4035 | const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`; |
||
4036 | const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`; |
||
4037 | const TAB_KEY = 'Tab'; |
||
4038 | const TAB_NAV_FORWARD = 'forward'; |
||
4039 | const TAB_NAV_BACKWARD = 'backward'; |
||
4040 | const Default$7 = { |
||
922 | daniel-mar | 4041 | autofocus: true, |
4042 | trapElement: null // The element to trap focus inside of |
||
1056 | daniel-mar | 4043 | }; |
922 | daniel-mar | 4044 | |
846 | daniel-mar | 4045 | const DefaultType$7 = { |
922 | daniel-mar | 4046 | autofocus: 'boolean', |
4047 | trapElement: 'element' |
||
637 | daniel-mar | 4048 | }; |
1056 | daniel-mar | 4049 | |
846 | daniel-mar | 4050 | /** |
4051 | * Class definition |
||
4052 | */ |
||
637 | daniel-mar | 4053 | |
846 | daniel-mar | 4054 | class FocusTrap extends Config { |
637 | daniel-mar | 4055 | constructor(config) { |
846 | daniel-mar | 4056 | super(); |
637 | daniel-mar | 4057 | this._config = this._getConfig(config); |
4058 | this._isActive = false; |
||
4059 | this._lastTabNavDirection = null; |
||
1056 | daniel-mar | 4060 | } |
846 | daniel-mar | 4061 | |
1056 | daniel-mar | 4062 | // Getters |
846 | daniel-mar | 4063 | static get Default() { |
4064 | return Default$7; |
||
637 | daniel-mar | 4065 | } |
846 | daniel-mar | 4066 | static get DefaultType() { |
4067 | return DefaultType$7; |
||
4068 | } |
||
4069 | static get NAME() { |
||
4070 | return NAME$8; |
||
1056 | daniel-mar | 4071 | } |
846 | daniel-mar | 4072 | |
1056 | daniel-mar | 4073 | // Public |
637 | daniel-mar | 4074 | activate() { |
4075 | if (this._isActive) { |
||
597 | daniel-mar | 4076 | return; |
4077 | } |
||
846 | daniel-mar | 4078 | if (this._config.autofocus) { |
4079 | this._config.trapElement.focus(); |
||
637 | daniel-mar | 4080 | } |
846 | daniel-mar | 4081 | EventHandler.off(document, EVENT_KEY$5); // guard against infinite focus loop |
4082 | EventHandler.on(document, EVENT_FOCUSIN$2, event => this._handleFocusin(event)); |
||
637 | daniel-mar | 4083 | EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)); |
4084 | this._isActive = true; |
||
597 | daniel-mar | 4085 | } |
637 | daniel-mar | 4086 | deactivate() { |
4087 | if (!this._isActive) { |
||
4088 | return; |
||
4089 | } |
||
4090 | this._isActive = false; |
||
846 | daniel-mar | 4091 | EventHandler.off(document, EVENT_KEY$5); |
1056 | daniel-mar | 4092 | } |
637 | daniel-mar | 4093 | |
1056 | daniel-mar | 4094 | // Private |
637 | daniel-mar | 4095 | _handleFocusin(event) { |
4096 | const { |
||
4097 | trapElement |
||
4098 | } = this._config; |
||
846 | daniel-mar | 4099 | if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) { |
637 | daniel-mar | 4100 | return; |
4101 | } |
||
4102 | const elements = SelectorEngine.focusableChildren(trapElement); |
||
4103 | if (elements.length === 0) { |
||
4104 | trapElement.focus(); |
||
4105 | } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { |
||
4106 | elements[elements.length - 1].focus(); |
||
4107 | } else { |
||
4108 | elements[0].focus(); |
||
4109 | } |
||
4110 | } |
||
4111 | _handleKeydown(event) { |
||
4112 | if (event.key !== TAB_KEY) { |
||
4113 | return; |
||
4114 | } |
||
4115 | this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD; |
||
4116 | } |
||
597 | daniel-mar | 4117 | } |
4118 | |||
4119 | /** |
||
4120 | * -------------------------------------------------------------------------- |
||
1151 | daniel-mar | 4121 | * Bootstrap util/scrollBar.js |
4122 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
||
4123 | * -------------------------------------------------------------------------- |
||
4124 | */ |
||
4125 | |||
1308 | daniel-mar | 4126 | |
1151 | daniel-mar | 4127 | /** |
4128 | * Constants |
||
4129 | */ |
||
4130 | |||
4131 | const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; |
||
4132 | const SELECTOR_STICKY_CONTENT = '.sticky-top'; |
||
4133 | const PROPERTY_PADDING = 'padding-right'; |
||
4134 | const PROPERTY_MARGIN = 'margin-right'; |
||
4135 | |||
4136 | /** |
||
4137 | * Class definition |
||
4138 | */ |
||
4139 | |||
4140 | class ScrollBarHelper { |
||
4141 | constructor() { |
||
4142 | this._element = document.body; |
||
4143 | } |
||
4144 | |||
4145 | // Public |
||
4146 | getWidth() { |
||
4147 | // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes |
||
4148 | const documentWidth = document.documentElement.clientWidth; |
||
4149 | return Math.abs(window.innerWidth - documentWidth); |
||
4150 | } |
||
4151 | hide() { |
||
4152 | const width = this.getWidth(); |
||
4153 | this._disableOverFlow(); |
||
4154 | // give padding to element to balance the hidden scrollbar width |
||
4155 | this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width); |
||
4156 | // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth |
||
4157 | this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width); |
||
4158 | this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width); |
||
4159 | } |
||
4160 | reset() { |
||
4161 | this._resetElementAttributes(this._element, 'overflow'); |
||
4162 | this._resetElementAttributes(this._element, PROPERTY_PADDING); |
||
4163 | this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING); |
||
4164 | this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN); |
||
4165 | } |
||
4166 | isOverflowing() { |
||
4167 | return this.getWidth() > 0; |
||
4168 | } |
||
4169 | |||
4170 | // Private |
||
4171 | _disableOverFlow() { |
||
4172 | this._saveInitialAttribute(this._element, 'overflow'); |
||
4173 | this._element.style.overflow = 'hidden'; |
||
4174 | } |
||
4175 | _setElementAttributes(selector, styleProperty, callback) { |
||
4176 | const scrollbarWidth = this.getWidth(); |
||
4177 | const manipulationCallBack = element => { |
||
4178 | if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { |
||
4179 | return; |
||
4180 | } |
||
4181 | this._saveInitialAttribute(element, styleProperty); |
||
4182 | const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty); |
||
4183 | element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`); |
||
4184 | }; |
||
4185 | this._applyManipulationCallback(selector, manipulationCallBack); |
||
4186 | } |
||
4187 | _saveInitialAttribute(element, styleProperty) { |
||
4188 | const actualValue = element.style.getPropertyValue(styleProperty); |
||
4189 | if (actualValue) { |
||
4190 | Manipulator.setDataAttribute(element, styleProperty, actualValue); |
||
4191 | } |
||
4192 | } |
||
4193 | _resetElementAttributes(selector, styleProperty) { |
||
4194 | const manipulationCallBack = element => { |
||
4195 | const value = Manipulator.getDataAttribute(element, styleProperty); |
||
4196 | // We only want to remove the property if the value is `null`; the value can also be zero |
||
4197 | if (value === null) { |
||
4198 | element.style.removeProperty(styleProperty); |
||
4199 | return; |
||
4200 | } |
||
4201 | Manipulator.removeDataAttribute(element, styleProperty); |
||
4202 | element.style.setProperty(styleProperty, value); |
||
4203 | }; |
||
4204 | this._applyManipulationCallback(selector, manipulationCallBack); |
||
4205 | } |
||
4206 | _applyManipulationCallback(selector, callBack) { |
||
4207 | if (isElement$1(selector)) { |
||
4208 | callBack(selector); |
||
4209 | return; |
||
4210 | } |
||
4211 | for (const sel of SelectorEngine.find(selector, this._element)) { |
||
4212 | callBack(sel); |
||
4213 | } |
||
4214 | } |
||
4215 | } |
||
4216 | |||
4217 | /** |
||
4218 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 4219 | * Bootstrap modal.js |
597 | daniel-mar | 4220 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
4221 | * -------------------------------------------------------------------------- |
||
4222 | */ |
||
1056 | daniel-mar | 4223 | |
1308 | daniel-mar | 4224 | |
597 | daniel-mar | 4225 | /** |
4226 | * Constants |
||
4227 | */ |
||
4228 | |||
846 | daniel-mar | 4229 | const NAME$7 = 'modal'; |
4230 | const DATA_KEY$4 = 'bs.modal'; |
||
4231 | const EVENT_KEY$4 = `.${DATA_KEY$4}`; |
||
4232 | const DATA_API_KEY$2 = '.data-api'; |
||
597 | daniel-mar | 4233 | const ESCAPE_KEY$1 = 'Escape'; |
846 | daniel-mar | 4234 | const EVENT_HIDE$4 = `hide${EVENT_KEY$4}`; |
4235 | const EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`; |
||
4236 | const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`; |
||
4237 | const EVENT_SHOW$4 = `show${EVENT_KEY$4}`; |
||
4238 | const EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`; |
||
4239 | const EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`; |
||
931 | daniel-mar | 4240 | const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`; |
922 | daniel-mar | 4241 | const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`; |
846 | daniel-mar | 4242 | const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`; |
4243 | const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`; |
||
4244 | const CLASS_NAME_OPEN = 'modal-open'; |
||
4245 | const CLASS_NAME_FADE$3 = 'fade'; |
||
4246 | const CLASS_NAME_SHOW$4 = 'show'; |
||
4247 | const CLASS_NAME_STATIC = 'modal-static'; |
||
4248 | const OPEN_SELECTOR$1 = '.modal.show'; |
||
4249 | const SELECTOR_DIALOG = '.modal-dialog'; |
||
4250 | const SELECTOR_MODAL_BODY = '.modal-body'; |
||
4251 | const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="modal"]'; |
||
4252 | const Default$6 = { |
||
597 | daniel-mar | 4253 | backdrop: true, |
922 | daniel-mar | 4254 | focus: true, |
4255 | keyboard: true |
||
597 | daniel-mar | 4256 | }; |
846 | daniel-mar | 4257 | const DefaultType$6 = { |
597 | daniel-mar | 4258 | backdrop: '(boolean|string)', |
922 | daniel-mar | 4259 | focus: 'boolean', |
4260 | keyboard: 'boolean' |
||
597 | daniel-mar | 4261 | }; |
1056 | daniel-mar | 4262 | |
597 | daniel-mar | 4263 | /** |
846 | daniel-mar | 4264 | * Class definition |
597 | daniel-mar | 4265 | */ |
4266 | |||
4267 | class Modal extends BaseComponent { |
||
4268 | constructor(element, config) { |
||
846 | daniel-mar | 4269 | super(element, config); |
597 | daniel-mar | 4270 | this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); |
4271 | this._backdrop = this._initializeBackDrop(); |
||
637 | daniel-mar | 4272 | this._focustrap = this._initializeFocusTrap(); |
597 | daniel-mar | 4273 | this._isShown = false; |
4274 | this._isTransitioning = false; |
||
637 | daniel-mar | 4275 | this._scrollBar = new ScrollBarHelper(); |
846 | daniel-mar | 4276 | this._addEventListeners(); |
1056 | daniel-mar | 4277 | } |
597 | daniel-mar | 4278 | |
1056 | daniel-mar | 4279 | // Getters |
597 | daniel-mar | 4280 | static get Default() { |
846 | daniel-mar | 4281 | return Default$6; |
597 | daniel-mar | 4282 | } |
846 | daniel-mar | 4283 | static get DefaultType() { |
4284 | return DefaultType$6; |
||
4285 | } |
||
597 | daniel-mar | 4286 | static get NAME() { |
846 | daniel-mar | 4287 | return NAME$7; |
1056 | daniel-mar | 4288 | } |
597 | daniel-mar | 4289 | |
1056 | daniel-mar | 4290 | // Public |
597 | daniel-mar | 4291 | toggle(relatedTarget) { |
4292 | return this._isShown ? this.hide() : this.show(relatedTarget); |
||
4293 | } |
||
4294 | show(relatedTarget) { |
||
4295 | if (this._isShown || this._isTransitioning) { |
||
4296 | return; |
||
4297 | } |
||
846 | daniel-mar | 4298 | const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, { |
597 | daniel-mar | 4299 | relatedTarget |
4300 | }); |
||
637 | daniel-mar | 4301 | if (showEvent.defaultPrevented) { |
597 | daniel-mar | 4302 | return; |
4303 | } |
||
4304 | this._isShown = true; |
||
846 | daniel-mar | 4305 | this._isTransitioning = true; |
637 | daniel-mar | 4306 | this._scrollBar.hide(); |
597 | daniel-mar | 4307 | document.body.classList.add(CLASS_NAME_OPEN); |
4308 | this._adjustDialog(); |
||
846 | daniel-mar | 4309 | this._backdrop.show(() => this._showElement(relatedTarget)); |
597 | daniel-mar | 4310 | } |
637 | daniel-mar | 4311 | hide() { |
597 | daniel-mar | 4312 | if (!this._isShown || this._isTransitioning) { |
4313 | return; |
||
4314 | } |
||
846 | daniel-mar | 4315 | const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4); |
597 | daniel-mar | 4316 | if (hideEvent.defaultPrevented) { |
4317 | return; |
||
4318 | } |
||
4319 | this._isShown = false; |
||
846 | daniel-mar | 4320 | this._isTransitioning = true; |
637 | daniel-mar | 4321 | this._focustrap.deactivate(); |
4322 | this._element.classList.remove(CLASS_NAME_SHOW$4); |
||
846 | daniel-mar | 4323 | this._queueCallback(() => this._hideModal(), this._element, this._isAnimated()); |
597 | daniel-mar | 4324 | } |
4325 | dispose() { |
||
1151 | daniel-mar | 4326 | EventHandler.off(window, EVENT_KEY$4); |
4327 | EventHandler.off(this._dialog, EVENT_KEY$4); |
||
597 | daniel-mar | 4328 | this._backdrop.dispose(); |
637 | daniel-mar | 4329 | this._focustrap.deactivate(); |
597 | daniel-mar | 4330 | super.dispose(); |
4331 | } |
||
4332 | handleUpdate() { |
||
4333 | this._adjustDialog(); |
||
1056 | daniel-mar | 4334 | } |
597 | daniel-mar | 4335 | |
1056 | daniel-mar | 4336 | // Private |
597 | daniel-mar | 4337 | _initializeBackDrop() { |
4338 | return new Backdrop({ |
||
4339 | isVisible: Boolean(this._config.backdrop), |
||
846 | daniel-mar | 4340 | // 'static' option will be translated to true, and booleans will keep their value, |
597 | daniel-mar | 4341 | isAnimated: this._isAnimated() |
4342 | }); |
||
4343 | } |
||
637 | daniel-mar | 4344 | _initializeFocusTrap() { |
4345 | return new FocusTrap({ |
||
4346 | trapElement: this._element |
||
4347 | }); |
||
4348 | } |
||
597 | daniel-mar | 4349 | _showElement(relatedTarget) { |
846 | daniel-mar | 4350 | // try to append dynamic modal |
4351 | if (!document.body.contains(this._element)) { |
||
637 | daniel-mar | 4352 | document.body.append(this._element); |
597 | daniel-mar | 4353 | } |
4354 | this._element.style.display = 'block'; |
||
4355 | this._element.removeAttribute('aria-hidden'); |
||
4356 | this._element.setAttribute('aria-modal', true); |
||
4357 | this._element.setAttribute('role', 'dialog'); |
||
4358 | this._element.scrollTop = 0; |
||
846 | daniel-mar | 4359 | const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog); |
597 | daniel-mar | 4360 | if (modalBody) { |
4361 | modalBody.scrollTop = 0; |
||
4362 | } |
||
846 | daniel-mar | 4363 | reflow(this._element); |
637 | daniel-mar | 4364 | this._element.classList.add(CLASS_NAME_SHOW$4); |
597 | daniel-mar | 4365 | const transitionComplete = () => { |
4366 | if (this._config.focus) { |
||
637 | daniel-mar | 4367 | this._focustrap.activate(); |
597 | daniel-mar | 4368 | } |
4369 | this._isTransitioning = false; |
||
846 | daniel-mar | 4370 | EventHandler.trigger(this._element, EVENT_SHOWN$4, { |
597 | daniel-mar | 4371 | relatedTarget |
4372 | }); |
||
4373 | }; |
||
846 | daniel-mar | 4374 | this._queueCallback(transitionComplete, this._dialog, this._isAnimated()); |
597 | daniel-mar | 4375 | } |
846 | daniel-mar | 4376 | _addEventListeners() { |
4377 | EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => { |
||
4378 | if (event.key !== ESCAPE_KEY$1) { |
||
4379 | return; |
||
4380 | } |
||
4381 | if (this._config.keyboard) { |
||
4382 | this.hide(); |
||
4383 | return; |
||
4384 | } |
||
4385 | this._triggerBackdropTransition(); |
||
4386 | }); |
||
4387 | EventHandler.on(window, EVENT_RESIZE$1, () => { |
||
4388 | if (this._isShown && !this._isTransitioning) { |
||
4389 | this._adjustDialog(); |
||
4390 | } |
||
4391 | }); |
||
922 | daniel-mar | 4392 | EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => { |
981 | daniel-mar | 4393 | // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks |
931 | daniel-mar | 4394 | EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => { |
981 | daniel-mar | 4395 | if (this._element !== event.target || this._element !== event2.target) { |
931 | daniel-mar | 4396 | return; |
4397 | } |
||
4398 | if (this._config.backdrop === 'static') { |
||
4399 | this._triggerBackdropTransition(); |
||
4400 | return; |
||
4401 | } |
||
4402 | if (this._config.backdrop) { |
||
4403 | this.hide(); |
||
4404 | } |
||
4405 | }); |
||
846 | daniel-mar | 4406 | }); |
597 | daniel-mar | 4407 | } |
4408 | _hideModal() { |
||
4409 | this._element.style.display = 'none'; |
||
4410 | this._element.setAttribute('aria-hidden', true); |
||
4411 | this._element.removeAttribute('aria-modal'); |
||
4412 | this._element.removeAttribute('role'); |
||
4413 | this._isTransitioning = false; |
||
4414 | this._backdrop.hide(() => { |
||
4415 | document.body.classList.remove(CLASS_NAME_OPEN); |
||
4416 | this._resetAdjustments(); |
||
637 | daniel-mar | 4417 | this._scrollBar.reset(); |
846 | daniel-mar | 4418 | EventHandler.trigger(this._element, EVENT_HIDDEN$4); |
597 | daniel-mar | 4419 | }); |
4420 | } |
||
4421 | _isAnimated() { |
||
637 | daniel-mar | 4422 | return this._element.classList.contains(CLASS_NAME_FADE$3); |
597 | daniel-mar | 4423 | } |
4424 | _triggerBackdropTransition() { |
||
846 | daniel-mar | 4425 | const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1); |
597 | daniel-mar | 4426 | if (hideEvent.defaultPrevented) { |
4427 | return; |
||
4428 | } |
||
846 | daniel-mar | 4429 | const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; |
1056 | daniel-mar | 4430 | const initialOverflowY = this._element.style.overflowY; |
4431 | // return if the following background transition hasn't yet completed |
||
846 | daniel-mar | 4432 | if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) { |
637 | daniel-mar | 4433 | return; |
4434 | } |
||
597 | daniel-mar | 4435 | if (!isModalOverflowing) { |
846 | daniel-mar | 4436 | this._element.style.overflowY = 'hidden'; |
597 | daniel-mar | 4437 | } |
846 | daniel-mar | 4438 | this._element.classList.add(CLASS_NAME_STATIC); |
637 | daniel-mar | 4439 | this._queueCallback(() => { |
846 | daniel-mar | 4440 | this._element.classList.remove(CLASS_NAME_STATIC); |
4441 | this._queueCallback(() => { |
||
4442 | this._element.style.overflowY = initialOverflowY; |
||
4443 | }, this._dialog); |
||
637 | daniel-mar | 4444 | }, this._dialog); |
597 | daniel-mar | 4445 | this._element.focus(); |
846 | daniel-mar | 4446 | } |
1056 | daniel-mar | 4447 | |
846 | daniel-mar | 4448 | /** |
4449 | * The following methods are used to handle overflowing modals |
||
4450 | */ |
||
597 | daniel-mar | 4451 | |
4452 | _adjustDialog() { |
||
4453 | const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; |
||
637 | daniel-mar | 4454 | const scrollbarWidth = this._scrollBar.getWidth(); |
597 | daniel-mar | 4455 | const isBodyOverflowing = scrollbarWidth > 0; |
846 | daniel-mar | 4456 | if (isBodyOverflowing && !isModalOverflowing) { |
4457 | const property = isRTL() ? 'paddingLeft' : 'paddingRight'; |
||
4458 | this._element.style[property] = `${scrollbarWidth}px`; |
||
597 | daniel-mar | 4459 | } |
846 | daniel-mar | 4460 | if (!isBodyOverflowing && isModalOverflowing) { |
4461 | const property = isRTL() ? 'paddingRight' : 'paddingLeft'; |
||
4462 | this._element.style[property] = `${scrollbarWidth}px`; |
||
597 | daniel-mar | 4463 | } |
4464 | } |
||
4465 | _resetAdjustments() { |
||
4466 | this._element.style.paddingLeft = ''; |
||
4467 | this._element.style.paddingRight = ''; |
||
1056 | daniel-mar | 4468 | } |
597 | daniel-mar | 4469 | |
1056 | daniel-mar | 4470 | // Static |
597 | daniel-mar | 4471 | static jQueryInterface(config, relatedTarget) { |
4472 | return this.each(function () { |
||
637 | daniel-mar | 4473 | const data = Modal.getOrCreateInstance(this, config); |
597 | daniel-mar | 4474 | if (typeof config !== 'string') { |
4475 | return; |
||
4476 | } |
||
4477 | if (typeof data[config] === 'undefined') { |
||
4478 | throw new TypeError(`No method named "${config}"`); |
||
4479 | } |
||
4480 | data[config](relatedTarget); |
||
4481 | }); |
||
4482 | } |
||
1056 | daniel-mar | 4483 | } |
597 | daniel-mar | 4484 | |
4485 | /** |
||
846 | daniel-mar | 4486 | * Data API implementation |
597 | daniel-mar | 4487 | */ |
4488 | |||
4489 | EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) { |
||
1056 | daniel-mar | 4490 | const target = SelectorEngine.getElementFromSelector(this); |
597 | daniel-mar | 4491 | if (['A', 'AREA'].includes(this.tagName)) { |
4492 | event.preventDefault(); |
||
4493 | } |
||
846 | daniel-mar | 4494 | EventHandler.one(target, EVENT_SHOW$4, showEvent => { |
597 | daniel-mar | 4495 | if (showEvent.defaultPrevented) { |
4496 | // only register focus restorer if modal will actually get shown |
||
4497 | return; |
||
4498 | } |
||
846 | daniel-mar | 4499 | EventHandler.one(target, EVENT_HIDDEN$4, () => { |
597 | daniel-mar | 4500 | if (isVisible(this)) { |
4501 | this.focus(); |
||
4502 | } |
||
4503 | }); |
||
1056 | daniel-mar | 4504 | }); |
637 | daniel-mar | 4505 | |
1056 | daniel-mar | 4506 | // avoid conflict when clicking modal toggler while another one is open |
846 | daniel-mar | 4507 | const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR$1); |
4508 | if (alreadyOpen) { |
||
4509 | Modal.getInstance(alreadyOpen).hide(); |
||
637 | daniel-mar | 4510 | } |
4511 | const data = Modal.getOrCreateInstance(target); |
||
597 | daniel-mar | 4512 | data.toggle(this); |
4513 | }); |
||
637 | daniel-mar | 4514 | enableDismissTrigger(Modal); |
1056 | daniel-mar | 4515 | |
597 | daniel-mar | 4516 | /** |
4517 | * jQuery |
||
4518 | */ |
||
4519 | |||
4520 | defineJQueryPlugin(Modal); |
||
4521 | |||
4522 | /** |
||
4523 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 4524 | * Bootstrap offcanvas.js |
679 | daniel-mar | 4525 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
597 | daniel-mar | 4526 | * -------------------------------------------------------------------------- |
4527 | */ |
||
1056 | daniel-mar | 4528 | |
1308 | daniel-mar | 4529 | |
597 | daniel-mar | 4530 | /** |
4531 | * Constants |
||
4532 | */ |
||
4533 | |||
846 | daniel-mar | 4534 | const NAME$6 = 'offcanvas'; |
4535 | const DATA_KEY$3 = 'bs.offcanvas'; |
||
4536 | const EVENT_KEY$3 = `.${DATA_KEY$3}`; |
||
4537 | const DATA_API_KEY$1 = '.data-api'; |
||
4538 | const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`; |
||
597 | daniel-mar | 4539 | const ESCAPE_KEY = 'Escape'; |
846 | daniel-mar | 4540 | const CLASS_NAME_SHOW$3 = 'show'; |
4541 | const CLASS_NAME_SHOWING$1 = 'showing'; |
||
4542 | const CLASS_NAME_HIDING = 'hiding'; |
||
4543 | const CLASS_NAME_BACKDROP = 'offcanvas-backdrop'; |
||
4544 | const OPEN_SELECTOR = '.offcanvas.show'; |
||
4545 | const EVENT_SHOW$3 = `show${EVENT_KEY$3}`; |
||
4546 | const EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`; |
||
4547 | const EVENT_HIDE$3 = `hide${EVENT_KEY$3}`; |
||
4548 | const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`; |
||
4549 | const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`; |
||
4550 | const EVENT_RESIZE = `resize${EVENT_KEY$3}`; |
||
4551 | const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`; |
||
4552 | const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`; |
||
4553 | const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="offcanvas"]'; |
||
4554 | const Default$5 = { |
||
597 | daniel-mar | 4555 | backdrop: true, |
4556 | keyboard: true, |
||
4557 | scroll: false |
||
4558 | }; |
||
846 | daniel-mar | 4559 | const DefaultType$5 = { |
4560 | backdrop: '(boolean|string)', |
||
597 | daniel-mar | 4561 | keyboard: 'boolean', |
4562 | scroll: 'boolean' |
||
4563 | }; |
||
1056 | daniel-mar | 4564 | |
597 | daniel-mar | 4565 | /** |
846 | daniel-mar | 4566 | * Class definition |
597 | daniel-mar | 4567 | */ |
4568 | |||
4569 | class Offcanvas extends BaseComponent { |
||
4570 | constructor(element, config) { |
||
846 | daniel-mar | 4571 | super(element, config); |
597 | daniel-mar | 4572 | this._isShown = false; |
4573 | this._backdrop = this._initializeBackDrop(); |
||
637 | daniel-mar | 4574 | this._focustrap = this._initializeFocusTrap(); |
597 | daniel-mar | 4575 | this._addEventListeners(); |
1056 | daniel-mar | 4576 | } |
597 | daniel-mar | 4577 | |
1056 | daniel-mar | 4578 | // Getters |
846 | daniel-mar | 4579 | static get Default() { |
4580 | return Default$5; |
||
597 | daniel-mar | 4581 | } |
846 | daniel-mar | 4582 | static get DefaultType() { |
4583 | return DefaultType$5; |
||
4584 | } |
||
4585 | static get NAME() { |
||
4586 | return NAME$6; |
||
1056 | daniel-mar | 4587 | } |
597 | daniel-mar | 4588 | |
1056 | daniel-mar | 4589 | // Public |
597 | daniel-mar | 4590 | toggle(relatedTarget) { |
4591 | return this._isShown ? this.hide() : this.show(relatedTarget); |
||
4592 | } |
||
4593 | show(relatedTarget) { |
||
4594 | if (this._isShown) { |
||
4595 | return; |
||
4596 | } |
||
846 | daniel-mar | 4597 | const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, { |
597 | daniel-mar | 4598 | relatedTarget |
4599 | }); |
||
4600 | if (showEvent.defaultPrevented) { |
||
4601 | return; |
||
4602 | } |
||
4603 | this._isShown = true; |
||
4604 | this._backdrop.show(); |
||
4605 | if (!this._config.scroll) { |
||
637 | daniel-mar | 4606 | new ScrollBarHelper().hide(); |
597 | daniel-mar | 4607 | } |
4608 | this._element.setAttribute('aria-modal', true); |
||
4609 | this._element.setAttribute('role', 'dialog'); |
||
846 | daniel-mar | 4610 | this._element.classList.add(CLASS_NAME_SHOWING$1); |
597 | daniel-mar | 4611 | const completeCallBack = () => { |
922 | daniel-mar | 4612 | if (!this._config.scroll || this._config.backdrop) { |
637 | daniel-mar | 4613 | this._focustrap.activate(); |
4614 | } |
||
846 | daniel-mar | 4615 | this._element.classList.add(CLASS_NAME_SHOW$3); |
4616 | this._element.classList.remove(CLASS_NAME_SHOWING$1); |
||
4617 | EventHandler.trigger(this._element, EVENT_SHOWN$3, { |
||
597 | daniel-mar | 4618 | relatedTarget |
4619 | }); |
||
4620 | }; |
||
4621 | this._queueCallback(completeCallBack, this._element, true); |
||
4622 | } |
||
4623 | hide() { |
||
4624 | if (!this._isShown) { |
||
4625 | return; |
||
4626 | } |
||
846 | daniel-mar | 4627 | const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3); |
597 | daniel-mar | 4628 | if (hideEvent.defaultPrevented) { |
4629 | return; |
||
4630 | } |
||
637 | daniel-mar | 4631 | this._focustrap.deactivate(); |
597 | daniel-mar | 4632 | this._element.blur(); |
4633 | this._isShown = false; |
||
846 | daniel-mar | 4634 | this._element.classList.add(CLASS_NAME_HIDING); |
597 | daniel-mar | 4635 | this._backdrop.hide(); |
4636 | const completeCallback = () => { |
||
846 | daniel-mar | 4637 | this._element.classList.remove(CLASS_NAME_SHOW$3, CLASS_NAME_HIDING); |
597 | daniel-mar | 4638 | this._element.removeAttribute('aria-modal'); |
4639 | this._element.removeAttribute('role'); |
||
4640 | if (!this._config.scroll) { |
||
637 | daniel-mar | 4641 | new ScrollBarHelper().reset(); |
597 | daniel-mar | 4642 | } |
846 | daniel-mar | 4643 | EventHandler.trigger(this._element, EVENT_HIDDEN$3); |
597 | daniel-mar | 4644 | }; |
4645 | this._queueCallback(completeCallback, this._element, true); |
||
4646 | } |
||
4647 | dispose() { |
||
4648 | this._backdrop.dispose(); |
||
637 | daniel-mar | 4649 | this._focustrap.deactivate(); |
597 | daniel-mar | 4650 | super.dispose(); |
1056 | daniel-mar | 4651 | } |
597 | daniel-mar | 4652 | |
1056 | daniel-mar | 4653 | // Private |
846 | daniel-mar | 4654 | _initializeBackDrop() { |
4655 | const clickCallback = () => { |
||
4656 | if (this._config.backdrop === 'static') { |
||
4657 | EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); |
||
4658 | return; |
||
4659 | } |
||
4660 | this.hide(); |
||
1056 | daniel-mar | 4661 | }; |
846 | daniel-mar | 4662 | |
1056 | daniel-mar | 4663 | // 'static' option will be translated to true, and booleans will keep their value |
846 | daniel-mar | 4664 | const isVisible = Boolean(this._config.backdrop); |
597 | daniel-mar | 4665 | return new Backdrop({ |
637 | daniel-mar | 4666 | className: CLASS_NAME_BACKDROP, |
846 | daniel-mar | 4667 | isVisible, |
597 | daniel-mar | 4668 | isAnimated: true, |
4669 | rootElement: this._element.parentNode, |
||
846 | daniel-mar | 4670 | clickCallback: isVisible ? clickCallback : null |
597 | daniel-mar | 4671 | }); |
4672 | } |
||
637 | daniel-mar | 4673 | _initializeFocusTrap() { |
4674 | return new FocusTrap({ |
||
4675 | trapElement: this._element |
||
597 | daniel-mar | 4676 | }); |
4677 | } |
||
4678 | _addEventListeners() { |
||
4679 | EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { |
||
846 | daniel-mar | 4680 | if (event.key !== ESCAPE_KEY) { |
4681 | return; |
||
597 | daniel-mar | 4682 | } |
1134 | daniel-mar | 4683 | if (this._config.keyboard) { |
4684 | this.hide(); |
||
846 | daniel-mar | 4685 | return; |
4686 | } |
||
1134 | daniel-mar | 4687 | EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); |
597 | daniel-mar | 4688 | }); |
1056 | daniel-mar | 4689 | } |
597 | daniel-mar | 4690 | |
1056 | daniel-mar | 4691 | // Static |
597 | daniel-mar | 4692 | static jQueryInterface(config) { |
4693 | return this.each(function () { |
||
637 | daniel-mar | 4694 | const data = Offcanvas.getOrCreateInstance(this, config); |
597 | daniel-mar | 4695 | if (typeof config !== 'string') { |
4696 | return; |
||
4697 | } |
||
4698 | if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { |
||
4699 | throw new TypeError(`No method named "${config}"`); |
||
4700 | } |
||
4701 | data[config](this); |
||
4702 | }); |
||
4703 | } |
||
1056 | daniel-mar | 4704 | } |
597 | daniel-mar | 4705 | |
4706 | /** |
||
846 | daniel-mar | 4707 | * Data API implementation |
597 | daniel-mar | 4708 | */ |
4709 | |||
4710 | EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) { |
||
1056 | daniel-mar | 4711 | const target = SelectorEngine.getElementFromSelector(this); |
597 | daniel-mar | 4712 | if (['A', 'AREA'].includes(this.tagName)) { |
4713 | event.preventDefault(); |
||
4714 | } |
||
4715 | if (isDisabled(this)) { |
||
4716 | return; |
||
4717 | } |
||
846 | daniel-mar | 4718 | EventHandler.one(target, EVENT_HIDDEN$3, () => { |
597 | daniel-mar | 4719 | // focus on trigger when it is closed |
4720 | if (isVisible(this)) { |
||
4721 | this.focus(); |
||
4722 | } |
||
1056 | daniel-mar | 4723 | }); |
597 | daniel-mar | 4724 | |
1056 | daniel-mar | 4725 | // avoid conflict when clicking a toggler of an offcanvas, while another is open |
846 | daniel-mar | 4726 | const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR); |
4727 | if (alreadyOpen && alreadyOpen !== target) { |
||
4728 | Offcanvas.getInstance(alreadyOpen).hide(); |
||
597 | daniel-mar | 4729 | } |
637 | daniel-mar | 4730 | const data = Offcanvas.getOrCreateInstance(target); |
597 | daniel-mar | 4731 | data.toggle(this); |
4732 | }); |
||
846 | daniel-mar | 4733 | EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => { |
4734 | for (const selector of SelectorEngine.find(OPEN_SELECTOR)) { |
||
4735 | Offcanvas.getOrCreateInstance(selector).show(); |
||
4736 | } |
||
4737 | }); |
||
4738 | EventHandler.on(window, EVENT_RESIZE, () => { |
||
4739 | for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) { |
||
4740 | if (getComputedStyle(element).position !== 'fixed') { |
||
4741 | Offcanvas.getOrCreateInstance(element).hide(); |
||
4742 | } |
||
4743 | } |
||
4744 | }); |
||
637 | daniel-mar | 4745 | enableDismissTrigger(Offcanvas); |
1056 | daniel-mar | 4746 | |
597 | daniel-mar | 4747 | /** |
4748 | * jQuery |
||
4749 | */ |
||
4750 | |||
4751 | defineJQueryPlugin(Offcanvas); |
||
4752 | |||
4753 | /** |
||
4754 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 4755 | * Bootstrap util/sanitizer.js |
597 | daniel-mar | 4756 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
4757 | * -------------------------------------------------------------------------- |
||
4758 | */ |
||
1056 | daniel-mar | 4759 | |
1151 | daniel-mar | 4760 | // js-docs-start allow-list |
4761 | const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; |
||
597 | daniel-mar | 4762 | const DefaultAllowlist = { |
4763 | // Global attributes allowed on any supplied element below. |
||
4764 | '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], |
||
4765 | a: ['target', 'href', 'title', 'rel'], |
||
4766 | area: [], |
||
4767 | b: [], |
||
4768 | br: [], |
||
4769 | col: [], |
||
4770 | code: [], |
||
4771 | div: [], |
||
4772 | em: [], |
||
4773 | hr: [], |
||
4774 | h1: [], |
||
4775 | h2: [], |
||
4776 | h3: [], |
||
4777 | h4: [], |
||
4778 | h5: [], |
||
4779 | h6: [], |
||
4780 | i: [], |
||
4781 | img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], |
||
4782 | li: [], |
||
4783 | ol: [], |
||
4784 | p: [], |
||
4785 | pre: [], |
||
4786 | s: [], |
||
4787 | small: [], |
||
4788 | span: [], |
||
4789 | sub: [], |
||
4790 | sup: [], |
||
4791 | strong: [], |
||
4792 | u: [], |
||
4793 | ul: [] |
||
4794 | }; |
||
1151 | daniel-mar | 4795 | // js-docs-end allow-list |
4796 | |||
1308 | daniel-mar | 4797 | const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']); |
4798 | |||
4799 | /** |
||
4800 | * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation |
||
4801 | * contexts. |
||
4802 | * |
||
4803 | * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38 |
||
4804 | */ |
||
4805 | // eslint-disable-next-line unicorn/better-regex |
||
4806 | const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i; |
||
4807 | const allowedAttribute = (attribute, allowedAttributeList) => { |
||
4808 | const attributeName = attribute.nodeName.toLowerCase(); |
||
4809 | if (allowedAttributeList.includes(attributeName)) { |
||
4810 | if (uriAttributes.has(attributeName)) { |
||
4811 | return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue)); |
||
4812 | } |
||
4813 | return true; |
||
4814 | } |
||
4815 | |||
4816 | // Check if a regular expression validates the attribute. |
||
4817 | return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp).some(regex => regex.test(attributeName)); |
||
4818 | }; |
||
846 | daniel-mar | 4819 | function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) { |
597 | daniel-mar | 4820 | if (!unsafeHtml.length) { |
4821 | return unsafeHtml; |
||
4822 | } |
||
846 | daniel-mar | 4823 | if (sanitizeFunction && typeof sanitizeFunction === 'function') { |
4824 | return sanitizeFunction(unsafeHtml); |
||
597 | daniel-mar | 4825 | } |
4826 | const domParser = new window.DOMParser(); |
||
4827 | const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); |
||
4828 | const elements = [].concat(...createdDocument.body.querySelectorAll('*')); |
||
846 | daniel-mar | 4829 | for (const element of elements) { |
679 | daniel-mar | 4830 | const elementName = element.nodeName.toLowerCase(); |
4831 | if (!Object.keys(allowList).includes(elementName)) { |
||
4832 | element.remove(); |
||
597 | daniel-mar | 4833 | continue; |
4834 | } |
||
679 | daniel-mar | 4835 | const attributeList = [].concat(...element.attributes); |
4836 | const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []); |
||
846 | daniel-mar | 4837 | for (const attribute of attributeList) { |
679 | daniel-mar | 4838 | if (!allowedAttribute(attribute, allowedAttributes)) { |
4839 | element.removeAttribute(attribute.nodeName); |
||
597 | daniel-mar | 4840 | } |
846 | daniel-mar | 4841 | } |
597 | daniel-mar | 4842 | } |
4843 | return createdDocument.body.innerHTML; |
||
4844 | } |
||
4845 | |||
4846 | /** |
||
4847 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 4848 | * Bootstrap util/template-factory.js |
597 | daniel-mar | 4849 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
4850 | * -------------------------------------------------------------------------- |
||
4851 | */ |
||
1056 | daniel-mar | 4852 | |
1308 | daniel-mar | 4853 | |
597 | daniel-mar | 4854 | /** |
4855 | * Constants |
||
4856 | */ |
||
4857 | |||
846 | daniel-mar | 4858 | const NAME$5 = 'TemplateFactory'; |
4859 | const Default$4 = { |
||
922 | daniel-mar | 4860 | allowList: DefaultAllowlist, |
846 | daniel-mar | 4861 | content: {}, |
4862 | // { selector : text , selector2 : text2 , } |
||
922 | daniel-mar | 4863 | extraClass: '', |
846 | daniel-mar | 4864 | html: false, |
4865 | sanitize: true, |
||
4866 | sanitizeFn: null, |
||
922 | daniel-mar | 4867 | template: '<div></div>' |
846 | daniel-mar | 4868 | }; |
4869 | const DefaultType$4 = { |
||
922 | daniel-mar | 4870 | allowList: 'object', |
4871 | content: 'object', |
||
846 | daniel-mar | 4872 | extraClass: '(string|function)', |
597 | daniel-mar | 4873 | html: 'boolean', |
4874 | sanitize: 'boolean', |
||
4875 | sanitizeFn: '(null|function)', |
||
922 | daniel-mar | 4876 | template: 'string' |
597 | daniel-mar | 4877 | }; |
846 | daniel-mar | 4878 | const DefaultContentType = { |
922 | daniel-mar | 4879 | entry: '(string|element|function|null)', |
4880 | selector: '(string|element)' |
||
846 | daniel-mar | 4881 | }; |
1056 | daniel-mar | 4882 | |
846 | daniel-mar | 4883 | /** |
4884 | * Class definition |
||
4885 | */ |
||
4886 | |||
4887 | class TemplateFactory extends Config { |
||
4888 | constructor(config) { |
||
4889 | super(); |
||
4890 | this._config = this._getConfig(config); |
||
1056 | daniel-mar | 4891 | } |
846 | daniel-mar | 4892 | |
1056 | daniel-mar | 4893 | // Getters |
846 | daniel-mar | 4894 | static get Default() { |
4895 | return Default$4; |
||
4896 | } |
||
4897 | static get DefaultType() { |
||
4898 | return DefaultType$4; |
||
4899 | } |
||
4900 | static get NAME() { |
||
4901 | return NAME$5; |
||
1056 | daniel-mar | 4902 | } |
846 | daniel-mar | 4903 | |
1056 | daniel-mar | 4904 | // Public |
846 | daniel-mar | 4905 | getContent() { |
4906 | return Object.values(this._config.content).map(config => this._resolvePossibleFunction(config)).filter(Boolean); |
||
4907 | } |
||
4908 | hasContent() { |
||
4909 | return this.getContent().length > 0; |
||
4910 | } |
||
4911 | changeContent(content) { |
||
4912 | this._checkContent(content); |
||
1056 | daniel-mar | 4913 | this._config.content = { |
4914 | ...this._config.content, |
||
846 | daniel-mar | 4915 | ...content |
4916 | }; |
||
4917 | return this; |
||
4918 | } |
||
4919 | toHtml() { |
||
4920 | const templateWrapper = document.createElement('div'); |
||
4921 | templateWrapper.innerHTML = this._maybeSanitize(this._config.template); |
||
4922 | for (const [selector, text] of Object.entries(this._config.content)) { |
||
4923 | this._setContent(templateWrapper, text, selector); |
||
4924 | } |
||
4925 | const template = templateWrapper.children[0]; |
||
4926 | const extraClass = this._resolvePossibleFunction(this._config.extraClass); |
||
4927 | if (extraClass) { |
||
4928 | template.classList.add(...extraClass.split(' ')); |
||
4929 | } |
||
4930 | return template; |
||
1056 | daniel-mar | 4931 | } |
846 | daniel-mar | 4932 | |
1056 | daniel-mar | 4933 | // Private |
846 | daniel-mar | 4934 | _typeCheckConfig(config) { |
4935 | super._typeCheckConfig(config); |
||
4936 | this._checkContent(config.content); |
||
4937 | } |
||
4938 | _checkContent(arg) { |
||
4939 | for (const [selector, content] of Object.entries(arg)) { |
||
4940 | super._typeCheckConfig({ |
||
4941 | selector, |
||
4942 | entry: content |
||
4943 | }, DefaultContentType); |
||
4944 | } |
||
4945 | } |
||
4946 | _setContent(template, content, selector) { |
||
4947 | const templateElement = SelectorEngine.findOne(selector, template); |
||
4948 | if (!templateElement) { |
||
4949 | return; |
||
4950 | } |
||
4951 | content = this._resolvePossibleFunction(content); |
||
4952 | if (!content) { |
||
4953 | templateElement.remove(); |
||
4954 | return; |
||
4955 | } |
||
4956 | if (isElement$1(content)) { |
||
4957 | this._putElementInTemplate(getElement(content), templateElement); |
||
4958 | return; |
||
4959 | } |
||
4960 | if (this._config.html) { |
||
4961 | templateElement.innerHTML = this._maybeSanitize(content); |
||
4962 | return; |
||
4963 | } |
||
4964 | templateElement.textContent = content; |
||
4965 | } |
||
4966 | _maybeSanitize(arg) { |
||
4967 | return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg; |
||
4968 | } |
||
4969 | _resolvePossibleFunction(arg) { |
||
1056 | daniel-mar | 4970 | return execute(arg, [this]); |
846 | daniel-mar | 4971 | } |
4972 | _putElementInTemplate(element, templateElement) { |
||
4973 | if (this._config.html) { |
||
4974 | templateElement.innerHTML = ''; |
||
4975 | templateElement.append(element); |
||
4976 | return; |
||
4977 | } |
||
4978 | templateElement.textContent = element.textContent; |
||
4979 | } |
||
4980 | } |
||
4981 | |||
4982 | /** |
||
4983 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 4984 | * Bootstrap tooltip.js |
846 | daniel-mar | 4985 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
4986 | * -------------------------------------------------------------------------- |
||
4987 | */ |
||
1056 | daniel-mar | 4988 | |
1308 | daniel-mar | 4989 | |
846 | daniel-mar | 4990 | /** |
4991 | * Constants |
||
4992 | */ |
||
4993 | |||
4994 | const NAME$4 = 'tooltip'; |
||
4995 | const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); |
||
4996 | const CLASS_NAME_FADE$2 = 'fade'; |
||
4997 | const CLASS_NAME_MODAL = 'modal'; |
||
4998 | const CLASS_NAME_SHOW$2 = 'show'; |
||
4999 | const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; |
||
5000 | const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`; |
||
5001 | const EVENT_MODAL_HIDE = 'hide.bs.modal'; |
||
5002 | const TRIGGER_HOVER = 'hover'; |
||
5003 | const TRIGGER_FOCUS = 'focus'; |
||
5004 | const TRIGGER_CLICK = 'click'; |
||
5005 | const TRIGGER_MANUAL = 'manual'; |
||
5006 | const EVENT_HIDE$2 = 'hide'; |
||
5007 | const EVENT_HIDDEN$2 = 'hidden'; |
||
5008 | const EVENT_SHOW$2 = 'show'; |
||
5009 | const EVENT_SHOWN$2 = 'shown'; |
||
5010 | const EVENT_INSERTED = 'inserted'; |
||
5011 | const EVENT_CLICK$1 = 'click'; |
||
5012 | const EVENT_FOCUSIN$1 = 'focusin'; |
||
5013 | const EVENT_FOCUSOUT$1 = 'focusout'; |
||
5014 | const EVENT_MOUSEENTER = 'mouseenter'; |
||
5015 | const EVENT_MOUSELEAVE = 'mouseleave'; |
||
597 | daniel-mar | 5016 | const AttachmentMap = { |
5017 | AUTO: 'auto', |
||
5018 | TOP: 'top', |
||
5019 | RIGHT: isRTL() ? 'left' : 'right', |
||
5020 | BOTTOM: 'bottom', |
||
5021 | LEFT: isRTL() ? 'right' : 'left' |
||
5022 | }; |
||
5023 | const Default$3 = { |
||
922 | daniel-mar | 5024 | allowList: DefaultAllowlist, |
597 | daniel-mar | 5025 | animation: true, |
922 | daniel-mar | 5026 | boundary: 'clippingParents', |
5027 | container: false, |
||
5028 | customClass: '', |
||
597 | daniel-mar | 5029 | delay: 0, |
922 | daniel-mar | 5030 | fallbackPlacements: ['top', 'right', 'bottom', 'left'], |
597 | daniel-mar | 5031 | html: false, |
1151 | daniel-mar | 5032 | offset: [0, 6], |
597 | daniel-mar | 5033 | placement: 'top', |
922 | daniel-mar | 5034 | popperConfig: null, |
597 | daniel-mar | 5035 | sanitize: true, |
5036 | sanitizeFn: null, |
||
922 | daniel-mar | 5037 | selector: false, |
5038 | template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>', |
||
5039 | title: '', |
||
5040 | trigger: 'hover focus' |
||
597 | daniel-mar | 5041 | }; |
846 | daniel-mar | 5042 | const DefaultType$3 = { |
922 | daniel-mar | 5043 | allowList: 'object', |
846 | daniel-mar | 5044 | animation: 'boolean', |
922 | daniel-mar | 5045 | boundary: '(string|element)', |
5046 | container: '(string|element|boolean)', |
||
5047 | customClass: '(string|function)', |
||
846 | daniel-mar | 5048 | delay: '(number|object)', |
922 | daniel-mar | 5049 | fallbackPlacements: 'array', |
846 | daniel-mar | 5050 | html: 'boolean', |
922 | daniel-mar | 5051 | offset: '(array|string|function)', |
846 | daniel-mar | 5052 | placement: '(string|function)', |
922 | daniel-mar | 5053 | popperConfig: '(null|object|function)', |
846 | daniel-mar | 5054 | sanitize: 'boolean', |
5055 | sanitizeFn: '(null|function)', |
||
922 | daniel-mar | 5056 | selector: '(string|boolean)', |
5057 | template: 'string', |
||
5058 | title: '(string|element|function)', |
||
5059 | trigger: 'string' |
||
597 | daniel-mar | 5060 | }; |
1056 | daniel-mar | 5061 | |
597 | daniel-mar | 5062 | /** |
846 | daniel-mar | 5063 | * Class definition |
597 | daniel-mar | 5064 | */ |
5065 | |||
5066 | class Tooltip extends BaseComponent { |
||
5067 | constructor(element, config) { |
||
5068 | if (typeof Popper === 'undefined') { |
||
5069 | throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)'); |
||
5070 | } |
||
1056 | daniel-mar | 5071 | super(element, config); |
597 | daniel-mar | 5072 | |
1056 | daniel-mar | 5073 | // Private |
597 | daniel-mar | 5074 | this._isEnabled = true; |
5075 | this._timeout = 0; |
||
931 | daniel-mar | 5076 | this._isHovered = null; |
597 | daniel-mar | 5077 | this._activeTrigger = {}; |
846 | daniel-mar | 5078 | this._popper = null; |
922 | daniel-mar | 5079 | this._templateFactory = null; |
1056 | daniel-mar | 5080 | this._newContent = null; |
597 | daniel-mar | 5081 | |
1056 | daniel-mar | 5082 | // Protected |
597 | daniel-mar | 5083 | this.tip = null; |
5084 | this._setListeners(); |
||
981 | daniel-mar | 5085 | if (!this._config.selector) { |
5086 | this._fixTitle(); |
||
5087 | } |
||
1056 | daniel-mar | 5088 | } |
597 | daniel-mar | 5089 | |
1056 | daniel-mar | 5090 | // Getters |
597 | daniel-mar | 5091 | static get Default() { |
5092 | return Default$3; |
||
5093 | } |
||
846 | daniel-mar | 5094 | static get DefaultType() { |
5095 | return DefaultType$3; |
||
5096 | } |
||
597 | daniel-mar | 5097 | static get NAME() { |
5098 | return NAME$4; |
||
1056 | daniel-mar | 5099 | } |
597 | daniel-mar | 5100 | |
1056 | daniel-mar | 5101 | // Public |
597 | daniel-mar | 5102 | enable() { |
5103 | this._isEnabled = true; |
||
5104 | } |
||
5105 | disable() { |
||
5106 | this._isEnabled = false; |
||
5107 | } |
||
5108 | toggleEnabled() { |
||
5109 | this._isEnabled = !this._isEnabled; |
||
5110 | } |
||
981 | daniel-mar | 5111 | toggle() { |
597 | daniel-mar | 5112 | if (!this._isEnabled) { |
5113 | return; |
||
5114 | } |
||
981 | daniel-mar | 5115 | this._activeTrigger.click = !this._activeTrigger.click; |
846 | daniel-mar | 5116 | if (this._isShown()) { |
5117 | this._leave(); |
||
5118 | return; |
||
597 | daniel-mar | 5119 | } |
846 | daniel-mar | 5120 | this._enter(); |
597 | daniel-mar | 5121 | } |
5122 | dispose() { |
||
5123 | clearTimeout(this._timeout); |
||
637 | daniel-mar | 5124 | EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); |
981 | daniel-mar | 5125 | if (this._element.getAttribute('data-bs-original-title')) { |
5126 | this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title')); |
||
931 | daniel-mar | 5127 | } |
637 | daniel-mar | 5128 | this._disposePopper(); |
597 | daniel-mar | 5129 | super.dispose(); |
5130 | } |
||
5131 | show() { |
||
5132 | if (this._element.style.display === 'none') { |
||
5133 | throw new Error('Please use show on visible elements'); |
||
5134 | } |
||
846 | daniel-mar | 5135 | if (!(this._isWithContent() && this._isEnabled)) { |
597 | daniel-mar | 5136 | return; |
5137 | } |
||
846 | daniel-mar | 5138 | const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2)); |
597 | daniel-mar | 5139 | const shadowRoot = findShadowRoot(this._element); |
846 | daniel-mar | 5140 | const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element); |
597 | daniel-mar | 5141 | if (showEvent.defaultPrevented || !isInTheDom) { |
5142 | return; |
||
1056 | daniel-mar | 5143 | } |
922 | daniel-mar | 5144 | |
1151 | daniel-mar | 5145 | // TODO: v6 remove this or make it optional |
1037 | daniel-mar | 5146 | this._disposePopper(); |
846 | daniel-mar | 5147 | const tip = this._getTipElement(); |
5148 | this._element.setAttribute('aria-describedby', tip.getAttribute('id')); |
||
597 | daniel-mar | 5149 | const { |
5150 | container |
||
5151 | } = this._config; |
||
5152 | if (!this._element.ownerDocument.documentElement.contains(this.tip)) { |
||
637 | daniel-mar | 5153 | container.append(tip); |
846 | daniel-mar | 5154 | EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED)); |
597 | daniel-mar | 5155 | } |
1056 | daniel-mar | 5156 | this._popper = this._createPopper(tip); |
5157 | tip.classList.add(CLASS_NAME_SHOW$2); |
||
597 | daniel-mar | 5158 | |
1056 | daniel-mar | 5159 | // If this is a touch-enabled device we add extra |
597 | daniel-mar | 5160 | // empty mouseover listeners to the body's immediate children; |
5161 | // only needed because of broken event delegation on iOS |
||
5162 | // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html |
||
5163 | if ('ontouchstart' in document.documentElement) { |
||
846 | daniel-mar | 5164 | for (const element of [].concat(...document.body.children)) { |
597 | daniel-mar | 5165 | EventHandler.on(element, 'mouseover', noop); |
846 | daniel-mar | 5166 | } |
597 | daniel-mar | 5167 | } |
5168 | const complete = () => { |
||
846 | daniel-mar | 5169 | EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2)); |
931 | daniel-mar | 5170 | if (this._isHovered === false) { |
846 | daniel-mar | 5171 | this._leave(); |
597 | daniel-mar | 5172 | } |
931 | daniel-mar | 5173 | this._isHovered = false; |
597 | daniel-mar | 5174 | }; |
846 | daniel-mar | 5175 | this._queueCallback(complete, this.tip, this._isAnimated()); |
597 | daniel-mar | 5176 | } |
5177 | hide() { |
||
846 | daniel-mar | 5178 | if (!this._isShown()) { |
597 | daniel-mar | 5179 | return; |
5180 | } |
||
846 | daniel-mar | 5181 | const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2)); |
597 | daniel-mar | 5182 | if (hideEvent.defaultPrevented) { |
5183 | return; |
||
5184 | } |
||
846 | daniel-mar | 5185 | const tip = this._getTipElement(); |
1056 | daniel-mar | 5186 | tip.classList.remove(CLASS_NAME_SHOW$2); |
846 | daniel-mar | 5187 | |
1056 | daniel-mar | 5188 | // If this is a touch-enabled device we remove the extra |
597 | daniel-mar | 5189 | // empty mouseover listeners we added for iOS support |
5190 | if ('ontouchstart' in document.documentElement) { |
||
846 | daniel-mar | 5191 | for (const element of [].concat(...document.body.children)) { |
5192 | EventHandler.off(element, 'mouseover', noop); |
||
5193 | } |
||
597 | daniel-mar | 5194 | } |
5195 | this._activeTrigger[TRIGGER_CLICK] = false; |
||
5196 | this._activeTrigger[TRIGGER_FOCUS] = false; |
||
5197 | this._activeTrigger[TRIGGER_HOVER] = false; |
||
931 | daniel-mar | 5198 | this._isHovered = null; // it is a trick to support manual triggering |
597 | daniel-mar | 5199 | |
846 | daniel-mar | 5200 | const complete = () => { |
5201 | if (this._isWithActiveTrigger()) { |
||
5202 | return; |
||
5203 | } |
||
5204 | if (!this._isHovered) { |
||
1037 | daniel-mar | 5205 | this._disposePopper(); |
846 | daniel-mar | 5206 | } |
5207 | this._element.removeAttribute('aria-describedby'); |
||
5208 | EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2)); |
||
5209 | }; |
||
5210 | this._queueCallback(complete, this.tip, this._isAnimated()); |
||
597 | daniel-mar | 5211 | } |
5212 | update() { |
||
846 | daniel-mar | 5213 | if (this._popper) { |
597 | daniel-mar | 5214 | this._popper.update(); |
5215 | } |
||
1056 | daniel-mar | 5216 | } |
597 | daniel-mar | 5217 | |
1056 | daniel-mar | 5218 | // Protected |
846 | daniel-mar | 5219 | _isWithContent() { |
5220 | return Boolean(this._getTitle()); |
||
597 | daniel-mar | 5221 | } |
846 | daniel-mar | 5222 | _getTipElement() { |
5223 | if (!this.tip) { |
||
922 | daniel-mar | 5224 | this.tip = this._createTipElement(this._newContent || this._getContentForTemplate()); |
597 | daniel-mar | 5225 | } |
5226 | return this.tip; |
||
5227 | } |
||
846 | daniel-mar | 5228 | _createTipElement(content) { |
1056 | daniel-mar | 5229 | const tip = this._getTemplateFactory(content).toHtml(); |
597 | daniel-mar | 5230 | |
1151 | daniel-mar | 5231 | // TODO: remove this check in v6 |
846 | daniel-mar | 5232 | if (!tip) { |
5233 | return null; |
||
5234 | } |
||
1056 | daniel-mar | 5235 | tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2); |
1151 | daniel-mar | 5236 | // TODO: v6 the following can be achieved with CSS only |
846 | daniel-mar | 5237 | tip.classList.add(`bs-${this.constructor.NAME}-auto`); |
5238 | const tipId = getUID(this.constructor.NAME).toString(); |
||
5239 | tip.setAttribute('id', tipId); |
||
5240 | if (this._isAnimated()) { |
||
5241 | tip.classList.add(CLASS_NAME_FADE$2); |
||
597 | daniel-mar | 5242 | } |
846 | daniel-mar | 5243 | return tip; |
5244 | } |
||
5245 | setContent(content) { |
||
922 | daniel-mar | 5246 | this._newContent = content; |
5247 | if (this._isShown()) { |
||
5248 | this._disposePopper(); |
||
846 | daniel-mar | 5249 | this.show(); |
597 | daniel-mar | 5250 | } |
5251 | } |
||
846 | daniel-mar | 5252 | _getTemplateFactory(content) { |
5253 | if (this._templateFactory) { |
||
5254 | this._templateFactory.changeContent(content); |
||
5255 | } else { |
||
1056 | daniel-mar | 5256 | this._templateFactory = new TemplateFactory({ |
5257 | ...this._config, |
||
846 | daniel-mar | 5258 | // the `content` var has to be after `this._config` |
5259 | // to override config.content in case of popover |
||
5260 | content, |
||
5261 | extraClass: this._resolvePossibleFunction(this._config.customClass) |
||
5262 | }); |
||
5263 | } |
||
5264 | return this._templateFactory; |
||
597 | daniel-mar | 5265 | } |
846 | daniel-mar | 5266 | _getContentForTemplate() { |
5267 | return { |
||
5268 | [SELECTOR_TOOLTIP_INNER]: this._getTitle() |
||
5269 | }; |
||
5270 | } |
||
5271 | _getTitle() { |
||
981 | daniel-mar | 5272 | return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title'); |
1056 | daniel-mar | 5273 | } |
597 | daniel-mar | 5274 | |
1056 | daniel-mar | 5275 | // Private |
846 | daniel-mar | 5276 | _initializeOnDelegatedTarget(event) { |
5277 | return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig()); |
||
597 | daniel-mar | 5278 | } |
846 | daniel-mar | 5279 | _isAnimated() { |
5280 | return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE$2); |
||
5281 | } |
||
5282 | _isShown() { |
||
5283 | return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2); |
||
5284 | } |
||
5285 | _createPopper(tip) { |
||
1056 | daniel-mar | 5286 | const placement = execute(this._config.placement, [this, tip, this._element]); |
846 | daniel-mar | 5287 | const attachment = AttachmentMap[placement.toUpperCase()]; |
922 | daniel-mar | 5288 | return createPopper(this._element, tip, this._getPopperConfig(attachment)); |
846 | daniel-mar | 5289 | } |
597 | daniel-mar | 5290 | _getOffset() { |
5291 | const { |
||
5292 | offset |
||
5293 | } = this._config; |
||
5294 | if (typeof offset === 'string') { |
||
846 | daniel-mar | 5295 | return offset.split(',').map(value => Number.parseInt(value, 10)); |
597 | daniel-mar | 5296 | } |
5297 | if (typeof offset === 'function') { |
||
5298 | return popperData => offset(popperData, this._element); |
||
5299 | } |
||
5300 | return offset; |
||
5301 | } |
||
846 | daniel-mar | 5302 | _resolvePossibleFunction(arg) { |
1056 | daniel-mar | 5303 | return execute(arg, [this._element]); |
637 | daniel-mar | 5304 | } |
597 | daniel-mar | 5305 | _getPopperConfig(attachment) { |
5306 | const defaultBsPopperConfig = { |
||
5307 | placement: attachment, |
||
5308 | modifiers: [{ |
||
5309 | name: 'flip', |
||
5310 | options: { |
||
5311 | fallbackPlacements: this._config.fallbackPlacements |
||
5312 | } |
||
5313 | }, { |
||
5314 | name: 'offset', |
||
5315 | options: { |
||
5316 | offset: this._getOffset() |
||
5317 | } |
||
5318 | }, { |
||
5319 | name: 'preventOverflow', |
||
5320 | options: { |
||
5321 | boundary: this._config.boundary |
||
5322 | } |
||
5323 | }, { |
||
5324 | name: 'arrow', |
||
5325 | options: { |
||
5326 | element: `.${this.constructor.NAME}-arrow` |
||
5327 | } |
||
5328 | }, { |
||
846 | daniel-mar | 5329 | name: 'preSetPlacement', |
597 | daniel-mar | 5330 | enabled: true, |
846 | daniel-mar | 5331 | phase: 'beforeMain', |
5332 | fn: data => { |
||
5333 | // Pre-set Popper's placement attribute in order to read the arrow sizes properly. |
||
5334 | // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement |
||
5335 | this._getTipElement().setAttribute('data-popper-placement', data.state.placement); |
||
597 | daniel-mar | 5336 | } |
846 | daniel-mar | 5337 | }] |
597 | daniel-mar | 5338 | }; |
1056 | daniel-mar | 5339 | return { |
5340 | ...defaultBsPopperConfig, |
||
5341 | ...execute(this._config.popperConfig, [defaultBsPopperConfig]) |
||
597 | daniel-mar | 5342 | }; |
5343 | } |
||
5344 | _setListeners() { |
||
5345 | const triggers = this._config.trigger.split(' '); |
||
846 | daniel-mar | 5346 | for (const trigger of triggers) { |
597 | daniel-mar | 5347 | if (trigger === 'click') { |
981 | daniel-mar | 5348 | EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => { |
5349 | const context = this._initializeOnDelegatedTarget(event); |
||
5350 | context.toggle(); |
||
5351 | }); |
||
597 | daniel-mar | 5352 | } else if (trigger !== TRIGGER_MANUAL) { |
846 | daniel-mar | 5353 | const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN$1); |
5354 | const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT$1); |
||
5355 | EventHandler.on(this._element, eventIn, this._config.selector, event => { |
||
5356 | const context = this._initializeOnDelegatedTarget(event); |
||
5357 | context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true; |
||
5358 | context._enter(); |
||
5359 | }); |
||
5360 | EventHandler.on(this._element, eventOut, this._config.selector, event => { |
||
5361 | const context = this._initializeOnDelegatedTarget(event); |
||
5362 | context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget); |
||
5363 | context._leave(); |
||
5364 | }); |
||
597 | daniel-mar | 5365 | } |
846 | daniel-mar | 5366 | } |
597 | daniel-mar | 5367 | this._hideModalHandler = () => { |
5368 | if (this._element) { |
||
5369 | this.hide(); |
||
5370 | } |
||
5371 | }; |
||
637 | daniel-mar | 5372 | EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); |
597 | daniel-mar | 5373 | } |
5374 | _fixTitle() { |
||
981 | daniel-mar | 5375 | const title = this._element.getAttribute('title'); |
846 | daniel-mar | 5376 | if (!title) { |
5377 | return; |
||
5378 | } |
||
922 | daniel-mar | 5379 | if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) { |
846 | daniel-mar | 5380 | this._element.setAttribute('aria-label', title); |
5381 | } |
||
981 | daniel-mar | 5382 | this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility |
846 | daniel-mar | 5383 | this._element.removeAttribute('title'); |
597 | daniel-mar | 5384 | } |
846 | daniel-mar | 5385 | _enter() { |
5386 | if (this._isShown() || this._isHovered) { |
||
5387 | this._isHovered = true; |
||
597 | daniel-mar | 5388 | return; |
5389 | } |
||
846 | daniel-mar | 5390 | this._isHovered = true; |
5391 | this._setTimeout(() => { |
||
5392 | if (this._isHovered) { |
||
5393 | this.show(); |
||
597 | daniel-mar | 5394 | } |
846 | daniel-mar | 5395 | }, this._config.delay.show); |
597 | daniel-mar | 5396 | } |
846 | daniel-mar | 5397 | _leave() { |
5398 | if (this._isWithActiveTrigger()) { |
||
597 | daniel-mar | 5399 | return; |
5400 | } |
||
846 | daniel-mar | 5401 | this._isHovered = false; |
5402 | this._setTimeout(() => { |
||
5403 | if (!this._isHovered) { |
||
5404 | this.hide(); |
||
597 | daniel-mar | 5405 | } |
846 | daniel-mar | 5406 | }, this._config.delay.hide); |
597 | daniel-mar | 5407 | } |
846 | daniel-mar | 5408 | _setTimeout(handler, timeout) { |
5409 | clearTimeout(this._timeout); |
||
5410 | this._timeout = setTimeout(handler, timeout); |
||
5411 | } |
||
597 | daniel-mar | 5412 | _isWithActiveTrigger() { |
846 | daniel-mar | 5413 | return Object.values(this._activeTrigger).includes(true); |
597 | daniel-mar | 5414 | } |
5415 | _getConfig(config) { |
||
5416 | const dataAttributes = Manipulator.getDataAttributes(this._element); |
||
846 | daniel-mar | 5417 | for (const dataAttribute of Object.keys(dataAttributes)) { |
5418 | if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) { |
||
5419 | delete dataAttributes[dataAttribute]; |
||
597 | daniel-mar | 5420 | } |
846 | daniel-mar | 5421 | } |
1056 | daniel-mar | 5422 | config = { |
5423 | ...dataAttributes, |
||
597 | daniel-mar | 5424 | ...(typeof config === 'object' && config ? config : {}) |
5425 | }; |
||
846 | daniel-mar | 5426 | config = this._mergeConfigObj(config); |
5427 | config = this._configAfterMerge(config); |
||
5428 | this._typeCheckConfig(config); |
||
5429 | return config; |
||
5430 | } |
||
5431 | _configAfterMerge(config) { |
||
597 | daniel-mar | 5432 | config.container = config.container === false ? document.body : getElement(config.container); |
5433 | if (typeof config.delay === 'number') { |
||
5434 | config.delay = { |
||
5435 | show: config.delay, |
||
5436 | hide: config.delay |
||
5437 | }; |
||
5438 | } |
||
5439 | if (typeof config.title === 'number') { |
||
5440 | config.title = config.title.toString(); |
||
5441 | } |
||
5442 | if (typeof config.content === 'number') { |
||
5443 | config.content = config.content.toString(); |
||
5444 | } |
||
5445 | return config; |
||
5446 | } |
||
5447 | _getDelegateConfig() { |
||
5448 | const config = {}; |
||
1056 | daniel-mar | 5449 | for (const [key, value] of Object.entries(this._config)) { |
5450 | if (this.constructor.Default[key] !== value) { |
||
5451 | config[key] = value; |
||
597 | daniel-mar | 5452 | } |
981 | daniel-mar | 5453 | } |
1056 | daniel-mar | 5454 | config.selector = false; |
5455 | config.trigger = 'manual'; |
||
981 | daniel-mar | 5456 | |
1056 | daniel-mar | 5457 | // In the future can be replaced with: |
637 | daniel-mar | 5458 | // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]]) |
5459 | // `Object.fromEntries(keysWithDifferentValues)` |
||
597 | daniel-mar | 5460 | return config; |
5461 | } |
||
637 | daniel-mar | 5462 | _disposePopper() { |
5463 | if (this._popper) { |
||
5464 | this._popper.destroy(); |
||
5465 | this._popper = null; |
||
5466 | } |
||
1037 | daniel-mar | 5467 | if (this.tip) { |
5468 | this.tip.remove(); |
||
5469 | this.tip = null; |
||
5470 | } |
||
1056 | daniel-mar | 5471 | } |
597 | daniel-mar | 5472 | |
1056 | daniel-mar | 5473 | // Static |
597 | daniel-mar | 5474 | static jQueryInterface(config) { |
5475 | return this.each(function () { |
||
637 | daniel-mar | 5476 | const data = Tooltip.getOrCreateInstance(this, config); |
846 | daniel-mar | 5477 | if (typeof config !== 'string') { |
5478 | return; |
||
5479 | } |
||
5480 | if (typeof data[config] === 'undefined') { |
||
5481 | throw new TypeError(`No method named "${config}"`); |
||
597 | daniel-mar | 5482 | } |
846 | daniel-mar | 5483 | data[config](); |
597 | daniel-mar | 5484 | }); |
5485 | } |
||
1056 | daniel-mar | 5486 | } |
597 | daniel-mar | 5487 | |
5488 | /** |
||
5489 | * jQuery |
||
5490 | */ |
||
5491 | |||
5492 | defineJQueryPlugin(Tooltip); |
||
5493 | |||
5494 | /** |
||
5495 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 5496 | * Bootstrap popover.js |
597 | daniel-mar | 5497 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
5498 | * -------------------------------------------------------------------------- |
||
5499 | */ |
||
1056 | daniel-mar | 5500 | |
1308 | daniel-mar | 5501 | |
597 | daniel-mar | 5502 | /** |
5503 | * Constants |
||
5504 | */ |
||
5505 | |||
5506 | const NAME$3 = 'popover'; |
||
846 | daniel-mar | 5507 | const SELECTOR_TITLE = '.popover-header'; |
5508 | const SELECTOR_CONTENT = '.popover-body'; |
||
1056 | daniel-mar | 5509 | const Default$2 = { |
5510 | ...Tooltip.Default, |
||
922 | daniel-mar | 5511 | content: '', |
5512 | offset: [0, 8], |
||
597 | daniel-mar | 5513 | placement: 'right', |
922 | daniel-mar | 5514 | template: '<div class="popover" role="tooltip">' + '<div class="popover-arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div>' + '</div>', |
5515 | trigger: 'click' |
||
597 | daniel-mar | 5516 | }; |
1056 | daniel-mar | 5517 | const DefaultType$2 = { |
5518 | ...Tooltip.DefaultType, |
||
846 | daniel-mar | 5519 | content: '(null|string|element|function)' |
597 | daniel-mar | 5520 | }; |
1056 | daniel-mar | 5521 | |
597 | daniel-mar | 5522 | /** |
846 | daniel-mar | 5523 | * Class definition |
597 | daniel-mar | 5524 | */ |
5525 | |||
5526 | class Popover extends Tooltip { |
||
5527 | // Getters |
||
5528 | static get Default() { |
||
5529 | return Default$2; |
||
5530 | } |
||
846 | daniel-mar | 5531 | static get DefaultType() { |
5532 | return DefaultType$2; |
||
5533 | } |
||
597 | daniel-mar | 5534 | static get NAME() { |
5535 | return NAME$3; |
||
1056 | daniel-mar | 5536 | } |
597 | daniel-mar | 5537 | |
1056 | daniel-mar | 5538 | // Overrides |
846 | daniel-mar | 5539 | _isWithContent() { |
5540 | return this._getTitle() || this._getContent(); |
||
1056 | daniel-mar | 5541 | } |
597 | daniel-mar | 5542 | |
1056 | daniel-mar | 5543 | // Private |
846 | daniel-mar | 5544 | _getContentForTemplate() { |
5545 | return { |
||
5546 | [SELECTOR_TITLE]: this._getTitle(), |
||
5547 | [SELECTOR_CONTENT]: this._getContent() |
||
5548 | }; |
||
597 | daniel-mar | 5549 | } |
5550 | _getContent() { |
||
637 | daniel-mar | 5551 | return this._resolvePossibleFunction(this._config.content); |
1056 | daniel-mar | 5552 | } |
597 | daniel-mar | 5553 | |
1056 | daniel-mar | 5554 | // Static |
597 | daniel-mar | 5555 | static jQueryInterface(config) { |
5556 | return this.each(function () { |
||
637 | daniel-mar | 5557 | const data = Popover.getOrCreateInstance(this, config); |
846 | daniel-mar | 5558 | if (typeof config !== 'string') { |
5559 | return; |
||
5560 | } |
||
5561 | if (typeof data[config] === 'undefined') { |
||
5562 | throw new TypeError(`No method named "${config}"`); |
||
597 | daniel-mar | 5563 | } |
846 | daniel-mar | 5564 | data[config](); |
597 | daniel-mar | 5565 | }); |
5566 | } |
||
1056 | daniel-mar | 5567 | } |
597 | daniel-mar | 5568 | |
5569 | /** |
||
5570 | * jQuery |
||
5571 | */ |
||
5572 | |||
5573 | defineJQueryPlugin(Popover); |
||
5574 | |||
5575 | /** |
||
5576 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 5577 | * Bootstrap scrollspy.js |
597 | daniel-mar | 5578 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
5579 | * -------------------------------------------------------------------------- |
||
5580 | */ |
||
1056 | daniel-mar | 5581 | |
1308 | daniel-mar | 5582 | |
597 | daniel-mar | 5583 | /** |
5584 | * Constants |
||
5585 | */ |
||
5586 | |||
5587 | const NAME$2 = 'scrollspy'; |
||
5588 | const DATA_KEY$2 = 'bs.scrollspy'; |
||
5589 | const EVENT_KEY$2 = `.${DATA_KEY$2}`; |
||
846 | daniel-mar | 5590 | const DATA_API_KEY = '.data-api'; |
597 | daniel-mar | 5591 | const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`; |
846 | daniel-mar | 5592 | const EVENT_CLICK = `click${EVENT_KEY$2}`; |
5593 | const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`; |
||
597 | daniel-mar | 5594 | const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'; |
5595 | const CLASS_NAME_ACTIVE$1 = 'active'; |
||
5596 | const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]'; |
||
846 | daniel-mar | 5597 | const SELECTOR_TARGET_LINKS = '[href]'; |
5598 | const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'; |
||
597 | daniel-mar | 5599 | const SELECTOR_NAV_LINKS = '.nav-link'; |
5600 | const SELECTOR_NAV_ITEMS = '.nav-item'; |
||
5601 | const SELECTOR_LIST_ITEMS = '.list-group-item'; |
||
846 | daniel-mar | 5602 | const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`; |
5603 | const SELECTOR_DROPDOWN = '.dropdown'; |
||
597 | daniel-mar | 5604 | const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle'; |
846 | daniel-mar | 5605 | const Default$1 = { |
5606 | offset: null, |
||
5607 | // TODO: v6 @deprecated, keep it for backwards compatibility reasons |
||
5608 | rootMargin: '0px 0px -25%', |
||
5609 | smoothScroll: false, |
||
931 | daniel-mar | 5610 | target: null, |
5611 | threshold: [0.1, 0.5, 1] |
||
846 | daniel-mar | 5612 | }; |
5613 | const DefaultType$1 = { |
||
5614 | offset: '(number|null)', |
||
5615 | // TODO v6 @deprecated, keep it for backwards compatibility reasons |
||
5616 | rootMargin: 'string', |
||
5617 | smoothScroll: 'boolean', |
||
931 | daniel-mar | 5618 | target: 'element', |
5619 | threshold: 'array' |
||
846 | daniel-mar | 5620 | }; |
1056 | daniel-mar | 5621 | |
597 | daniel-mar | 5622 | /** |
846 | daniel-mar | 5623 | * Class definition |
597 | daniel-mar | 5624 | */ |
5625 | |||
5626 | class ScrollSpy extends BaseComponent { |
||
5627 | constructor(element, config) { |
||
1056 | daniel-mar | 5628 | super(element, config); |
846 | daniel-mar | 5629 | |
1056 | daniel-mar | 5630 | // this._element is the observablesContainer and config.target the menu links wrapper |
846 | daniel-mar | 5631 | this._targetLinks = new Map(); |
5632 | this._observableSections = new Map(); |
||
5633 | this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element; |
||
597 | daniel-mar | 5634 | this._activeTarget = null; |
846 | daniel-mar | 5635 | this._observer = null; |
5636 | this._previousScrollData = { |
||
5637 | visibleEntryTop: 0, |
||
5638 | parentScrollTop: 0 |
||
5639 | }; |
||
5640 | this.refresh(); // initialize |
||
1056 | daniel-mar | 5641 | } |
597 | daniel-mar | 5642 | |
1056 | daniel-mar | 5643 | // Getters |
597 | daniel-mar | 5644 | static get Default() { |
5645 | return Default$1; |
||
5646 | } |
||
846 | daniel-mar | 5647 | static get DefaultType() { |
5648 | return DefaultType$1; |
||
5649 | } |
||
597 | daniel-mar | 5650 | static get NAME() { |
5651 | return NAME$2; |
||
1056 | daniel-mar | 5652 | } |
597 | daniel-mar | 5653 | |
1056 | daniel-mar | 5654 | // Public |
597 | daniel-mar | 5655 | refresh() { |
846 | daniel-mar | 5656 | this._initializeTargetsAndObservables(); |
5657 | this._maybeEnableSmoothScroll(); |
||
5658 | if (this._observer) { |
||
5659 | this._observer.disconnect(); |
||
5660 | } else { |
||
5661 | this._observer = this._getNewObserver(); |
||
5662 | } |
||
5663 | for (const section of this._observableSections.values()) { |
||
5664 | this._observer.observe(section); |
||
5665 | } |
||
597 | daniel-mar | 5666 | } |
5667 | dispose() { |
||
846 | daniel-mar | 5668 | this._observer.disconnect(); |
597 | daniel-mar | 5669 | super.dispose(); |
1056 | daniel-mar | 5670 | } |
597 | daniel-mar | 5671 | |
1056 | daniel-mar | 5672 | // Private |
846 | daniel-mar | 5673 | _configAfterMerge(config) { |
5674 | // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case |
||
1056 | daniel-mar | 5675 | config.target = getElement(config.target) || document.body; |
931 | daniel-mar | 5676 | |
1056 | daniel-mar | 5677 | // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only |
931 | daniel-mar | 5678 | config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin; |
5679 | if (typeof config.threshold === 'string') { |
||
5680 | config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value)); |
||
5681 | } |
||
597 | daniel-mar | 5682 | return config; |
5683 | } |
||
846 | daniel-mar | 5684 | _maybeEnableSmoothScroll() { |
5685 | if (!this._config.smoothScroll) { |
||
5686 | return; |
||
1056 | daniel-mar | 5687 | } |
597 | daniel-mar | 5688 | |
1056 | daniel-mar | 5689 | // unregister any previous listeners |
846 | daniel-mar | 5690 | EventHandler.off(this._config.target, EVENT_CLICK); |
5691 | EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => { |
||
5692 | const observableSection = this._observableSections.get(event.target.hash); |
||
5693 | if (observableSection) { |
||
5694 | event.preventDefault(); |
||
5695 | const root = this._rootElement || window; |
||
5696 | const height = observableSection.offsetTop - this._element.offsetTop; |
||
5697 | if (root.scrollTo) { |
||
5698 | root.scrollTo({ |
||
922 | daniel-mar | 5699 | top: height, |
5700 | behavior: 'smooth' |
||
846 | daniel-mar | 5701 | }); |
5702 | return; |
||
1056 | daniel-mar | 5703 | } |
846 | daniel-mar | 5704 | |
1056 | daniel-mar | 5705 | // Chrome 60 doesn't support `scrollTo` |
846 | daniel-mar | 5706 | root.scrollTop = height; |
5707 | } |
||
5708 | }); |
||
597 | daniel-mar | 5709 | } |
846 | daniel-mar | 5710 | _getNewObserver() { |
5711 | const options = { |
||
5712 | root: this._rootElement, |
||
931 | daniel-mar | 5713 | threshold: this._config.threshold, |
5714 | rootMargin: this._config.rootMargin |
||
846 | daniel-mar | 5715 | }; |
5716 | return new IntersectionObserver(entries => this._observerCallback(entries), options); |
||
1056 | daniel-mar | 5717 | } |
597 | daniel-mar | 5718 | |
1056 | daniel-mar | 5719 | // The logic of selection |
846 | daniel-mar | 5720 | _observerCallback(entries) { |
5721 | const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`); |
||
5722 | const activate = entry => { |
||
5723 | this._previousScrollData.visibleEntryTop = entry.target.offsetTop; |
||
5724 | this._process(targetElement(entry)); |
||
5725 | }; |
||
5726 | const parentScrollTop = (this._rootElement || document.documentElement).scrollTop; |
||
5727 | const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop; |
||
5728 | this._previousScrollData.parentScrollTop = parentScrollTop; |
||
5729 | for (const entry of entries) { |
||
5730 | if (!entry.isIntersecting) { |
||
5731 | this._activeTarget = null; |
||
5732 | this._clearActiveClass(targetElement(entry)); |
||
5733 | continue; |
||
597 | daniel-mar | 5734 | } |
1056 | daniel-mar | 5735 | const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop; |
5736 | // if we are scrolling down, pick the bigger offsetTop |
||
846 | daniel-mar | 5737 | if (userScrollsDown && entryIsLowerThanPrevious) { |
1056 | daniel-mar | 5738 | activate(entry); |
5739 | // if parent isn't scrolled, let's keep the first visible item, breaking the iteration |
||
846 | daniel-mar | 5740 | if (!parentScrollTop) { |
5741 | return; |
||
5742 | } |
||
5743 | continue; |
||
1056 | daniel-mar | 5744 | } |
597 | daniel-mar | 5745 | |
1056 | daniel-mar | 5746 | // if we are scrolling up, pick the smallest offsetTop |
846 | daniel-mar | 5747 | if (!userScrollsDown && !entryIsLowerThanPrevious) { |
5748 | activate(entry); |
||
597 | daniel-mar | 5749 | } |
5750 | } |
||
5751 | } |
||
846 | daniel-mar | 5752 | _initializeTargetsAndObservables() { |
5753 | this._targetLinks = new Map(); |
||
5754 | this._observableSections = new Map(); |
||
5755 | const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target); |
||
5756 | for (const anchor of targetLinks) { |
||
5757 | // ensure that the anchor has an id and is not disabled |
||
5758 | if (!anchor.hash || isDisabled(anchor)) { |
||
5759 | continue; |
||
5760 | } |
||
1308 | daniel-mar | 5761 | const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element); |
597 | daniel-mar | 5762 | |
1056 | daniel-mar | 5763 | // ensure that the observableSection exists & is visible |
846 | daniel-mar | 5764 | if (isVisible(observableSection)) { |
1308 | daniel-mar | 5765 | this._targetLinks.set(decodeURI(anchor.hash), anchor); |
846 | daniel-mar | 5766 | this._observableSections.set(anchor.hash, observableSection); |
5767 | } |
||
597 | daniel-mar | 5768 | } |
846 | daniel-mar | 5769 | } |
5770 | _process(target) { |
||
5771 | if (this._activeTarget === target) { |
||
5772 | return; |
||
5773 | } |
||
5774 | this._clearActiveClass(this._config.target); |
||
5775 | this._activeTarget = target; |
||
5776 | target.classList.add(CLASS_NAME_ACTIVE$1); |
||
5777 | this._activateParents(target); |
||
5778 | EventHandler.trigger(this._element, EVENT_ACTIVATE, { |
||
597 | daniel-mar | 5779 | relatedTarget: target |
5780 | }); |
||
5781 | } |
||
846 | daniel-mar | 5782 | _activateParents(target) { |
5783 | // Activate dropdown parents |
||
5784 | if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { |
||
5785 | SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE$1); |
||
5786 | return; |
||
5787 | } |
||
5788 | for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) { |
||
5789 | // Set triggered links parents as active |
||
5790 | // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor |
||
5791 | for (const item of SelectorEngine.prev(listGroup, SELECTOR_LINK_ITEMS)) { |
||
5792 | item.classList.add(CLASS_NAME_ACTIVE$1); |
||
5793 | } |
||
5794 | } |
||
5795 | } |
||
5796 | _clearActiveClass(parent) { |
||
5797 | parent.classList.remove(CLASS_NAME_ACTIVE$1); |
||
5798 | const activeNodes = SelectorEngine.find(`${SELECTOR_TARGET_LINKS}.${CLASS_NAME_ACTIVE$1}`, parent); |
||
5799 | for (const node of activeNodes) { |
||
5800 | node.classList.remove(CLASS_NAME_ACTIVE$1); |
||
5801 | } |
||
1056 | daniel-mar | 5802 | } |
597 | daniel-mar | 5803 | |
1056 | daniel-mar | 5804 | // Static |
597 | daniel-mar | 5805 | static jQueryInterface(config) { |
5806 | return this.each(function () { |
||
637 | daniel-mar | 5807 | const data = ScrollSpy.getOrCreateInstance(this, config); |
597 | daniel-mar | 5808 | if (typeof config !== 'string') { |
5809 | return; |
||
5810 | } |
||
846 | daniel-mar | 5811 | if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { |
597 | daniel-mar | 5812 | throw new TypeError(`No method named "${config}"`); |
5813 | } |
||
5814 | data[config](); |
||
5815 | }); |
||
5816 | } |
||
1056 | daniel-mar | 5817 | } |
597 | daniel-mar | 5818 | |
5819 | /** |
||
846 | daniel-mar | 5820 | * Data API implementation |
597 | daniel-mar | 5821 | */ |
5822 | |||
846 | daniel-mar | 5823 | EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => { |
5824 | for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) { |
||
5825 | ScrollSpy.getOrCreateInstance(spy); |
||
5826 | } |
||
597 | daniel-mar | 5827 | }); |
1056 | daniel-mar | 5828 | |
597 | daniel-mar | 5829 | /** |
5830 | * jQuery |
||
5831 | */ |
||
5832 | |||
5833 | defineJQueryPlugin(ScrollSpy); |
||
5834 | |||
5835 | /** |
||
5836 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 5837 | * Bootstrap tab.js |
597 | daniel-mar | 5838 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
5839 | * -------------------------------------------------------------------------- |
||
5840 | */ |
||
1056 | daniel-mar | 5841 | |
1308 | daniel-mar | 5842 | |
597 | daniel-mar | 5843 | /** |
5844 | * Constants |
||
5845 | */ |
||
5846 | |||
5847 | const NAME$1 = 'tab'; |
||
5848 | const DATA_KEY$1 = 'bs.tab'; |
||
5849 | const EVENT_KEY$1 = `.${DATA_KEY$1}`; |
||
5850 | const EVENT_HIDE$1 = `hide${EVENT_KEY$1}`; |
||
5851 | const EVENT_HIDDEN$1 = `hidden${EVENT_KEY$1}`; |
||
5852 | const EVENT_SHOW$1 = `show${EVENT_KEY$1}`; |
||
5853 | const EVENT_SHOWN$1 = `shown${EVENT_KEY$1}`; |
||
846 | daniel-mar | 5854 | const EVENT_CLICK_DATA_API = `click${EVENT_KEY$1}`; |
5855 | const EVENT_KEYDOWN = `keydown${EVENT_KEY$1}`; |
||
5856 | const EVENT_LOAD_DATA_API = `load${EVENT_KEY$1}`; |
||
5857 | const ARROW_LEFT_KEY = 'ArrowLeft'; |
||
5858 | const ARROW_RIGHT_KEY = 'ArrowRight'; |
||
5859 | const ARROW_UP_KEY = 'ArrowUp'; |
||
5860 | const ARROW_DOWN_KEY = 'ArrowDown'; |
||
597 | daniel-mar | 5861 | const CLASS_NAME_ACTIVE = 'active'; |
5862 | const CLASS_NAME_FADE$1 = 'fade'; |
||
5863 | const CLASS_NAME_SHOW$1 = 'show'; |
||
846 | daniel-mar | 5864 | const CLASS_DROPDOWN = 'dropdown'; |
597 | daniel-mar | 5865 | const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'; |
846 | daniel-mar | 5866 | const SELECTOR_DROPDOWN_MENU = '.dropdown-menu'; |
5867 | const NOT_SELECTOR_DROPDOWN_TOGGLE = ':not(.dropdown-toggle)'; |
||
5868 | const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]'; |
||
5869 | const SELECTOR_OUTER = '.nav-item, .list-group-item'; |
||
5870 | const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`; |
||
1151 | daniel-mar | 5871 | const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]'; // TODO: could only be `tab` in v6 |
846 | daniel-mar | 5872 | const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`; |
5873 | const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="pill"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="list"]`; |
||
1056 | daniel-mar | 5874 | |
597 | daniel-mar | 5875 | /** |
846 | daniel-mar | 5876 | * Class definition |
597 | daniel-mar | 5877 | */ |
5878 | |||
5879 | class Tab extends BaseComponent { |
||
846 | daniel-mar | 5880 | constructor(element) { |
5881 | super(element); |
||
5882 | this._parent = this._element.closest(SELECTOR_TAB_PANEL); |
||
5883 | if (!this._parent) { |
||
1056 | daniel-mar | 5884 | return; |
1151 | daniel-mar | 5885 | // TODO: should throw exception in v6 |
846 | daniel-mar | 5886 | // throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`) |
1056 | daniel-mar | 5887 | } |
846 | daniel-mar | 5888 | |
1056 | daniel-mar | 5889 | // Set up initial aria attributes |
846 | daniel-mar | 5890 | this._setInitialAttributes(this._parent, this._getChildren()); |
5891 | EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event)); |
||
1056 | daniel-mar | 5892 | } |
846 | daniel-mar | 5893 | |
1056 | daniel-mar | 5894 | // Getters |
597 | daniel-mar | 5895 | static get NAME() { |
5896 | return NAME$1; |
||
1056 | daniel-mar | 5897 | } |
597 | daniel-mar | 5898 | |
1056 | daniel-mar | 5899 | // Public |
597 | daniel-mar | 5900 | show() { |
846 | daniel-mar | 5901 | // Shows this elem and deactivate the active sibling if exists |
5902 | const innerElem = this._element; |
||
5903 | if (this._elemIsActive(innerElem)) { |
||
597 | daniel-mar | 5904 | return; |
1056 | daniel-mar | 5905 | } |
846 | daniel-mar | 5906 | |
1056 | daniel-mar | 5907 | // Search for active tab on same parent to deactivate it |
846 | daniel-mar | 5908 | const active = this._getActiveElem(); |
5909 | const hideEvent = active ? EventHandler.trigger(active, EVENT_HIDE$1, { |
||
5910 | relatedTarget: innerElem |
||
5911 | }) : null; |
||
5912 | const showEvent = EventHandler.trigger(innerElem, EVENT_SHOW$1, { |
||
5913 | relatedTarget: active |
||
5914 | }); |
||
5915 | if (showEvent.defaultPrevented || hideEvent && hideEvent.defaultPrevented) { |
||
5916 | return; |
||
597 | daniel-mar | 5917 | } |
846 | daniel-mar | 5918 | this._deactivate(active, innerElem); |
5919 | this._activate(innerElem, active); |
||
1056 | daniel-mar | 5920 | } |
597 | daniel-mar | 5921 | |
1056 | daniel-mar | 5922 | // Private |
846 | daniel-mar | 5923 | _activate(element, relatedElem) { |
5924 | if (!element) { |
||
5925 | return; |
||
597 | daniel-mar | 5926 | } |
846 | daniel-mar | 5927 | element.classList.add(CLASS_NAME_ACTIVE); |
1056 | daniel-mar | 5928 | this._activate(SelectorEngine.getElementFromSelector(element)); // Search and activate/show the proper section |
597 | daniel-mar | 5929 | |
846 | daniel-mar | 5930 | const complete = () => { |
922 | daniel-mar | 5931 | if (element.getAttribute('role') !== 'tab') { |
846 | daniel-mar | 5932 | element.classList.add(CLASS_NAME_SHOW$1); |
5933 | return; |
||
5934 | } |
||
5935 | element.removeAttribute('tabindex'); |
||
5936 | element.setAttribute('aria-selected', true); |
||
5937 | this._toggleDropDown(element, true); |
||
5938 | EventHandler.trigger(element, EVENT_SHOWN$1, { |
||
5939 | relatedTarget: relatedElem |
||
5940 | }); |
||
5941 | }; |
||
922 | daniel-mar | 5942 | this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE$1)); |
846 | daniel-mar | 5943 | } |
5944 | _deactivate(element, relatedElem) { |
||
5945 | if (!element) { |
||
597 | daniel-mar | 5946 | return; |
5947 | } |
||
846 | daniel-mar | 5948 | element.classList.remove(CLASS_NAME_ACTIVE); |
5949 | element.blur(); |
||
1056 | daniel-mar | 5950 | this._deactivate(SelectorEngine.getElementFromSelector(element)); // Search and deactivate the shown section too |
597 | daniel-mar | 5951 | |
5952 | const complete = () => { |
||
922 | daniel-mar | 5953 | if (element.getAttribute('role') !== 'tab') { |
846 | daniel-mar | 5954 | element.classList.remove(CLASS_NAME_SHOW$1); |
5955 | return; |
||
5956 | } |
||
5957 | element.setAttribute('aria-selected', false); |
||
5958 | element.setAttribute('tabindex', '-1'); |
||
5959 | this._toggleDropDown(element, false); |
||
5960 | EventHandler.trigger(element, EVENT_HIDDEN$1, { |
||
5961 | relatedTarget: relatedElem |
||
597 | daniel-mar | 5962 | }); |
5963 | }; |
||
922 | daniel-mar | 5964 | this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE$1)); |
846 | daniel-mar | 5965 | } |
5966 | _keydown(event) { |
||
5967 | if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { |
||
5968 | return; |
||
597 | daniel-mar | 5969 | } |
846 | daniel-mar | 5970 | event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page |
5971 | event.preventDefault(); |
||
5972 | const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key); |
||
5973 | const nextActiveElement = getNextActiveElement(this._getChildren().filter(element => !isDisabled(element)), event.target, isNext, true); |
||
5974 | if (nextActiveElement) { |
||
981 | daniel-mar | 5975 | nextActiveElement.focus({ |
5976 | preventScroll: true |
||
5977 | }); |
||
846 | daniel-mar | 5978 | Tab.getOrCreateInstance(nextActiveElement).show(); |
5979 | } |
||
5980 | } |
||
5981 | _getChildren() { |
||
5982 | // collection of inner elements |
||
5983 | return SelectorEngine.find(SELECTOR_INNER_ELEM, this._parent); |
||
5984 | } |
||
5985 | _getActiveElem() { |
||
5986 | return this._getChildren().find(child => this._elemIsActive(child)) || null; |
||
5987 | } |
||
5988 | _setInitialAttributes(parent, children) { |
||
5989 | this._setAttributeIfNotExists(parent, 'role', 'tablist'); |
||
5990 | for (const child of children) { |
||
5991 | this._setInitialAttributesOnChild(child); |
||
597 | daniel-mar | 5992 | } |
5993 | } |
||
846 | daniel-mar | 5994 | _setInitialAttributesOnChild(child) { |
5995 | child = this._getInnerElement(child); |
||
5996 | const isActive = this._elemIsActive(child); |
||
5997 | const outerElem = this._getOuterElement(child); |
||
5998 | child.setAttribute('aria-selected', isActive); |
||
5999 | if (outerElem !== child) { |
||
6000 | this._setAttributeIfNotExists(outerElem, 'role', 'presentation'); |
||
597 | daniel-mar | 6001 | } |
846 | daniel-mar | 6002 | if (!isActive) { |
6003 | child.setAttribute('tabindex', '-1'); |
||
6004 | } |
||
1056 | daniel-mar | 6005 | this._setAttributeIfNotExists(child, 'role', 'tab'); |
597 | daniel-mar | 6006 | |
1056 | daniel-mar | 6007 | // set attributes to the related panel too |
846 | daniel-mar | 6008 | this._setInitialAttributesOnTargetPanel(child); |
6009 | } |
||
6010 | _setInitialAttributesOnTargetPanel(child) { |
||
1056 | daniel-mar | 6011 | const target = SelectorEngine.getElementFromSelector(child); |
846 | daniel-mar | 6012 | if (!target) { |
6013 | return; |
||
597 | daniel-mar | 6014 | } |
846 | daniel-mar | 6015 | this._setAttributeIfNotExists(target, 'role', 'tabpanel'); |
6016 | if (child.id) { |
||
1134 | daniel-mar | 6017 | this._setAttributeIfNotExists(target, 'aria-labelledby', `${child.id}`); |
597 | daniel-mar | 6018 | } |
846 | daniel-mar | 6019 | } |
6020 | _toggleDropDown(element, open) { |
||
6021 | const outerElem = this._getOuterElement(element); |
||
6022 | if (!outerElem.classList.contains(CLASS_DROPDOWN)) { |
||
6023 | return; |
||
597 | daniel-mar | 6024 | } |
846 | daniel-mar | 6025 | const toggle = (selector, className) => { |
6026 | const element = SelectorEngine.findOne(selector, outerElem); |
||
6027 | if (element) { |
||
6028 | element.classList.toggle(className, open); |
||
597 | daniel-mar | 6029 | } |
846 | daniel-mar | 6030 | }; |
6031 | toggle(SELECTOR_DROPDOWN_TOGGLE, CLASS_NAME_ACTIVE); |
||
6032 | toggle(SELECTOR_DROPDOWN_MENU, CLASS_NAME_SHOW$1); |
||
6033 | outerElem.setAttribute('aria-expanded', open); |
||
6034 | } |
||
6035 | _setAttributeIfNotExists(element, attribute, value) { |
||
6036 | if (!element.hasAttribute(attribute)) { |
||
6037 | element.setAttribute(attribute, value); |
||
597 | daniel-mar | 6038 | } |
846 | daniel-mar | 6039 | } |
6040 | _elemIsActive(elem) { |
||
6041 | return elem.classList.contains(CLASS_NAME_ACTIVE); |
||
1056 | daniel-mar | 6042 | } |
846 | daniel-mar | 6043 | |
1056 | daniel-mar | 6044 | // Try to get the inner element (usually the .nav-link) |
846 | daniel-mar | 6045 | _getInnerElement(elem) { |
6046 | return elem.matches(SELECTOR_INNER_ELEM) ? elem : SelectorEngine.findOne(SELECTOR_INNER_ELEM, elem); |
||
1056 | daniel-mar | 6047 | } |
846 | daniel-mar | 6048 | |
1056 | daniel-mar | 6049 | // Try to get the outer element (usually the .nav-item) |
846 | daniel-mar | 6050 | _getOuterElement(elem) { |
6051 | return elem.closest(SELECTOR_OUTER) || elem; |
||
1056 | daniel-mar | 6052 | } |
597 | daniel-mar | 6053 | |
1056 | daniel-mar | 6054 | // Static |
597 | daniel-mar | 6055 | static jQueryInterface(config) { |
6056 | return this.each(function () { |
||
637 | daniel-mar | 6057 | const data = Tab.getOrCreateInstance(this); |
846 | daniel-mar | 6058 | if (typeof config !== 'string') { |
6059 | return; |
||
6060 | } |
||
6061 | if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { |
||
6062 | throw new TypeError(`No method named "${config}"`); |
||
597 | daniel-mar | 6063 | } |
846 | daniel-mar | 6064 | data[config](); |
597 | daniel-mar | 6065 | }); |
6066 | } |
||
1056 | daniel-mar | 6067 | } |
597 | daniel-mar | 6068 | |
6069 | /** |
||
846 | daniel-mar | 6070 | * Data API implementation |
597 | daniel-mar | 6071 | */ |
6072 | |||
6073 | EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { |
||
6074 | if (['A', 'AREA'].includes(this.tagName)) { |
||
6075 | event.preventDefault(); |
||
6076 | } |
||
6077 | if (isDisabled(this)) { |
||
6078 | return; |
||
6079 | } |
||
846 | daniel-mar | 6080 | Tab.getOrCreateInstance(this).show(); |
597 | daniel-mar | 6081 | }); |
1056 | daniel-mar | 6082 | |
597 | daniel-mar | 6083 | /** |
846 | daniel-mar | 6084 | * Initialize on focus |
6085 | */ |
||
6086 | EventHandler.on(window, EVENT_LOAD_DATA_API, () => { |
||
6087 | for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE_ACTIVE)) { |
||
6088 | Tab.getOrCreateInstance(element); |
||
6089 | } |
||
6090 | }); |
||
6091 | /** |
||
597 | daniel-mar | 6092 | * jQuery |
6093 | */ |
||
6094 | |||
6095 | defineJQueryPlugin(Tab); |
||
6096 | |||
6097 | /** |
||
6098 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 6099 | * Bootstrap toast.js |
597 | daniel-mar | 6100 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
6101 | * -------------------------------------------------------------------------- |
||
6102 | */ |
||
1056 | daniel-mar | 6103 | |
1308 | daniel-mar | 6104 | |
597 | daniel-mar | 6105 | /** |
6106 | * Constants |
||
6107 | */ |
||
6108 | |||
6109 | const NAME = 'toast'; |
||
6110 | const DATA_KEY = 'bs.toast'; |
||
6111 | const EVENT_KEY = `.${DATA_KEY}`; |
||
6112 | const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`; |
||
6113 | const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`; |
||
6114 | const EVENT_FOCUSIN = `focusin${EVENT_KEY}`; |
||
6115 | const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`; |
||
6116 | const EVENT_HIDE = `hide${EVENT_KEY}`; |
||
6117 | const EVENT_HIDDEN = `hidden${EVENT_KEY}`; |
||
6118 | const EVENT_SHOW = `show${EVENT_KEY}`; |
||
6119 | const EVENT_SHOWN = `shown${EVENT_KEY}`; |
||
6120 | const CLASS_NAME_FADE = 'fade'; |
||
637 | daniel-mar | 6121 | const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility |
597 | daniel-mar | 6122 | const CLASS_NAME_SHOW = 'show'; |
6123 | const CLASS_NAME_SHOWING = 'showing'; |
||
6124 | const DefaultType = { |
||
6125 | animation: 'boolean', |
||
6126 | autohide: 'boolean', |
||
6127 | delay: 'number' |
||
6128 | }; |
||
6129 | const Default = { |
||
6130 | animation: true, |
||
6131 | autohide: true, |
||
6132 | delay: 5000 |
||
6133 | }; |
||
1056 | daniel-mar | 6134 | |
597 | daniel-mar | 6135 | /** |
846 | daniel-mar | 6136 | * Class definition |
597 | daniel-mar | 6137 | */ |
6138 | |||
6139 | class Toast extends BaseComponent { |
||
6140 | constructor(element, config) { |
||
846 | daniel-mar | 6141 | super(element, config); |
597 | daniel-mar | 6142 | this._timeout = null; |
6143 | this._hasMouseInteraction = false; |
||
6144 | this._hasKeyboardInteraction = false; |
||
6145 | this._setListeners(); |
||
1056 | daniel-mar | 6146 | } |
597 | daniel-mar | 6147 | |
1056 | daniel-mar | 6148 | // Getters |
846 | daniel-mar | 6149 | static get Default() { |
6150 | return Default; |
||
6151 | } |
||
597 | daniel-mar | 6152 | static get DefaultType() { |
6153 | return DefaultType; |
||
6154 | } |
||
6155 | static get NAME() { |
||
6156 | return NAME; |
||
1056 | daniel-mar | 6157 | } |
597 | daniel-mar | 6158 | |
1056 | daniel-mar | 6159 | // Public |
597 | daniel-mar | 6160 | show() { |
6161 | const showEvent = EventHandler.trigger(this._element, EVENT_SHOW); |
||
6162 | if (showEvent.defaultPrevented) { |
||
6163 | return; |
||
6164 | } |
||
6165 | this._clearTimeout(); |
||
6166 | if (this._config.animation) { |
||
6167 | this._element.classList.add(CLASS_NAME_FADE); |
||
6168 | } |
||
6169 | const complete = () => { |
||
6170 | this._element.classList.remove(CLASS_NAME_SHOWING); |
||
6171 | EventHandler.trigger(this._element, EVENT_SHOWN); |
||
6172 | this._maybeScheduleHide(); |
||
6173 | }; |
||
637 | daniel-mar | 6174 | this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated |
597 | daniel-mar | 6175 | reflow(this._element); |
846 | daniel-mar | 6176 | this._element.classList.add(CLASS_NAME_SHOW, CLASS_NAME_SHOWING); |
597 | daniel-mar | 6177 | this._queueCallback(complete, this._element, this._config.animation); |
6178 | } |
||
6179 | hide() { |
||
846 | daniel-mar | 6180 | if (!this.isShown()) { |
597 | daniel-mar | 6181 | return; |
6182 | } |
||
6183 | const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE); |
||
6184 | if (hideEvent.defaultPrevented) { |
||
6185 | return; |
||
6186 | } |
||
6187 | const complete = () => { |
||
637 | daniel-mar | 6188 | this._element.classList.add(CLASS_NAME_HIDE); // @deprecated |
846 | daniel-mar | 6189 | this._element.classList.remove(CLASS_NAME_SHOWING, CLASS_NAME_SHOW); |
597 | daniel-mar | 6190 | EventHandler.trigger(this._element, EVENT_HIDDEN); |
6191 | }; |
||
637 | daniel-mar | 6192 | this._element.classList.add(CLASS_NAME_SHOWING); |
597 | daniel-mar | 6193 | this._queueCallback(complete, this._element, this._config.animation); |
6194 | } |
||
6195 | dispose() { |
||
6196 | this._clearTimeout(); |
||
846 | daniel-mar | 6197 | if (this.isShown()) { |
597 | daniel-mar | 6198 | this._element.classList.remove(CLASS_NAME_SHOW); |
6199 | } |
||
6200 | super.dispose(); |
||
846 | daniel-mar | 6201 | } |
6202 | isShown() { |
||
6203 | return this._element.classList.contains(CLASS_NAME_SHOW); |
||
1056 | daniel-mar | 6204 | } |
597 | daniel-mar | 6205 | |
1056 | daniel-mar | 6206 | // Private |
597 | daniel-mar | 6207 | |
6208 | _maybeScheduleHide() { |
||
6209 | if (!this._config.autohide) { |
||
6210 | return; |
||
6211 | } |
||
6212 | if (this._hasMouseInteraction || this._hasKeyboardInteraction) { |
||
6213 | return; |
||
6214 | } |
||
6215 | this._timeout = setTimeout(() => { |
||
6216 | this.hide(); |
||
6217 | }, this._config.delay); |
||
6218 | } |
||
6219 | _onInteraction(event, isInteracting) { |
||
6220 | switch (event.type) { |
||
6221 | case 'mouseover': |
||
6222 | case 'mouseout': |
||
981 | daniel-mar | 6223 | { |
6224 | this._hasMouseInteraction = isInteracting; |
||
6225 | break; |
||
6226 | } |
||
597 | daniel-mar | 6227 | case 'focusin': |
6228 | case 'focusout': |
||
981 | daniel-mar | 6229 | { |
6230 | this._hasKeyboardInteraction = isInteracting; |
||
6231 | break; |
||
6232 | } |
||
597 | daniel-mar | 6233 | } |
6234 | if (isInteracting) { |
||
6235 | this._clearTimeout(); |
||
6236 | return; |
||
6237 | } |
||
6238 | const nextElement = event.relatedTarget; |
||
6239 | if (this._element === nextElement || this._element.contains(nextElement)) { |
||
6240 | return; |
||
6241 | } |
||
6242 | this._maybeScheduleHide(); |
||
6243 | } |
||
6244 | _setListeners() { |
||
6245 | EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true)); |
||
6246 | EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false)); |
||
6247 | EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true)); |
||
6248 | EventHandler.on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false)); |
||
6249 | } |
||
6250 | _clearTimeout() { |
||
6251 | clearTimeout(this._timeout); |
||
6252 | this._timeout = null; |
||
1056 | daniel-mar | 6253 | } |
597 | daniel-mar | 6254 | |
1056 | daniel-mar | 6255 | // Static |
597 | daniel-mar | 6256 | static jQueryInterface(config) { |
6257 | return this.each(function () { |
||
637 | daniel-mar | 6258 | const data = Toast.getOrCreateInstance(this, config); |
597 | daniel-mar | 6259 | if (typeof config === 'string') { |
6260 | if (typeof data[config] === 'undefined') { |
||
6261 | throw new TypeError(`No method named "${config}"`); |
||
6262 | } |
||
6263 | data[config](this); |
||
6264 | } |
||
6265 | }); |
||
6266 | } |
||
1056 | daniel-mar | 6267 | } |
597 | daniel-mar | 6268 | |
846 | daniel-mar | 6269 | /** |
6270 | * Data API implementation |
||
6271 | */ |
||
637 | daniel-mar | 6272 | |
1056 | daniel-mar | 6273 | enableDismissTrigger(Toast); |
846 | daniel-mar | 6274 | |
597 | daniel-mar | 6275 | /** |
6276 | * jQuery |
||
6277 | */ |
||
6278 | |||
6279 | defineJQueryPlugin(Toast); |
||
6280 | |||
6281 | /** |
||
6282 | * -------------------------------------------------------------------------- |
||
1134 | daniel-mar | 6283 | * Bootstrap index.umd.js |
597 | daniel-mar | 6284 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
6285 | * -------------------------------------------------------------------------- |
||
6286 | */ |
||
1308 | daniel-mar | 6287 | |
679 | daniel-mar | 6288 | const index_umd = { |
597 | daniel-mar | 6289 | Alert, |
6290 | Button, |
||
6291 | Carousel, |
||
6292 | Collapse, |
||
6293 | Dropdown, |
||
6294 | Modal, |
||
6295 | Offcanvas, |
||
6296 | Popover, |
||
6297 | ScrollSpy, |
||
6298 | Tab, |
||
6299 | Toast, |
||
6300 | Tooltip |
||
6301 | }; |
||
6302 | |||
6303 | return index_umd; |
||
6304 | |||
679 | daniel-mar | 6305 | })); |
597 | daniel-mar | 6306 | //# sourceMappingURL=bootstrap.bundle.js.map |