Data: path.resolve(__dirname, '../js/src/dom/data.js'),
EventHandler: path.resolve(__dirname, '../js/src/dom/eventHandler.js'),
Manipulator: path.resolve(__dirname, '../js/src/dom/manipulator.js'),
- Polyfill: path.resolve(__dirname, '../js/src/dom/polyfill.js'),
SelectorEngine: path.resolve(__dirname, '../js/src/dom/selectorEngine.js'),
Alert: path.resolve(__dirname, '../js/src/alert.js'),
Button: path.resolve(__dirname, '../js/src/button.js'),
if (
pluginKey === 'Data' ||
pluginKey === 'Manipulator' ||
- pluginKey === 'Polyfill' ||
+ pluginKey === 'EventHandler' ||
+ pluginKey === 'SelectorEngine' ||
pluginKey === 'Util' ||
pluginKey === 'Sanitizer'
) {
}
}
- if (pluginKey === 'EventHandler' || pluginKey === 'SelectorEngine') {
- return {
- external: [
- bsPlugins.Polyfill
- ],
- globals: {
- [bsPlugins.Polyfill]: 'Polyfill'
- }
- }
- }
-
if (pluginKey === 'Alert' || pluginKey === 'Tab') {
return defaultPluginConfig
}
'Data',
'EventHandler',
'Manipulator',
- 'Polyfill',
'SelectorEngine'
]
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)
+ }
})
/**
*/
import { jQuery as $ } from '../util/index'
-import Polyfill from './polyfill'
+import { createCustomEvent, defaultPreventedPreservedOnDispatch } from './polyfill'
/**
* ------------------------------------------------------------------------
evt = document.createEvent('HTMLEvents')
evt.initEvent(typeEvent, bubbles, true)
} else {
- evt = new CustomEvent(event, {
+ evt = createCustomEvent(event, {
bubbles,
cancelable: true
})
if (defaultPrevented) {
evt.preventDefault()
- if (!Polyfill.defaultPreventedPreservedOnDispatch) {
+ if (!defaultPreventedPreservedOnDispatch) {
Object.defineProperty(evt, 'defaultPrevented', {
get: () => true
})
+/* istanbul ignore file */
+
/**
* --------------------------------------------------------------------------
* Bootstrap (v4.3.1): dom/polyfill.js
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
+}
* --------------------------------------------------------------------------
*/
-import Polyfill from './polyfill'
+import { find as findFn, findOne, matches, closest } from './polyfill'
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) {
return null
}
- return element.closest(selector)
+ return closest.call(element, selector)
},
prev(element, selector) {
}
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
browser: 'Edge',
browser_version: 'latest'
},
+ ie11Win10: {
+ base: 'BrowserStack',
+ os: 'Windows',
+ os_version: '10',
+ browser: 'IE',
+ browser_version: '11.0'
+ },
chromeWin10: {
base: 'BrowserStack',
os: 'Windows',
conf.detectBrowsers = detectBrowsers
files = files.concat([
jqueryFile,
+ 'js/tests/unit/tests-polyfills.js',
'dist/js/bootstrap.js',
- 'js/tests/unit/*.js'
+ 'js/tests/unit/!(tests-polyfills).js'
])
} else if (browserStack) {
conf.hostname = ip.address()
reporters.push('BrowserStack')
files = files.concat([
jqueryFile,
+ 'js/tests/unit/tests-polyfills.js',
'js/coverage/dist/util/util.js',
'js/coverage/dist/util/sanitizer.js',
'js/coverage/dist/dom/polyfill.js',
'js/coverage/dist/dom/!(polyfill).js',
'js/coverage/dist/tooltip.js',
'js/coverage/dist/!(util|index|tooltip).js', // include all of our js/dist files except util.js, index.js and tooltip.js
- 'js/tests/unit/*.js',
+ 'js/tests/unit/!(tests-polyfills).js',
'js/tests/unit/dom/*.js',
'js/tests/unit/util/*.js'
])
)
files = files.concat([
jqueryFile,
+ 'js/tests/unit/tests-polyfills.js',
'js/coverage/dist/util/util.js',
'js/coverage/dist/util/sanitizer.js',
'js/coverage/dist/dom/polyfill.js',
'js/coverage/dist/dom/!(polyfill).js',
'js/coverage/dist/tooltip.js',
'js/coverage/dist/!(util|index|tooltip).js', // include all of our js/dist files except util.js, index.js and tooltip.js
- 'js/tests/unit/*.js',
+ 'js/tests/unit/!(tests-polyfills).js',
'js/tests/unit/dom/*.js',
'js/tests/unit/util/*.js'
])
})
QUnit.test('should enforce focus', function (assert) {
- assert.expect(2)
+ var isIE11 = Boolean(window.MSInputMethodContext) && Boolean(document.documentMode)
+
+ if (isIE11) {
+ assert.expect(1)
+ } else {
+ assert.expect(2)
+ }
+
var done = assert.async()
var $modal = $([
done()
}
- document.addEventListener('focusin', focusInListener)
+ if (isIE11) {
+ done()
+ } else {
+ document.addEventListener('focusin', focusInListener)
- var focusInEvent = new Event('focusin')
- Object.defineProperty(focusInEvent, 'target', {
- value: $('#qunit-fixture')[0]
- })
+ var focusInEvent = new Event('focusin')
+ Object.defineProperty(focusInEvent, 'target', {
+ value: $('#qunit-fixture')[0]
+ })
- document.dispatchEvent(focusInEvent)
+ document.dispatchEvent(focusInEvent)
+ }
})
.bootstrapModal('show')
})
--- /dev/null
+// Polyfills for our unit tests
+(function () {
+ 'use strict'
+
+ // Event constructor shim
+ if (!window.Event || typeof window.Event !== 'function') {
+ var origEvent = window.Event
+ window.Event = function (inType, params) {
+ params = params || {}
+ var e = document.createEvent('Event')
+ e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable))
+ return e
+ }
+
+ window.Event.prototype = origEvent.prototype
+ }
+
+ if (typeof window.CustomEvent !== 'function') {
+ window.CustomEvent = function (event, params) {
+ params = params || { bubbles: false, cancelable: false, detail: null }
+ var evt = document.createEvent('CustomEvent')
+ evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
+ return evt
+ }
+
+ CustomEvent.prototype = window.Event.prototype
+ }
+})()