util.js 4.56 KB
Newer Older
fat's avatar
fat committed
1
2
/**
 * --------------------------------------------------------------------------
Mark Otto's avatar
Mark Otto committed
3
 * Bootstrap (v4.2.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

Johann-S's avatar
Johann-S committed
85
86
    return selector && document.querySelector(selector) ? selector : null
  },
fat's avatar
fat committed
87

Johann-S's avatar
Johann-S committed
88
89
90
91
  getTransitionDurationFromElement(element) {
    if (!element) {
      return 0
    }
92

Johann-S's avatar
Johann-S committed
93
94
    // Get transition-duration of the element
    let transitionDuration = $(element).css('transition-duration')
95
96
    let transitionDelay = $(element).css('transition-delay')

Johann-S's avatar
Johann-S committed
97
    const floatTransitionDuration = parseFloat(transitionDuration)
98
    const floatTransitionDelay = parseFloat(transitionDelay)
99

Johann-S's avatar
Johann-S committed
100
    // Return 0 if element or transition duration is not found
101
    if (!floatTransitionDuration && !floatTransitionDelay) {
Johann-S's avatar
Johann-S committed
102
103
      return 0
    }
104

Johann-S's avatar
Johann-S committed
105
106
    // If multiple durations are defined, take the first
    transitionDuration = transitionDuration.split(',')[0]
107
    transitionDelay = transitionDelay.split(',')[0]
Johann-S's avatar
Johann-S committed
108

109
    return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
Johann-S's avatar
Johann-S committed
110
111
112
113
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
  },

  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
142
143
        }
      }
144
    }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  },

  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
168
  }
Johann-S's avatar
Johann-S committed
169
}
fat's avatar
fat committed
170

Johann-S's avatar
Johann-S committed
171
setTransitionEndSupport()
172
173

export default Util