source: imaps-frontend/node_modules/bootstrap/js/src/util/index.js@ d565449

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

Update repo after prototype presentation

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/**
2 * --------------------------------------------------------------------------
3 * Bootstrap util/index.js
4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5 * --------------------------------------------------------------------------
6 */
7
8const MAX_UID = 1_000_000
9const MILLISECONDS_MULTIPLIER = 1000
10const TRANSITION_END = 'transitionend'
11
12/**
13 * Properly escape IDs selectors to handle weird IDs
14 * @param {string} selector
15 * @returns {string}
16 */
17const parseSelector = selector => {
18 if (selector && window.CSS && window.CSS.escape) {
19 // document.querySelector needs escaping to handle IDs (html5+) containing for instance /
20 selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`)
21 }
22
23 return selector
24}
25
26// Shout-out Angus Croll (https://goo.gl/pxwQGp)
27const toType = object => {
28 if (object === null || object === undefined) {
29 return `${object}`
30 }
31
32 return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase()
33}
34
35/**
36 * Public Util API
37 */
38
39const getUID = prefix => {
40 do {
41 prefix += Math.floor(Math.random() * MAX_UID)
42 } while (document.getElementById(prefix))
43
44 return prefix
45}
46
47const getTransitionDurationFromElement = element => {
48 if (!element) {
49 return 0
50 }
51
52 // Get transition-duration of the element
53 let { transitionDuration, transitionDelay } = window.getComputedStyle(element)
54
55 const floatTransitionDuration = Number.parseFloat(transitionDuration)
56 const floatTransitionDelay = Number.parseFloat(transitionDelay)
57
58 // Return 0 if element or transition duration is not found
59 if (!floatTransitionDuration && !floatTransitionDelay) {
60 return 0
61 }
62
63 // If multiple durations are defined, take the first
64 transitionDuration = transitionDuration.split(',')[0]
65 transitionDelay = transitionDelay.split(',')[0]
66
67 return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
68}
69
70const triggerTransitionEnd = element => {
71 element.dispatchEvent(new Event(TRANSITION_END))
72}
73
74const isElement = object => {
75 if (!object || typeof object !== 'object') {
76 return false
77 }
78
79 if (typeof object.jquery !== 'undefined') {
80 object = object[0]
81 }
82
83 return typeof object.nodeType !== 'undefined'
84}
85
86const getElement = object => {
87 // it's a jQuery object or a node element
88 if (isElement(object)) {
89 return object.jquery ? object[0] : object
90 }
91
92 if (typeof object === 'string' && object.length > 0) {
93 return document.querySelector(parseSelector(object))
94 }
95
96 return null
97}
98
99const isVisible = element => {
100 if (!isElement(element) || element.getClientRects().length === 0) {
101 return false
102 }
103
104 const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'
105 // Handle `details` element as its content may falsie appear visible when it is closed
106 const closedDetails = element.closest('details:not([open])')
107
108 if (!closedDetails) {
109 return elementIsVisible
110 }
111
112 if (closedDetails !== element) {
113 const summary = element.closest('summary')
114 if (summary && summary.parentNode !== closedDetails) {
115 return false
116 }
117
118 if (summary === null) {
119 return false
120 }
121 }
122
123 return elementIsVisible
124}
125
126const isDisabled = element => {
127 if (!element || element.nodeType !== Node.ELEMENT_NODE) {
128 return true
129 }
130
131 if (element.classList.contains('disabled')) {
132 return true
133 }
134
135 if (typeof element.disabled !== 'undefined') {
136 return element.disabled
137 }
138
139 return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'
140}
141
142const findShadowRoot = element => {
143 if (!document.documentElement.attachShadow) {
144 return null
145 }
146
147 // Can find the shadow root otherwise it'll return the document
148 if (typeof element.getRootNode === 'function') {
149 const root = element.getRootNode()
150 return root instanceof ShadowRoot ? root : null
151 }
152
153 if (element instanceof ShadowRoot) {
154 return element
155 }
156
157 // when we don't find a shadow root
158 if (!element.parentNode) {
159 return null
160 }
161
162 return findShadowRoot(element.parentNode)
163}
164
165const noop = () => {}
166
167/**
168 * Trick to restart an element's animation
169 *
170 * @param {HTMLElement} element
171 * @return void
172 *
173 * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
174 */
175const reflow = element => {
176 element.offsetHeight // eslint-disable-line no-unused-expressions
177}
178
179const getjQuery = () => {
180 if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
181 return window.jQuery
182 }
183
184 return null
185}
186
187const DOMContentLoadedCallbacks = []
188
189const onDOMContentLoaded = callback => {
190 if (document.readyState === 'loading') {
191 // add listener on the first call when the document is in loading state
192 if (!DOMContentLoadedCallbacks.length) {
193 document.addEventListener('DOMContentLoaded', () => {
194 for (const callback of DOMContentLoadedCallbacks) {
195 callback()
196 }
197 })
198 }
199
200 DOMContentLoadedCallbacks.push(callback)
201 } else {
202 callback()
203 }
204}
205
206const isRTL = () => document.documentElement.dir === 'rtl'
207
208const defineJQueryPlugin = plugin => {
209 onDOMContentLoaded(() => {
210 const $ = getjQuery()
211 /* istanbul ignore if */
212 if ($) {
213 const name = plugin.NAME
214 const JQUERY_NO_CONFLICT = $.fn[name]
215 $.fn[name] = plugin.jQueryInterface
216 $.fn[name].Constructor = plugin
217 $.fn[name].noConflict = () => {
218 $.fn[name] = JQUERY_NO_CONFLICT
219 return plugin.jQueryInterface
220 }
221 }
222 })
223}
224
225const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
226 return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue
227}
228
229const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
230 if (!waitForTransition) {
231 execute(callback)
232 return
233 }
234
235 const durationPadding = 5
236 const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding
237
238 let called = false
239
240 const handler = ({ target }) => {
241 if (target !== transitionElement) {
242 return
243 }
244
245 called = true
246 transitionElement.removeEventListener(TRANSITION_END, handler)
247 execute(callback)
248 }
249
250 transitionElement.addEventListener(TRANSITION_END, handler)
251 setTimeout(() => {
252 if (!called) {
253 triggerTransitionEnd(transitionElement)
254 }
255 }, emulatedDuration)
256}
257
258/**
259 * Return the previous/next element of a list.
260 *
261 * @param {array} list The list of elements
262 * @param activeElement The active element
263 * @param shouldGetNext Choose to get next or previous element
264 * @param isCycleAllowed
265 * @return {Element|elem} The proper element
266 */
267const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
268 const listLength = list.length
269 let index = list.indexOf(activeElement)
270
271 // if the element does not exist in the list return an element
272 // depending on the direction and if cycle is allowed
273 if (index === -1) {
274 return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]
275 }
276
277 index += shouldGetNext ? 1 : -1
278
279 if (isCycleAllowed) {
280 index = (index + listLength) % listLength
281 }
282
283 return list[Math.max(0, Math.min(index, listLength - 1))]
284}
285
286export {
287 defineJQueryPlugin,
288 execute,
289 executeAfterTransition,
290 findShadowRoot,
291 getElement,
292 getjQuery,
293 getNextActiveElement,
294 getTransitionDurationFromElement,
295 getUID,
296 isDisabled,
297 isElement,
298 isRTL,
299 isVisible,
300 noop,
301 onDOMContentLoaded,
302 parseSelector,
303 reflow,
304 triggerTransitionEnd,
305 toType
306}
Note: See TracBrowser for help on using the repository browser.