util.js 4.6 KB
Newer Older
fat's avatar
fat committed
1
2
/**
 * --------------------------------------------------------------------------
XhmikosR's avatar
XhmikosR committed
3
 * Bootstrap (v4.3.1): util.js
fat's avatar
fat committed
4
5
6
7
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

8
import $ from 'jquery'
fat's avatar
fat committed
9

Johann-S's avatar
Johann-S committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * ------------------------------------------------------------------------
 * Private TransitionEnd Helpers
 * ------------------------------------------------------------------------
 */

const TRANSITION_END = 'transitionend'
const MAX_UID = 1000000
const MILLISECONDS_MULTIPLIER = 1000

// Shoutout AngusCroll (https://goo.gl/pxwQGp)
function toType(obj) {
  return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
}

function getSpecialTransitionEndEvent() {
  return {
    bindType: TRANSITION_END,
    delegateType: TRANSITION_END,
    handle(event) {
      if ($(event.target).is(this)) {
        return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params
32
      }
Johann-S's avatar
Johann-S committed
33
      return undefined // eslint-disable-line no-undefined
34
35
    }
  }
Johann-S's avatar
Johann-S committed
36
}
fat's avatar
fat committed
37

Johann-S's avatar
Johann-S committed
38
39
function transitionEndEmulator(duration) {
  let called = false
fat's avatar
fat committed
40

Johann-S's avatar
Johann-S committed
41
42
43
  $(this).one(Util.TRANSITION_END, () => {
    called = true
  })
fat's avatar
fat committed
44

Johann-S's avatar
Johann-S committed
45
46
47
48
49
  setTimeout(() => {
    if (!called) {
      Util.triggerTransitionEnd(this)
    }
  }, duration)
fat's avatar
fat committed
50

Johann-S's avatar
Johann-S committed
51
52
  return this
}
fat's avatar
fat committed
53

Johann-S's avatar
Johann-S committed
54
55
56
57
function setTransitionEndSupport() {
  $.fn.emulateTransitionEnd = transitionEndEmulator
  $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()
}
fat's avatar
fat committed
58

Johann-S's avatar
Johann-S committed
59
60
61
62
63
/**
 * --------------------------------------------------------------------------
 * Public Util Api
 * --------------------------------------------------------------------------
 */
fat's avatar
fat committed
64

Johann-S's avatar
Johann-S committed
65
const Util = {
fat's avatar
fat committed
66

Johann-S's avatar
Johann-S committed
67
  TRANSITION_END: 'bsTransitionEnd',
68

Johann-S's avatar
Johann-S committed
69
70
71
72
73
74
75
  getUID(prefix) {
    do {
      // eslint-disable-next-line no-bitwise
      prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here
    } while (document.getElementById(prefix))
    return prefix
  },
fat's avatar
fat committed
76

Johann-S's avatar
Johann-S committed
77
78
  getSelectorFromElement(element) {
    let selector = element.getAttribute('data-target')
79

Johann-S's avatar
Johann-S committed
80
81
82
83
    if (!selector || selector === '#') {
      const hrefAttr = element.getAttribute('href')
      selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''
    }
84

85
86
87
88
89
    try {
      return document.querySelector(selector) ? selector : null
    } catch (err) {
      return null
    }
Johann-S's avatar
Johann-S committed
90
  },
fat's avatar
fat committed
91

Johann-S's avatar
Johann-S committed
92
93
94
95
  getTransitionDurationFromElement(element) {
    if (!element) {
      return 0
    }
96

Johann-S's avatar
Johann-S committed
97
98
    // Get transition-duration of the element
    let transitionDuration = $(element).css('transition-duration')
99
100
    let transitionDelay = $(element).css('transition-delay')

Johann-S's avatar
Johann-S committed
101
    const floatTransitionDuration = parseFloat(transitionDuration)
102
    const floatTransitionDelay = parseFloat(transitionDelay)
103

Johann-S's avatar
Johann-S committed
104
    // Return 0 if element or transition duration is not found
105
    if (!floatTransitionDuration && !floatTransitionDelay) {
Johann-S's avatar
Johann-S committed
106
107
      return 0
    }
108

Johann-S's avatar
Johann-S committed
109
110
    // If multiple durations are defined, take the first
    transitionDuration = transitionDuration.split(',')[0]
111
    transitionDelay = transitionDelay.split(',')[0]
Johann-S's avatar
Johann-S committed
112

113
    return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
Johann-S's avatar
Johann-S committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  },

  reflow(element) {
    return element.offsetHeight
  },

  triggerTransitionEnd(element) {
    $(element).trigger(TRANSITION_END)
  },

  // TODO: Remove in v5
  supportsTransitionEnd() {
    return Boolean(TRANSITION_END)
  },

  isElement(obj) {
    return (obj[0] || obj).nodeType
  },

  typeCheckConfig(componentName, config, configTypes) {
    for (const property in configTypes) {
      if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
        const expectedTypes = configTypes[property]
        const value         = config[property]
        const valueType     = value && Util.isElement(value)
          ? 'element' : toType(value)

        if (!new RegExp(expectedTypes).test(valueType)) {
          throw new Error(
            `${componentName.toUpperCase()}: ` +
            `Option "${property}" provided type "${valueType}" ` +
            `but expected type "${expectedTypes}".`)
fat's avatar
fat committed
146
147
        }
      }
148
    }
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  },

  findShadowRoot(element) {
    if (!document.documentElement.attachShadow) {
      return null
    }

    // Can find the shadow root otherwise it'll return the document
    if (typeof element.getRootNode === 'function') {
      const root = element.getRootNode()
      return root instanceof ShadowRoot ? root : null
    }

    if (element instanceof ShadowRoot) {
      return element
    }

    // when we don't find a shadow root
    if (!element.parentNode) {
      return null
    }

    return Util.findShadowRoot(element.parentNode)
fat's avatar
fat committed
172
  }
Johann-S's avatar
Johann-S committed
173
}
fat's avatar
fat committed
174

Johann-S's avatar
Johann-S committed
175
setTransitionEndSupport()
176
177

export default Util