Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/js/src
diff options
context:
space:
mode:
authorJohann-S <johann.servoire@gmail.com>2019-02-23 01:37:55 +0300
committerXhmikosR <xhmikosr@gmail.com>2019-02-26 14:04:04 +0300
commit8a37045b798fd66ede9c68774f9bb657e28d956a (patch)
tree35a1cf1b26701975f9732e99553e53fb295678c7 /js/src
parent8affe84c722bc459e7152e57d36a4f515f537abf (diff)
move util in a util folder with the sanitizer
Diffstat (limited to 'js/src')
-rw-r--r--js/src/alert.js17
-rw-r--r--js/src/button.js5
-rw-r--r--js/src/carousel.js36
-rw-r--r--js/src/collapse.js51
-rw-r--r--js/src/dom/eventHandler.js5
-rw-r--r--js/src/dom/polyfill.js6
-rw-r--r--js/src/dom/selectorEngine.js6
-rw-r--r--js/src/dropdown.js30
-rw-r--r--js/src/index.js2
-rw-r--r--js/src/modal.js55
-rw-r--r--js/src/popover.js5
-rw-r--r--js/src/scrollspy.js21
-rw-r--r--js/src/tab.js26
-rw-r--r--js/src/toast.js23
-rw-r--r--js/src/tooltip.js47
-rw-r--r--js/src/util.js179
-rw-r--r--js/src/util/index.js177
-rw-r--r--js/src/util/sanitizer.js (renamed from js/src/tools/sanitizer.js)84
18 files changed, 425 insertions, 350 deletions
diff --git a/js/src/alert.js b/js/src/alert.js
index a8d0cc5da9..9d8f69c465 100644
--- a/js/src/alert.js
+++ b/js/src/alert.js
@@ -5,10 +5,16 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ TRANSITION_END,
+ emulateTransitionEnd,
+ getSelectorFromElement,
+ getTransitionDurationFromElement
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -83,7 +89,7 @@ class Alert {
// Private
_getRootElement(element) {
- const selector = Util.getSelectorFromElement(element)
+ const selector = getSelectorFromElement(element)
let parent = false
if (selector) {
@@ -109,11 +115,11 @@ class Alert {
return
}
- const transitionDuration = Util.getTransitionDurationFromElement(element)
+ const transitionDuration = getTransitionDurationFromElement(element)
EventHandler
- .one(element, Util.TRANSITION_END, (event) => this._destroyElement(element, event))
- Util.emulateTransitionEnd(element, transitionDuration)
+ .one(element, TRANSITION_END, (event) => this._destroyElement(element, event))
+ emulateTransitionEnd(element, transitionDuration)
}
_destroyElement(element) {
@@ -170,7 +176,6 @@ EventHandler
* add .alert to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Alert._jQueryInterface
diff --git a/js/src/button.js b/js/src/button.js
index 2cb6acabae..489fe9de35 100644
--- a/js/src/button.js
+++ b/js/src/button.js
@@ -5,10 +5,12 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -180,7 +182,6 @@ EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (eve
* add .button to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Button._jQueryInterface
diff --git a/js/src/carousel.js b/js/src/carousel.js
index 0536593141..d253d51dfd 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -5,11 +5,22 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ TRANSITION_END,
+ emulateTransitionEnd,
+ getSelectorFromElement,
+ getTransitionDurationFromElement,
+ isVisible,
+ makeArray,
+ reflow,
+ triggerTransitionEnd,
+ typeCheckConfig
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -143,7 +154,7 @@ class Carousel {
nextWhenVisible() {
// Don't call next when the page isn't visible
// or the carousel or its parent isn't visible
- if (!document.hidden && Util.isVisible(this._element)) {
+ if (!document.hidden && isVisible(this._element)) {
this.next()
}
}
@@ -160,7 +171,7 @@ class Carousel {
}
if (SelectorEngine.findOne(Selector.NEXT_PREV, this._element)) {
- Util.triggerTransitionEnd(this._element)
+ triggerTransitionEnd(this._element)
this.cycle(true)
}
@@ -233,7 +244,7 @@ class Carousel {
...Default,
...config
}
- Util.typeCheckConfig(NAME, config, DefaultType)
+ typeCheckConfig(NAME, config, DefaultType)
return config
}
@@ -320,7 +331,7 @@ class Carousel {
}
}
- Util.makeArray(SelectorEngine.find(Selector.ITEM_IMG, this._element)).forEach((itemImg) => {
+ makeArray(SelectorEngine.find(Selector.ITEM_IMG, this._element)).forEach((itemImg) => {
EventHandler.on(itemImg, Event.DRAG_START, (e) => e.preventDefault())
})
@@ -356,7 +367,7 @@ class Carousel {
_getItemIndex(element) {
this._items = element && element.parentNode
- ? Util.makeArray(SelectorEngine.find(Selector.ITEM, element.parentNode))
+ ? makeArray(SelectorEngine.find(Selector.ITEM, element.parentNode))
: []
return this._items.indexOf(element)
@@ -459,7 +470,7 @@ class Carousel {
if (this._element.classList.contains(ClassName.SLIDE)) {
nextElement.classList.add(orderClassName)
- Util.reflow(nextElement)
+ reflow(nextElement)
activeElement.classList.add(directionalClassName)
nextElement.classList.add(directionalClassName)
@@ -472,10 +483,10 @@ class Carousel {
this._config.interval = this._config.defaultInterval || this._config.interval
}
- const transitionDuration = Util.getTransitionDurationFromElement(activeElement)
+ const transitionDuration = getTransitionDurationFromElement(activeElement)
EventHandler
- .one(activeElement, Util.TRANSITION_END, () => {
+ .one(activeElement, TRANSITION_END, () => {
nextElement.classList.remove(directionalClassName)
nextElement.classList.remove(orderClassName)
nextElement.classList.add(ClassName.ACTIVE)
@@ -496,7 +507,7 @@ class Carousel {
}, 0)
})
- Util.emulateTransitionEnd(activeElement, transitionDuration)
+ emulateTransitionEnd(activeElement, transitionDuration)
} else {
activeElement.classList.remove(ClassName.ACTIVE)
nextElement.classList.add(ClassName.ACTIVE)
@@ -557,7 +568,7 @@ class Carousel {
}
static _dataApiClickHandler(event) {
- const selector = Util.getSelectorFromElement(this)
+ const selector = getSelectorFromElement(this)
if (!selector) {
return
@@ -603,7 +614,7 @@ EventHandler
.on(document, Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)
EventHandler.on(window, Event.LOAD_DATA_API, () => {
- const carousels = Util.makeArray(SelectorEngine.find(Selector.DATA_RIDE))
+ const carousels = makeArray(SelectorEngine.find(Selector.DATA_RIDE))
for (let i = 0, len = carousels.length; i < len; i++) {
Carousel._carouselInterface(carousels[i], Data.getData(carousels[i], DATA_KEY))
}
@@ -616,7 +627,6 @@ EventHandler.on(window, Event.LOAD_DATA_API, () => {
* add .carousel to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Carousel._jQueryInterface
diff --git a/js/src/collapse.js b/js/src/collapse.js
index 9c2773754c..847062d8d1 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -5,11 +5,21 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ TRANSITION_END,
+ emulateTransitionEnd,
+ getSelectorFromElement,
+ getTransitionDurationFromElement,
+ isElement,
+ makeArray,
+ reflow,
+ typeCheckConfig
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -69,16 +79,16 @@ class Collapse {
this._isTransitioning = false
this._element = element
this._config = this._getConfig(config)
- this._triggerArray = Util.makeArray(SelectorEngine.find(
+ this._triggerArray = makeArray(SelectorEngine.find(
`[data-toggle="collapse"][href="#${element.id}"],` +
`[data-toggle="collapse"][data-target="#${element.id}"]`
))
- const toggleList = Util.makeArray(SelectorEngine.find(Selector.DATA_TOGGLE))
+ const toggleList = makeArray(SelectorEngine.find(Selector.DATA_TOGGLE))
for (let i = 0, len = toggleList.length; i < len; i++) {
const elem = toggleList[i]
- const selector = Util.getSelectorFromElement(elem)
- const filterElement = Util.makeArray(SelectorEngine.find(selector))
+ const selector = getSelectorFromElement(elem)
+ const filterElement = makeArray(SelectorEngine.find(selector))
.filter((foundElem) => foundElem === element)
if (selector !== null && filterElement.length) {
@@ -130,7 +140,7 @@ class Collapse {
let activesData
if (this._parent) {
- actives = Util.makeArray(SelectorEngine.find(Selector.ACTIVES, this._parent))
+ actives = makeArray(SelectorEngine.find(Selector.ACTIVES, this._parent))
.filter((elem) => {
if (typeof this._config.parent === 'string') {
return elem.getAttribute('data-parent') === this._config.parent
@@ -201,11 +211,11 @@ class Collapse {
const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)
const scrollSize = `scroll${capitalizedDimension}`
- const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+ const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, Util.TRANSITION_END, complete)
+ EventHandler.one(this._element, TRANSITION_END, complete)
- Util.emulateTransitionEnd(this._element, transitionDuration)
+ emulateTransitionEnd(this._element, transitionDuration)
this._element.style[dimension] = `${this._element[scrollSize]}px`
}
@@ -224,7 +234,7 @@ class Collapse {
this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`
- Util.reflow(this._element)
+ reflow(this._element)
this._element.classList.add(ClassName.COLLAPSING)
this._element.classList.remove(ClassName.COLLAPSE)
@@ -234,7 +244,7 @@ class Collapse {
if (triggerArrayLength > 0) {
for (let i = 0; i < triggerArrayLength; i++) {
const trigger = this._triggerArray[i]
- const selector = Util.getSelectorFromElement(trigger)
+ const selector = getSelectorFromElement(trigger)
if (selector !== null) {
const elem = SelectorEngine.findOne(selector)
@@ -257,10 +267,10 @@ class Collapse {
}
this._element.style[dimension] = ''
- const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+ const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, Util.TRANSITION_END, complete)
- Util.emulateTransitionEnd(this._element, transitionDuration)
+ EventHandler.one(this._element, TRANSITION_END, complete)
+ emulateTransitionEnd(this._element, transitionDuration)
}
setTransitioning(isTransitioning) {
@@ -285,7 +295,7 @@ class Collapse {
...config
}
config.toggle = Boolean(config.toggle) // Coerce string values
- Util.typeCheckConfig(NAME, config, DefaultType)
+ typeCheckConfig(NAME, config, DefaultType)
return config
}
@@ -297,7 +307,7 @@ class Collapse {
_getParent() {
let parent
- if (Util.isElement(this._config.parent)) {
+ if (isElement(this._config.parent)) {
parent = this._config.parent
// it's a jQuery object
@@ -311,7 +321,7 @@ class Collapse {
const selector =
`[data-toggle="collapse"][data-parent="${this._config.parent}"]`
- Util.makeArray(SelectorEngine.find(selector, parent))
+ makeArray(SelectorEngine.find(selector, parent))
.forEach((element) => {
this._addAriaAndCollapsedClass(
Collapse._getTargetFromElement(element),
@@ -342,7 +352,7 @@ class Collapse {
// Static
static _getTargetFromElement(element) {
- const selector = Util.getSelectorFromElement(element)
+ const selector = getSelectorFromElement(element)
return selector ? SelectorEngine.findOne(selector) : null
}
@@ -394,8 +404,8 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (
}
const triggerData = Manipulator.getDataAttributes(this)
- const selector = Util.getSelectorFromElement(this)
- const selectorElements = Util.makeArray(SelectorEngine.find(selector))
+ const selector = getSelectorFromElement(this)
+ const selectorElements = makeArray(SelectorEngine.find(selector))
selectorElements.forEach((element) => {
const data = Data.getData(element, DATA_KEY)
@@ -422,7 +432,6 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (
* add .collapse to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Collapse._jQueryInterface
diff --git a/js/src/dom/eventHandler.js b/js/src/dom/eventHandler.js
index 3b42388b8e..d92920cdaa 100644
--- a/js/src/dom/eventHandler.js
+++ b/js/src/dom/eventHandler.js
@@ -5,8 +5,10 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $
+} from '../util/index'
import Polyfill from './polyfill'
-import Util from '../util'
/**
* ------------------------------------------------------------------------
@@ -248,7 +250,6 @@ const EventHandler = {
const typeEvent = event.replace(stripNameRegex, '')
const inNamespace = event !== typeEvent
const isNative = nativeEvents.indexOf(typeEvent) > -1
- const $ = Util.jQuery
let jQueryEvent
let bubbles = true
diff --git a/js/src/dom/polyfill.js b/js/src/dom/polyfill.js
index cbae0f668e..579b7a10ed 100644
--- a/js/src/dom/polyfill.js
+++ b/js/src/dom/polyfill.js
@@ -5,7 +5,9 @@
* --------------------------------------------------------------------------
*/
-import Util from '../util'
+import {
+ getUID
+} from '../util/index'
/* istanbul ignore next */
const Polyfill = (() => {
@@ -48,7 +50,7 @@ const Polyfill = (() => {
const hasId = Boolean(this.id)
if (!hasId) {
- this.id = Util.getUID('scope')
+ this.id = getUID('scope')
}
let nodeList = null
diff --git a/js/src/dom/selectorEngine.js b/js/src/dom/selectorEngine.js
index 95b5a9fb50..151bb54c75 100644
--- a/js/src/dom/selectorEngine.js
+++ b/js/src/dom/selectorEngine.js
@@ -6,7 +6,9 @@
*/
import Polyfill from './polyfill'
-import Util from '../util'
+import {
+ makeArray
+} from '../util/index'
/**
* ------------------------------------------------------------------------
@@ -44,7 +46,7 @@ const SelectorEngine = {
return null
}
- const children = Util.makeArray(element.children)
+ const children = makeArray(element.children)
return children.filter((child) => this.matches(child, selector))
},
diff --git a/js/src/dropdown.js b/js/src/dropdown.js
index 46aff8f884..f5150a016f 100644
--- a/js/src/dropdown.js
+++ b/js/src/dropdown.js
@@ -5,12 +5,19 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ getSelectorFromElement,
+ isElement,
+ makeArray,
+ noop,
+ typeCheckConfig
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import Manipulator from './dom/manipulator'
import Popper from 'popper.js'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -159,7 +166,7 @@ class Dropdown {
if (this._config.reference === 'parent') {
referenceElement = parent
- } else if (Util.isElement(this._config.reference)) {
+ } else if (isElement(this._config.reference)) {
referenceElement = this._config.reference
// Check if it's jQuery element
@@ -182,9 +189,9 @@ class Dropdown {
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if ('ontouchstart' in document.documentElement &&
- !Util.makeArray(SelectorEngine.closest(parent, Selector.NAVBAR_NAV)).length) {
- Util.makeArray(document.body.children)
- .forEach((elem) => EventHandler.on(elem, 'mouseover', null, Util.noop()))
+ !makeArray(SelectorEngine.closest(parent, Selector.NAVBAR_NAV)).length) {
+ makeArray(document.body.children)
+ .forEach((elem) => EventHandler.on(elem, 'mouseover', null, noop()))
}
this._element.focus()
@@ -272,7 +279,7 @@ class Dropdown {
...config
}
- Util.typeCheckConfig(
+ typeCheckConfig(
NAME,
config,
this.constructor.DefaultType
@@ -389,7 +396,7 @@ class Dropdown {
return
}
- const toggles = Util.makeArray(SelectorEngine.find(Selector.DATA_TOGGLE))
+ const toggles = makeArray(SelectorEngine.find(Selector.DATA_TOGGLE))
for (let i = 0, len = toggles.length; i < len; i++) {
const parent = Dropdown._getParentFromElement(toggles[i])
const context = Data.getData(toggles[i], DATA_KEY)
@@ -425,8 +432,8 @@ class Dropdown {
// If this is a touch-enabled device we remove the extra
// empty mouseover listeners we added for iOS support
if ('ontouchstart' in document.documentElement) {
- Util.makeArray(document.body.children)
- .forEach((elem) => EventHandler.off(elem, 'mouseover', null, Util.noop()))
+ makeArray(document.body.children)
+ .forEach((elem) => EventHandler.off(elem, 'mouseover', null, noop()))
}
toggles[i].setAttribute('aria-expanded', 'false')
@@ -439,7 +446,7 @@ class Dropdown {
static _getParentFromElement(element) {
let parent
- const selector = Util.getSelectorFromElement(element)
+ const selector = getSelectorFromElement(element)
if (selector) {
parent = SelectorEngine.findOne(selector)
@@ -482,7 +489,7 @@ class Dropdown {
return
}
- const items = Util.makeArray(SelectorEngine.find(Selector.VISIBLE_ITEMS, parent))
+ const items = makeArray(SelectorEngine.find(Selector.VISIBLE_ITEMS, parent))
if (!items.length) {
return
@@ -535,7 +542,6 @@ EventHandler
* add .dropdown to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Dropdown._jQueryInterface
diff --git a/js/src/index.js b/js/src/index.js
index 8a0044fe53..4d46d84b95 100644
--- a/js/src/index.js
+++ b/js/src/index.js
@@ -16,10 +16,8 @@ import ScrollSpy from './scrollspy'
import Tab from './tab'
import Toast from './toast'
import Tooltip from './tooltip'
-import Util from './util'
export {
- Util,
Alert,
Button,
Carousel,
diff --git a/js/src/modal.js b/js/src/modal.js
index 0897b317ab..7efb24f842 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -5,11 +5,21 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ TRANSITION_END,
+ emulateTransitionEnd,
+ getSelectorFromElement,
+ getTransitionDurationFromElement,
+ isVisible,
+ makeArray,
+ reflow,
+ typeCheckConfig
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -184,10 +194,10 @@ class Modal {
if (transition) {
- const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+ const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, Util.TRANSITION_END, (event) => this._hideModal(event))
- Util.emulateTransitionEnd(this._element, transitionDuration)
+ EventHandler.one(this._element, TRANSITION_END, (event) => this._hideModal(event))
+ emulateTransitionEnd(this._element, transitionDuration)
} else {
this._hideModal()
}
@@ -228,7 +238,7 @@ class Modal {
...Default,
...config
}
- Util.typeCheckConfig(NAME, config, DefaultType)
+ typeCheckConfig(NAME, config, DefaultType)
return config
}
@@ -252,7 +262,7 @@ class Modal {
}
if (transition) {
- Util.reflow(this._element)
+ reflow(this._element)
}
this._element.classList.add(ClassName.SHOW)
@@ -272,10 +282,10 @@ class Modal {
}
if (transition) {
- const transitionDuration = Util.getTransitionDurationFromElement(this._dialog)
+ const transitionDuration = getTransitionDurationFromElement(this._dialog)
- EventHandler.one(this._dialog, Util.TRANSITION_END, transitionComplete)
- Util.emulateTransitionEnd(this._dialog, transitionDuration)
+ EventHandler.one(this._dialog, TRANSITION_END, transitionComplete)
+ emulateTransitionEnd(this._dialog, transitionDuration)
} else {
transitionComplete()
}
@@ -364,7 +374,7 @@ class Modal {
})
if (animate) {
- Util.reflow(this._backdrop)
+ reflow(this._backdrop)
}
this._backdrop.classList.add(ClassName.SHOW)
@@ -378,10 +388,10 @@ class Modal {
return
}
- const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)
+ const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop)
- EventHandler.one(this._backdrop, Util.TRANSITION_END, callback)
- Util.emulateTransitionEnd(this._backdrop, backdropTransitionDuration)
+ EventHandler.one(this._backdrop, TRANSITION_END, callback)
+ emulateTransitionEnd(this._backdrop, backdropTransitionDuration)
} else if (!this._isShown && this._backdrop) {
this._backdrop.classList.remove(ClassName.SHOW)
@@ -393,9 +403,9 @@ class Modal {
}
if (this._element.classList.contains(ClassName.FADE)) {
- const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)
- EventHandler.one(this._backdrop, Util.TRANSITION_END, callbackRemove)
- Util.emulateTransitionEnd(this._backdrop, backdropTransitionDuration)
+ const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop)
+ EventHandler.one(this._backdrop, TRANSITION_END, callbackRemove)
+ emulateTransitionEnd(this._backdrop, backdropTransitionDuration)
} else {
callbackRemove()
}
@@ -439,7 +449,7 @@ class Modal {
// while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
// Adjust fixed content padding
- Util.makeArray(SelectorEngine.find(Selector.FIXED_CONTENT))
+ makeArray(SelectorEngine.find(Selector.FIXED_CONTENT))
.forEach((element) => {
const actualPadding = element.style.paddingRight
const calculatedPadding = window.getComputedStyle(element)['padding-right']
@@ -448,7 +458,7 @@ class Modal {
})
// Adjust sticky content margin
- Util.makeArray(SelectorEngine.find(Selector.STICKY_CONTENT))
+ makeArray(SelectorEngine.find(Selector.STICKY_CONTENT))
.forEach((element) => {
const actualMargin = element.style.marginRight
const calculatedMargin = window.getComputedStyle(element)['margin-right']
@@ -469,7 +479,7 @@ class Modal {
_resetScrollbar() {
// Restore fixed content padding
- Util.makeArray(SelectorEngine.find(Selector.FIXED_CONTENT))
+ makeArray(SelectorEngine.find(Selector.FIXED_CONTENT))
.forEach((element) => {
const padding = Manipulator.getDataAttribute(element, 'padding-right')
if (typeof padding !== 'undefined') {
@@ -479,7 +489,7 @@ class Modal {
})
// Restore sticky content and navbar-toggler margin
- Util.makeArray(SelectorEngine.find(`${Selector.STICKY_CONTENT}`))
+ makeArray(SelectorEngine.find(`${Selector.STICKY_CONTENT}`))
.forEach((element) => {
const margin = Manipulator.getDataAttribute(element, 'margin-right')
if (typeof margin !== 'undefined') {
@@ -546,7 +556,7 @@ class Modal {
EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
let target
- const selector = Util.getSelectorFromElement(this)
+ const selector = getSelectorFromElement(this)
if (selector) {
target = SelectorEngine.findOne(selector)
@@ -569,7 +579,7 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (
}
EventHandler.one(target, Event.HIDDEN, () => {
- if (Util.isVisible(this)) {
+ if (isVisible(this)) {
this.focus()
}
})
@@ -589,7 +599,6 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (
* ------------------------------------------------------------------------
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Modal._jQueryInterface
diff --git a/js/src/popover.js b/js/src/popover.js
index ce5edcd5c4..958beaa3d0 100644
--- a/js/src/popover.js
+++ b/js/src/popover.js
@@ -5,10 +5,12 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $
+} from './util/index'
import Data from './dom/data'
import SelectorEngine from './dom/selectorEngine'
import Tooltip from './tooltip'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -177,7 +179,6 @@ class Popover extends Tooltip {
* ------------------------------------------------------------------------
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Popover._jQueryInterface
diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js
index f5d1008af7..74b60b7348 100644
--- a/js/src/scrollspy.js
+++ b/js/src/scrollspy.js
@@ -5,11 +5,17 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ getSelectorFromElement,
+ getUID,
+ makeArray,
+ typeCheckConfig
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -118,12 +124,12 @@ class ScrollSpy {
this._scrollHeight = this._getScrollHeight()
- const targets = Util.makeArray(SelectorEngine.find(this._selector))
+ const targets = makeArray(SelectorEngine.find(this._selector))
targets
.map((element) => {
let target
- const targetSelector = Util.getSelectorFromElement(element)
+ const targetSelector = getSelectorFromElement(element)
if (targetSelector) {
target = SelectorEngine.findOne(targetSelector)
@@ -174,13 +180,13 @@ class ScrollSpy {
if (typeof config.target !== 'string') {
let id = config.target.id
if (!id) {
- id = Util.getUID(NAME)
+ id = getUID(NAME)
config.target.id = id
}
config.target = `#${id}`
}
- Util.typeCheckConfig(NAME, config, DefaultType)
+ typeCheckConfig(NAME, config, DefaultType)
return config
}
@@ -284,7 +290,7 @@ class ScrollSpy {
}
_clear() {
- Util.makeArray(SelectorEngine.find(this._selector))
+ makeArray(SelectorEngine.find(this._selector))
.filter((node) => node.classList.contains(ClassName.ACTIVE))
.forEach((node) => node.classList.remove(ClassName.ACTIVE))
}
@@ -321,7 +327,7 @@ class ScrollSpy {
*/
EventHandler.on(window, Event.LOAD_DATA_API, () => {
- Util.makeArray(SelectorEngine.find(Selector.DATA_SPY))
+ makeArray(SelectorEngine.find(Selector.DATA_SPY))
.forEach((spy) => new ScrollSpy(spy, Manipulator.getDataAttributes(spy)))
})
@@ -331,7 +337,6 @@ EventHandler.on(window, Event.LOAD_DATA_API, () => {
* ------------------------------------------------------------------------
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = ScrollSpy._jQueryInterface
diff --git a/js/src/tab.js b/js/src/tab.js
index dab38c51c9..4320ee9eab 100644
--- a/js/src/tab.js
+++ b/js/src/tab.js
@@ -5,10 +5,18 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ TRANSITION_END,
+ emulateTransitionEnd,
+ getSelectorFromElement,
+ getTransitionDurationFromElement,
+ makeArray,
+ reflow
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -80,11 +88,11 @@ class Tab {
let target
let previous
const listElement = SelectorEngine.closest(this._element, Selector.NAV_LIST_GROUP)
- const selector = Util.getSelectorFromElement(this._element)
+ const selector = getSelectorFromElement(this._element)
if (listElement) {
const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE
- previous = Util.makeArray(SelectorEngine.find(itemSelector, listElement))
+ previous = makeArray(SelectorEngine.find(itemSelector, listElement))
previous = previous[previous.length - 1]
}
@@ -153,11 +161,11 @@ class Tab {
)
if (active && isTransitioning) {
- const transitionDuration = Util.getTransitionDurationFromElement(active)
+ const transitionDuration = getTransitionDurationFromElement(active)
active.classList.remove(ClassName.SHOW)
- EventHandler.one(active, Util.TRANSITION_END, complete)
- Util.emulateTransitionEnd(active, transitionDuration)
+ EventHandler.one(active, TRANSITION_END, complete)
+ emulateTransitionEnd(active, transitionDuration)
} else {
complete()
}
@@ -183,7 +191,7 @@ class Tab {
element.setAttribute('aria-selected', true)
}
- Util.reflow(element)
+ reflow(element)
if (element.classList.contains(ClassName.FADE)) {
element.classList.add(ClassName.SHOW)
@@ -193,7 +201,7 @@ class Tab {
const dropdownElement = SelectorEngine.closest(element, Selector.DROPDOWN)
if (dropdownElement) {
- Util.makeArray(SelectorEngine.find(Selector.DROPDOWN_TOGGLE))
+ makeArray(SelectorEngine.find(Selector.DROPDOWN_TOGGLE))
.forEach((dropdown) => dropdown.classList.add(ClassName.ACTIVE))
}
@@ -242,9 +250,9 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
+ * add .tab to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Tab._jQueryInterface
diff --git a/js/src/toast.js b/js/src/toast.js
index 6e878e5c80..fba559197f 100644
--- a/js/src/toast.js
+++ b/js/src/toast.js
@@ -5,10 +5,16 @@
* --------------------------------------------------------------------------
*/
+import {
+ jQuery as $,
+ TRANSITION_END,
+ emulateTransitionEnd,
+ getTransitionDurationFromElement,
+ typeCheckConfig
+} from './util/index'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import Manipulator from './dom/manipulator'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -104,10 +110,10 @@ class Toast {
this._element.classList.remove(ClassName.HIDE)
this._element.classList.add(ClassName.SHOWING)
if (this._config.animation) {
- const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+ const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, Util.TRANSITION_END, complete)
- Util.emulateTransitionEnd(this._element, transitionDuration)
+ EventHandler.one(this._element, TRANSITION_END, complete)
+ emulateTransitionEnd(this._element, transitionDuration)
} else {
complete()
}
@@ -153,7 +159,7 @@ class Toast {
...typeof config === 'object' && config ? config : {}
}
- Util.typeCheckConfig(
+ typeCheckConfig(
NAME,
config,
this.constructor.DefaultType
@@ -179,10 +185,10 @@ class Toast {
this._element.classList.remove(ClassName.SHOW)
if (this._config.animation) {
- const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+ const transitionDuration = getTransitionDurationFromElement(this._element)
- EventHandler.one(this._element, Util.TRANSITION_END, complete)
- Util.emulateTransitionEnd(this._element, transitionDuration)
+ EventHandler.one(this._element, TRANSITION_END, complete)
+ emulateTransitionEnd(this._element, transitionDuration)
} else {
complete()
}
@@ -221,7 +227,6 @@ class Toast {
* add .toast to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Toast._jQueryInterface
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index 8c2dbe7b23..13a5c62b7e 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -6,15 +6,26 @@
*/
import {
+ jQuery as $,
+ TRANSITION_END,
+ emulateTransitionEnd,
+ findShadowRoot,
+ getTransitionDurationFromElement,
+ getUID,
+ isElement,
+ makeArray,
+ noop,
+ typeCheckConfig
+} from './util/index'
+import {
DefaultWhitelist,
sanitizeHtml
-} from './tools/sanitizer'
+} from './util/sanitizer'
import Data from './dom/data'
import EventHandler from './dom/eventHandler'
import Manipulator from './dom/manipulator'
import Popper from 'popper.js'
import SelectorEngine from './dom/selectorEngine'
-import Util from './util'
/**
* ------------------------------------------------------------------------
@@ -257,7 +268,7 @@ class Tooltip {
if (this.isWithContent() && this._isEnabled) {
const showEvent = EventHandler.trigger(this.element, this.constructor.Event.SHOW)
- const shadowRoot = Util.findShadowRoot(this.element)
+ const shadowRoot = findShadowRoot(this.element)
const isInTheDom = shadowRoot !== null
? shadowRoot.contains(this.element)
: this.element.ownerDocument.documentElement.contains(this.element)
@@ -267,7 +278,7 @@ class Tooltip {
}
const tip = this.getTipElement()
- const tipId = Util.getUID(this.constructor.NAME)
+ const tipId = getUID(this.constructor.NAME)
tip.setAttribute('id', tipId)
this.element.setAttribute('aria-describedby', tipId)
@@ -323,8 +334,8 @@ class Tooltip {
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if ('ontouchstart' in document.documentElement) {
- Util.makeArray(document.body.children).forEach((element) => {
- EventHandler.on(element, 'mouseover', Util.noop())
+ makeArray(document.body.children).forEach((element) => {
+ EventHandler.on(element, 'mouseover', noop())
})
}
@@ -343,9 +354,9 @@ class Tooltip {
}
if (this.tip.classList.contains(ClassName.FADE)) {
- const transitionDuration = Util.getTransitionDurationFromElement(this.tip)
- EventHandler.one(this.tip, Util.TRANSITION_END, complete)
- Util.emulateTransitionEnd(this.tip, transitionDuration)
+ const transitionDuration = getTransitionDurationFromElement(this.tip)
+ EventHandler.one(this.tip, TRANSITION_END, complete)
+ emulateTransitionEnd(this.tip, transitionDuration)
} else {
complete()
}
@@ -381,8 +392,8 @@ class Tooltip {
// If this is a touch-enabled device we remove the extra
// empty mouseover listeners we added for iOS support
if ('ontouchstart' in document.documentElement) {
- Util.makeArray(document.body.children)
- .forEach((element) => EventHandler.off(element, 'mouseover', Util.noop))
+ makeArray(document.body.children)
+ .forEach((element) => EventHandler.off(element, 'mouseover', noop))
}
this._activeTrigger[Trigger.CLICK] = false
@@ -390,9 +401,10 @@ class Tooltip {
this._activeTrigger[Trigger.HOVER] = false
if (this.tip.classList.contains(ClassName.FADE)) {
- const transitionDuration = Util.getTransitionDurationFromElement(tip)
- EventHandler.one(tip, Util.TRANSITION_END, complete)
- Util.emulateTransitionEnd(tip, transitionDuration)
+ const transitionDuration = getTransitionDurationFromElement(tip)
+
+ EventHandler.one(tip, TRANSITION_END, complete)
+ emulateTransitionEnd(tip, transitionDuration)
} else {
complete()
}
@@ -507,7 +519,7 @@ class Tooltip {
return document.body
}
- if (Util.isElement(this.config.container)) {
+ if (isElement(this.config.container)) {
return this.config.container
}
@@ -705,7 +717,7 @@ class Tooltip {
config.content = config.content.toString()
}
- Util.typeCheckConfig(
+ typeCheckConfig(
NAME,
config,
this.constructor.DefaultType
@@ -795,8 +807,9 @@ class Tooltip {
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
+ * add .tooltip to jQuery only if jQuery is present
*/
-const $ = Util.jQuery
+
if (typeof $ !== 'undefined') {
const JQUERY_NO_CONFLICT = $.fn[NAME]
$.fn[NAME] = Tooltip._jQueryInterface
diff --git a/js/src/util.js b/js/src/util.js
deleted file mode 100644
index 8b6226f61c..0000000000
--- a/js/src/util.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): util.js
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * --------------------------------------------------------------------------
- */
-
-/**
- * ------------------------------------------------------------------------
- * Private TransitionEnd Helpers
- * ------------------------------------------------------------------------
- */
-
-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()
-}
-
-/**
- * --------------------------------------------------------------------------
- * Public Util Api
- * --------------------------------------------------------------------------
- */
-
-const Util = {
- TRANSITION_END: 'transitionend',
-
- 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
- },
-
- getSelectorFromElement(element) {
- let selector = element.getAttribute('data-target')
-
- if (!selector || selector === '#') {
- const hrefAttr = element.getAttribute('href')
- selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''
- }
-
- try {
- return document.querySelector(selector) ? selector : null
- } catch (err) {
- return null
- }
- },
-
- getTransitionDurationFromElement(element) {
- if (!element) {
- return 0
- }
-
- // Get transition-duration of the element
- let transitionDuration = window.getComputedStyle(element).transitionDuration
- let transitionDelay = window.getComputedStyle(element).transitionDelay
-
- const floatTransitionDuration = parseFloat(transitionDuration)
- const floatTransitionDelay = parseFloat(transitionDelay)
-
- // Return 0 if element or transition duration is not found
- if (!floatTransitionDuration && !floatTransitionDelay) {
- return 0
- }
-
- // If multiple durations are defined, take the first
- transitionDuration = transitionDuration.split(',')[0]
- transitionDelay = transitionDelay.split(',')[0]
-
- return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
- },
-
- reflow(element) {
- return element.offsetHeight
- },
-
- triggerTransitionEnd(element) {
- element.dispatchEvent(new Event(Util.TRANSITION_END))
- },
-
- isElement(obj) {
- return (obj[0] || obj).nodeType
- },
-
- emulateTransitionEnd(element, duration) {
- let called = false
- const durationPadding = 5
- const emulatedDuration = duration + durationPadding
- function listener() {
- called = true
- element.removeEventListener(Util.TRANSITION_END, listener)
- }
-
- element.addEventListener(Util.TRANSITION_END, listener)
- setTimeout(() => {
- if (!called) {
- Util.triggerTransitionEnd(element)
- }
- }, emulatedDuration)
- },
-
- 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}".`)
- }
- }
- }
- },
-
- makeArray(nodeList) {
- if (!nodeList) {
- return []
- }
-
- return [].slice.call(nodeList)
- },
-
- isVisible(element) {
- if (!element) {
- return false
- }
-
- if (element.style !== null && element.parentNode !== null && typeof element.parentNode.style !== 'undefined') {
- return element.style.display !== 'none' &&
- element.parentNode.style.display !== 'none' &&
- element.style.visibility !== 'hidden'
- }
- return false
- },
-
- 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)
- },
-
- noop() {
- // eslint-disable-next-line no-empty-function
- return function () {}
- },
-
- get jQuery() {
- return window.jQuery
- }
-}
-
-export default Util
diff --git a/js/src/util/index.js b/js/src/util/index.js
new file mode 100644
index 0000000000..7c86a95ffa
--- /dev/null
+++ b/js/src/util/index.js
@@ -0,0 +1,177 @@
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.3.1): util/index.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+const MAX_UID = 1000000
+const MILLISECONDS_MULTIPLIER = 1000
+const TRANSITION_END = 'transitionend'
+const jQuery = window.jQuery
+
+// Shoutout AngusCroll (https://goo.gl/pxwQGp)
+const toType = (obj) => ({}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase())
+
+/**
+ * --------------------------------------------------------------------------
+ * Public Util Api
+ * --------------------------------------------------------------------------
+ */
+
+const 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
+}
+
+const getSelectorFromElement = (element) => {
+ let selector = element.getAttribute('data-target')
+
+ if (!selector || selector === '#') {
+ const hrefAttr = element.getAttribute('href')
+
+ selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''
+ }
+
+ try {
+ return document.querySelector(selector) ? selector : null
+ } catch (err) {
+ return null
+ }
+}
+
+const getTransitionDurationFromElement = (element) => {
+ if (!element) {
+ return 0
+ }
+
+ // Get transition-duration of the element
+ let {
+ transitionDuration,
+ transitionDelay
+ } = window.getComputedStyle(element)
+
+ const floatTransitionDuration = parseFloat(transitionDuration)
+ const floatTransitionDelay = parseFloat(transitionDelay)
+
+ // Return 0 if element or transition duration is not found
+ if (!floatTransitionDuration && !floatTransitionDelay) {
+ return 0
+ }
+
+ // If multiple durations are defined, take the first
+ transitionDuration = transitionDuration.split(',')[0]
+ transitionDelay = transitionDelay.split(',')[0]
+
+ return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
+}
+
+const triggerTransitionEnd = (element) => {
+ element.dispatchEvent(new Event(TRANSITION_END))
+}
+
+const isElement = (obj) => (obj[0] || obj).nodeType
+
+const emulateTransitionEnd = (element, duration) => {
+ let called = false
+ const durationPadding = 5
+ const emulatedDuration = duration + durationPadding
+ function listener() {
+ called = true
+ element.removeEventListener(TRANSITION_END, listener)
+ }
+
+ element.addEventListener(TRANSITION_END, listener)
+ setTimeout(() => {
+ if (!called) {
+ triggerTransitionEnd(element)
+ }
+ }, emulatedDuration)
+}
+
+const typeCheckConfig = (componentName, config, configTypes) => {
+ Object.keys(configTypes)
+ .forEach((property) => {
+ const expectedTypes = configTypes[property]
+ const value = config[property]
+ const valueType = value && 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}".`)
+ }
+ })
+}
+
+const makeArray = (nodeList) => {
+ if (!nodeList) {
+ return []
+ }
+
+ return [].slice.call(nodeList)
+}
+
+const isVisible = (element) => {
+ if (!element) {
+ return false
+ }
+
+ if (element.style && element.parentNode && element.parentNode.style) {
+ return element.style.display !== 'none' &&
+ element.parentNode.style.display !== 'none' &&
+ element.style.visibility !== 'hidden'
+ }
+
+ return false
+}
+
+const 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 findShadowRoot(element.parentNode)
+}
+
+// eslint-disable-next-line no-empty-function
+const noop = () => function () {}
+
+const reflow = (element) => element.offsetHeight
+
+export {
+ jQuery,
+ TRANSITION_END,
+ getUID,
+ getSelectorFromElement,
+ getTransitionDurationFromElement,
+ triggerTransitionEnd,
+ isElement,
+ emulateTransitionEnd,
+ typeCheckConfig,
+ makeArray,
+ isVisible,
+ findShadowRoot,
+ noop,
+ reflow
+}
diff --git a/js/src/tools/sanitizer.js b/js/src/util/sanitizer.js
index 3c1608fee8..f8bb172a95 100644
--- a/js/src/tools/sanitizer.js
+++ b/js/src/util/sanitizer.js
@@ -1,11 +1,13 @@
/**
* --------------------------------------------------------------------------
- * Bootstrap (v4.3.1): tools/sanitizer.js
+ * Bootstrap (v4.3.1): util/sanitizer.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* --------------------------------------------------------------------------
*/
-import Util from '../util'
+import {
+ makeArray
+} from './index'
const uriAttrs = [
'background',
@@ -20,40 +22,6 @@ const uriAttrs = [
const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
-export const DefaultWhitelist = {
- // Global attributes allowed on any supplied element below.
- '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
- a: ['target', 'href', 'title', 'rel'],
- area: [],
- b: [],
- br: [],
- col: [],
- code: [],
- div: [],
- em: [],
- hr: [],
- h1: [],
- h2: [],
- h3: [],
- h4: [],
- h5: [],
- h6: [],
- i: [],
- img: ['src', 'alt', 'title', 'width', 'height'],
- li: [],
- ol: [],
- p: [],
- pre: [],
- s: [],
- small: [],
- span: [],
- sub: [],
- sup: [],
- strong: [],
- u: [],
- ul: []
-}
-
/**
* A pattern that recognizes a commonly useful subset of URLs that are safe.
*
@@ -68,7 +36,7 @@ const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|
*/
const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
-function allowedAttribute(attr, allowedAttributeList) {
+const allowedAttribute = (attr, allowedAttributeList) => {
const attrName = attr.nodeName.toLowerCase()
if (allowedAttributeList.indexOf(attrName) !== -1) {
@@ -91,8 +59,42 @@ function allowedAttribute(attr, allowedAttributeList) {
return false
}
+export const DefaultWhitelist = {
+ // Global attributes allowed on any supplied element below.
+ '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
+ a: ['target', 'href', 'title', 'rel'],
+ area: [],
+ b: [],
+ br: [],
+ col: [],
+ code: [],
+ div: [],
+ em: [],
+ hr: [],
+ h1: [],
+ h2: [],
+ h3: [],
+ h4: [],
+ h5: [],
+ h6: [],
+ i: [],
+ img: ['src', 'alt', 'title', 'width', 'height'],
+ li: [],
+ ol: [],
+ p: [],
+ pre: [],
+ s: [],
+ small: [],
+ span: [],
+ sub: [],
+ sup: [],
+ strong: [],
+ u: [],
+ ul: []
+}
+
export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
- if (unsafeHtml.length === 0) {
+ if (!unsafeHtml.length) {
return unsafeHtml
}
@@ -103,19 +105,19 @@ export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
const domParser = new window.DOMParser()
const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
const whitelistKeys = Object.keys(whiteList)
- const elements = Util.makeArray(createdDocument.body.querySelectorAll('*'))
+ const elements = makeArray(createdDocument.body.querySelectorAll('*'))
for (let i = 0, len = elements.length; i < len; i++) {
const el = elements[i]
const elName = el.nodeName.toLowerCase()
- if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {
+ if (whitelistKeys.indexOf(elName) === -1) {
el.parentNode.removeChild(el)
continue
}
- const attributeList = Util.makeArray(el.attributes)
+ const attributeList = makeArray(el.attributes)
const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
attributeList.forEach((attr) => {