util.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /**
  2. * --------------------------------------------------------------------------
  3. * Bootstrap (v4.4.1): util.js
  4. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5. * --------------------------------------------------------------------------
  6. */
  7. import $ from 'jquery'
  8. /**
  9. * ------------------------------------------------------------------------
  10. * Private TransitionEnd Helpers
  11. * ------------------------------------------------------------------------
  12. */
  13. const TRANSITION_END = 'transitionend'
  14. const MAX_UID = 1000000
  15. const MILLISECONDS_MULTIPLIER = 1000
  16. // Shoutout AngusCroll (https://goo.gl/pxwQGp)
  17. function toType(obj) {
  18. return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
  19. }
  20. function getSpecialTransitionEndEvent() {
  21. return {
  22. bindType: TRANSITION_END,
  23. delegateType: TRANSITION_END,
  24. handle(event) {
  25. if ($(event.target).is(this)) {
  26. return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params
  27. }
  28. return undefined // eslint-disable-line no-undefined
  29. }
  30. }
  31. }
  32. function transitionEndEmulator(duration) {
  33. let called = false
  34. $(this).one(Util.TRANSITION_END, () => {
  35. called = true
  36. })
  37. setTimeout(() => {
  38. if (!called) {
  39. Util.triggerTransitionEnd(this)
  40. }
  41. }, duration)
  42. return this
  43. }
  44. function setTransitionEndSupport() {
  45. $.fn.emulateTransitionEnd = transitionEndEmulator
  46. $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()
  47. }
  48. /**
  49. * --------------------------------------------------------------------------
  50. * Public Util Api
  51. * --------------------------------------------------------------------------
  52. */
  53. const Util = {
  54. TRANSITION_END: 'bsTransitionEnd',
  55. getUID(prefix) {
  56. do {
  57. // eslint-disable-next-line no-bitwise
  58. prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here
  59. } while (document.getElementById(prefix))
  60. return prefix
  61. },
  62. getSelectorFromElement(element) {
  63. let selector = element.getAttribute('data-target')
  64. if (!selector || selector === '#') {
  65. const hrefAttr = element.getAttribute('href')
  66. selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''
  67. }
  68. try {
  69. return document.querySelector(selector) ? selector : null
  70. } catch (err) {
  71. return null
  72. }
  73. },
  74. getTransitionDurationFromElement(element) {
  75. if (!element) {
  76. return 0
  77. }
  78. // Get transition-duration of the element
  79. let transitionDuration = $(element).css('transition-duration')
  80. let transitionDelay = $(element).css('transition-delay')
  81. const floatTransitionDuration = parseFloat(transitionDuration)
  82. const floatTransitionDelay = parseFloat(transitionDelay)
  83. // Return 0 if element or transition duration is not found
  84. if (!floatTransitionDuration && !floatTransitionDelay) {
  85. return 0
  86. }
  87. // If multiple durations are defined, take the first
  88. transitionDuration = transitionDuration.split(',')[0]
  89. transitionDelay = transitionDelay.split(',')[0]
  90. return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
  91. },
  92. reflow(element) {
  93. return element.offsetHeight
  94. },
  95. triggerTransitionEnd(element) {
  96. $(element).trigger(TRANSITION_END)
  97. },
  98. // TODO: Remove in v5
  99. supportsTransitionEnd() {
  100. return Boolean(TRANSITION_END)
  101. },
  102. isElement(obj) {
  103. return (obj[0] || obj).nodeType
  104. },
  105. typeCheckConfig(componentName, config, configTypes) {
  106. for (const property in configTypes) {
  107. if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
  108. const expectedTypes = configTypes[property]
  109. const value = config[property]
  110. const valueType = value && Util.isElement(value)
  111. ? 'element' : toType(value)
  112. if (!new RegExp(expectedTypes).test(valueType)) {
  113. throw new Error(
  114. `${componentName.toUpperCase()}: ` +
  115. `Option "${property}" provided type "${valueType}" ` +
  116. `but expected type "${expectedTypes}".`)
  117. }
  118. }
  119. }
  120. },
  121. findShadowRoot(element) {
  122. if (!document.documentElement.attachShadow) {
  123. return null
  124. }
  125. // Can find the shadow root otherwise it'll return the document
  126. if (typeof element.getRootNode === 'function') {
  127. const root = element.getRootNode()
  128. return root instanceof ShadowRoot ? root : null
  129. }
  130. if (element instanceof ShadowRoot) {
  131. return element
  132. }
  133. // when we don't find a shadow root
  134. if (!element.parentNode) {
  135. return null
  136. }
  137. return Util.findShadowRoot(element.parentNode)
  138. },
  139. jQueryDetection() {
  140. if (typeof $ === 'undefined') {
  141. throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.')
  142. }
  143. const version = $.fn.jquery.split(' ')[0].split('.')
  144. const minMajor = 1
  145. const ltMajor = 2
  146. const minMinor = 9
  147. const minPatch = 1
  148. const maxMajor = 4
  149. if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {
  150. throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
  151. }
  152. }
  153. }
  154. Util.jQueryDetection()
  155. setTransitionEndSupport()
  156. export default Util