4 * --------------------------------------------------------------------------
5 * Bootstrap (v4.1.3): util.js
6 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 * --------------------------------------------------------------------------
10 const Util = (($) => {
12 * ------------------------------------------------------------------------
13 * Private TransitionEnd Helpers
14 * ------------------------------------------------------------------------
17 const TRANSITION_END = 'transitionend'
18 const MAX_UID = 1000000
19 const MILLISECONDS_MULTIPLIER = 1000
21 // Shoutout AngusCroll (https://goo.gl/pxwQGp)
22 function toType(obj) {
23 return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
26 function getSpecialTransitionEndEvent() {
28 bindType: TRANSITION_END,
29 delegateType: TRANSITION_END,
31 if ($(event.target).is(this)) {
32 return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params
34 return undefined // eslint-disable-line no-undefined
39 function transitionEndEmulator(duration) {
42 $(this).one(Util.TRANSITION_END, () => {
48 Util.triggerTransitionEnd(this)
55 function setTransitionEndSupport() {
56 $.fn.emulateTransitionEnd = transitionEndEmulator
57 $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()
61 * --------------------------------------------------------------------------
63 * --------------------------------------------------------------------------
68 TRANSITION_END: 'bsTransitionEnd',
72 // eslint-disable-next-line no-bitwise
73 prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here
74 } while (document.getElementById(prefix))
78 getSelectorFromElement(element) {
79 let selector = element.getAttribute('data-target')
80 if (!selector || selector === '#') {
81 selector = element.getAttribute('href') || ''
85 return document.querySelector(selector) ? selector : null
91 getTransitionDurationFromElement(element) {
96 // Get transition-duration of the element
97 let transitionDuration = $(element).css('transition-duration')
98 const floatTransitionDuration = parseFloat(transitionDuration)
100 // Return 0 if element or transition duration is not found
101 if (!floatTransitionDuration) {
105 // If multiple durations are defined, take the first
106 transitionDuration = transitionDuration.split(',')[0]
108 return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER
112 return element.offsetHeight
115 triggerTransitionEnd(element) {
116 $(element).trigger(TRANSITION_END)
119 // TODO: Remove in v5
120 supportsTransitionEnd() {
121 return Boolean(TRANSITION_END)
125 return (obj[0] || obj).nodeType
128 typeCheckConfig(componentName, config, configTypes) {
129 for (const property in configTypes) {
130 if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
131 const expectedTypes = configTypes[property]
132 const value = config[property]
133 const valueType = value && Util.isElement(value)
134 ? 'element' : toType(value)
136 if (!new RegExp(expectedTypes).test(valueType)) {
138 `${componentName.toUpperCase()}: ` +
139 `Option "${property}" provided type "${valueType}" ` +
140 `but expected type "${expectedTypes}".`)
147 setTransitionEndSupport()