util.js 4.03 KB
Newer Older
1
2
import $ from 'jquery'

fat's avatar
fat committed
3
4
/**
 * --------------------------------------------------------------------------
Mark Otto's avatar
Mark Otto committed
5
 * Bootstrap (v4.1.3): util.js
fat's avatar
fat committed
6
7
8
9
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

fat's avatar
fat committed
10

Johann-S's avatar
Johann-S committed
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * ------------------------------------------------------------------------
 * 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
33
      }
Johann-S's avatar
Johann-S committed
34
      return undefined // eslint-disable-line no-undefined
35
36
    }
  }
Johann-S's avatar
Johann-S committed
37
}
fat's avatar
fat committed
38

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

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

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

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

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

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

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

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

Johann-S's avatar
Johann-S committed
70
71
72
73
74
75
76
  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
77

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

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

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

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

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

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

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

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

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

  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
143
144
        }
      }
145
    }
fat's avatar
fat committed
146
  }
Johann-S's avatar
Johann-S committed
147
}
fat's avatar
fat committed
148

Johann-S's avatar
Johann-S committed
149
setTransitionEndSupport()
150
151

export default Util