aboutsummaryrefslogtreecommitdiff
path: root/js/src
diff options
context:
space:
mode:
authorJohann-S <[email protected]>2019-03-16 16:10:23 +0200
committerXhmikosR <[email protected]>2019-03-18 01:11:05 +0200
commit08679ac0b5f34e1a1f1766be460e51bc1aa8d82a (patch)
tree2cef1cf8f17668c56b410c4c3e32a55bd4853af9 /js/src
parentf7c1b1e683976ee780faadddc4edc70b477aa01f (diff)
downloadbootstrap-08679ac0b5f34e1a1f1766be460e51bc1aa8d82a.tar.xz
bootstrap-08679ac0b5f34e1a1f1766be460e51bc1aa8d82a.zip
Add back support for IE 11
Diffstat (limited to 'js/src')
-rw-r--r--js/src/button.js10
-rw-r--r--js/src/dom/eventHandler.js6
-rw-r--r--js/src/dom/polyfill.js179
-rw-r--r--js/src/dom/selectorEngine.js7
-rw-r--r--js/src/util/index.js5
5 files changed, 139 insertions, 68 deletions
diff --git a/js/src/button.js b/js/src/button.js
index 6453137e4..78b0fea8c 100644
--- a/js/src/button.js
+++ b/js/src/button.js
@@ -166,12 +166,18 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, eve
EventHandler.on(document, Event.FOCUS_DATA_API, Selector.DATA_TOGGLE_CARROT, event => {
const button = SelectorEngine.closest(event.target, Selector.BUTTON)
- button.classList.add(ClassName.FOCUS)
+
+ if (button) {
+ button.classList.add(ClassName.FOCUS)
+ }
})
EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, event => {
const button = SelectorEngine.closest(event.target, Selector.BUTTON)
- button.classList.remove(ClassName.FOCUS)
+
+ if (button) {
+ button.classList.remove(ClassName.FOCUS)
+ }
})
/**
diff --git a/js/src/dom/eventHandler.js b/js/src/dom/eventHandler.js
index 177465053..65c671fac 100644
--- a/js/src/dom/eventHandler.js
+++ b/js/src/dom/eventHandler.js
@@ -6,7 +6,7 @@
*/
import { jQuery as $ } from '../util/index'
-import Polyfill from './polyfill'
+import { createCustomEvent, defaultPreventedPreservedOnDispatch } from './polyfill'
/**
* ------------------------------------------------------------------------
@@ -305,7 +305,7 @@ const EventHandler = {
evt = document.createEvent('HTMLEvents')
evt.initEvent(typeEvent, bubbles, true)
} else {
- evt = new CustomEvent(event, {
+ evt = createCustomEvent(event, {
bubbles,
cancelable: true
})
@@ -326,7 +326,7 @@ const EventHandler = {
if (defaultPrevented) {
evt.preventDefault()
- if (!Polyfill.defaultPreventedPreservedOnDispatch) {
+ if (!defaultPreventedPreservedOnDispatch) {
Object.defineProperty(evt, 'defaultPrevented', {
get: () => true
})
diff --git a/js/src/dom/polyfill.js b/js/src/dom/polyfill.js
index f6cd23bdb..fd857cb38 100644
--- a/js/src/dom/polyfill.js
+++ b/js/src/dom/polyfill.js
@@ -1,3 +1,5 @@
+/* istanbul ignore file */
+
/**
* --------------------------------------------------------------------------
* Bootstrap (v4.3.1): dom/polyfill.js
@@ -7,83 +9,144 @@
import { getUID } from '../util/index'
-/* istanbul ignore next */
-const Polyfill = (() => {
- // MSEdge resets defaultPrevented flag upon dispatchEvent call if at least one listener is attached
- const defaultPreventedPreservedOnDispatch = (() => {
- const e = new CustomEvent('Bootstrap', {
- cancelable: true
- })
+let { matches, closest } = Element.prototype
+let find = Element.prototype.querySelectorAll
+let findOne = Element.prototype.querySelector
+let createCustomEvent = (eventName, params) => {
+ const cEvent = new CustomEvent(eventName, params)
- const element = document.createElement('div')
- element.addEventListener('Bootstrap', () => null)
+ return cEvent
+}
- e.preventDefault()
- element.dispatchEvent(e)
- return e.defaultPrevented
- })()
+if (typeof window.CustomEvent !== 'function') {
+ createCustomEvent = (eventName, params) => {
+ params = params || { bubbles: false, cancelable: false, detail: null }
- let find = Element.prototype.querySelectorAll
- let findOne = Element.prototype.querySelector
+ const evt = document.createEvent('CustomEvent')
- const scopeSelectorRegex = /:scope\b/
- const supportScopeQuery = (() => {
- const element = document.createElement('div')
+ evt.initCustomEvent(eventName, params.bubbles, params.cancelable, params.detail)
+ return evt
+ }
+}
- try {
- element.querySelectorAll(':scope *')
- } catch (error) {
- return false
+const workingDefaultPrevented = (() => {
+ const e = document.createEvent('CustomEvent')
+
+ e.initEvent('Bootstrap', true, true)
+ e.preventDefault()
+ return e.defaultPrevented
+})()
+
+if (!workingDefaultPrevented) {
+ const origPreventDefault = Event.prototype.preventDefault
+
+ Event.prototype.preventDefault = function () {
+ if (!this.cancelable) {
+ return
}
- return true
- })()
+ origPreventDefault.call(this)
+ Object.defineProperty(this, 'defaultPrevented', {
+ get() {
+ return true
+ },
+ configurable: true
+ })
+ }
+}
- if (!supportScopeQuery) {
- find = function (selector) {
- if (!scopeSelectorRegex.test(selector)) {
- return this.querySelectorAll(selector)
- }
+// MSEdge resets defaultPrevented flag upon dispatchEvent call if at least one listener is attached
+const defaultPreventedPreservedOnDispatch = (() => {
+ const e = createCustomEvent('Bootstrap', {
+ cancelable: true
+ })
- const hasId = Boolean(this.id)
+ const element = document.createElement('div')
+ element.addEventListener('Bootstrap', () => null)
- if (!hasId) {
- this.id = getUID('scope')
- }
+ e.preventDefault()
+ element.dispatchEvent(e)
+ return e.defaultPrevented
+})()
+
+if (!matches) {
+ matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector
+}
- let nodeList = null
- try {
- selector = selector.replace(scopeSelectorRegex, `#${this.id}`)
- nodeList = this.querySelectorAll(selector)
- } finally {
- if (!hasId) {
- this.removeAttribute('id')
- }
+if (!closest) {
+ closest = function (selector) {
+ let element = this
+
+ do {
+ if (matches.call(element, selector)) {
+ return element
}
- return nodeList
+ element = element.parentElement || element.parentNode
+ } while (element !== null && element.nodeType === 1)
+
+ return null
+ }
+}
+
+const scopeSelectorRegex = /:scope\b/
+const supportScopeQuery = (() => {
+ const element = document.createElement('div')
+
+ try {
+ element.querySelectorAll(':scope *')
+ } catch (error) {
+ return false
+ }
+
+ return true
+})()
+
+if (!supportScopeQuery) {
+ find = function (selector) {
+ if (!scopeSelectorRegex.test(selector)) {
+ return this.querySelectorAll(selector)
}
- findOne = function (selector) {
- if (!scopeSelectorRegex.test(selector)) {
- return this.querySelector(selector)
- }
+ const hasId = Boolean(this.id)
- const matches = find.call(this, selector)
+ if (!hasId) {
+ this.id = getUID('scope')
+ }
- if (typeof matches[0] !== 'undefined') {
- return matches[0]
+ let nodeList = null
+ try {
+ selector = selector.replace(scopeSelectorRegex, `#${this.id}`)
+ nodeList = this.querySelectorAll(selector)
+ } finally {
+ if (!hasId) {
+ this.removeAttribute('id')
}
-
- return null
}
- }
- return {
- defaultPreventedPreservedOnDispatch,
- find,
- findOne
+ return nodeList
}
-})()
-export default Polyfill
+ findOne = function (selector) {
+ if (!scopeSelectorRegex.test(selector)) {
+ return this.querySelector(selector)
+ }
+
+ const matches = find.call(this, selector)
+
+ if (typeof matches[0] !== 'undefined') {
+ return matches[0]
+ }
+
+ return null
+ }
+}
+
+export {
+ createCustomEvent,
+ find,
+ findOne,
+ matches,
+ closest,
+ defaultPreventedPreservedOnDispatch
+}
diff --git a/js/src/dom/selectorEngine.js b/js/src/dom/selectorEngine.js
index a54b18e58..fad3a43b5 100644
--- a/js/src/dom/selectorEngine.js
+++ b/js/src/dom/selectorEngine.js
@@ -5,7 +5,7 @@
* --------------------------------------------------------------------------
*/
-import Polyfill from './polyfill'
+import { find as findFn, findOne, matches, closest } from './polyfill'
import { makeArray } from '../util/index'
/**
@@ -14,12 +14,11 @@ import { makeArray } from '../util/index'
* ------------------------------------------------------------------------
*/
-const { find: findFn, findOne } = Polyfill
const NODE_TEXT = 3
const SelectorEngine = {
matches(element, selector) {
- return element.matches(selector)
+ return matches.call(element, selector)
},
find(selector, element = document.documentElement) {
@@ -72,7 +71,7 @@ const SelectorEngine = {
return null
}
- return element.closest(selector)
+ return closest.call(element, selector)
},
prev(element, selector) {
diff --git a/js/src/util/index.js b/js/src/util/index.js
index aea369558..5788c8749 100644
--- a/js/src/util/index.js
+++ b/js/src/util/index.js
@@ -71,7 +71,10 @@ const getTransitionDurationFromElement = element => {
}
const triggerTransitionEnd = element => {
- element.dispatchEvent(new Event(TRANSITION_END))
+ const evt = document.createEvent('HTMLEvents')
+
+ evt.initEvent(TRANSITION_END, true, true)
+ element.dispatchEvent(evt)
}
const isElement = obj => (obj[0] || obj).nodeType