diff --git a/js/src/alert.js b/js/src/alert.js index 1bdd9706a4..9332aa891d 100644 --- a/js/src/alert.js +++ b/js/src/alert.js @@ -114,8 +114,11 @@ class Alert { } _destroyElement(element) { + if (element.parentNode) { + element.parentNode.removeChild(element) + } + EventHandler.trigger(element, Event.CLOSED) - element.parentNode.removeChild(element) } // Static @@ -150,8 +153,8 @@ EventHandler.on(document, Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleD * add .alert to jQuery only if jQuery is present */ -if (typeof window.$ !== 'undefined' || typeof window.jQuery !== 'undefined') { - const $ = window.$ || window.jQuery +const $ = Util.jQuery +if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] $.fn[NAME] = Alert._jQueryInterface $.fn[NAME].Constructor = Alert diff --git a/js/src/button.js b/js/src/button.js index acba736af4..0e3b8a9df5 100644 --- a/js/src/button.js +++ b/js/src/button.js @@ -9,6 +9,7 @@ import Data from './dom/data' import EventHandler from './dom/eventHandler' import Manipulator from './dom/manipulator' import SelectorEngine from './dom/selectorEngine' +import Util from './util' /** * ------------------------------------------------------------------------ @@ -175,8 +176,8 @@ EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (eve * add .button to jQuery only if jQuery is present */ -if (typeof window.$ !== 'undefined' || typeof window.jQuery !== 'undefined') { - const $ = window.$ || window.jQuery +const $ = Util.jQuery +if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] $.fn[NAME] = Button._jQueryInterface $.fn[NAME].Constructor = Button diff --git a/js/src/carousel.js b/js/src/carousel.js index e33788594d..fd6d5bf802 100644 --- a/js/src/carousel.js +++ b/js/src/carousel.js @@ -571,7 +571,7 @@ class Carousel { config.interval = false } - Carousel._jQueryInterface.call($(target), config) + Carousel._carouselInterface(target, config) if (slideIndex) { Data.getData(target, DATA_KEY).to(slideIndex) @@ -605,8 +605,8 @@ EventHandler.on(window, Event.LOAD_DATA_API, () => { * add .carousel to jQuery only if jQuery is present */ -if (typeof window.$ !== 'undefined' || typeof window.jQuery !== 'undefined') { - const $ = window.$ || window.jQuery +const $ = Util.jQuery +if (typeof $ !== 'undefined') { const JQUERY_NO_CONFLICT = $.fn[NAME] $.fn[NAME] = Carousel._jQueryInterface $.fn[NAME].Constructor = Carousel diff --git a/js/src/collapse.js b/js/src/collapse.js index 31200c33a8..7d6aa30ed8 100644 --- a/js/src/collapse.js +++ b/js/src/collapse.js @@ -141,12 +141,11 @@ class Collapse { } } + const container = SelectorEngine.findOne(this._selector) if (actives) { - const tempActiveData = actives.filter((elem) => { - const container = SelectorEngine.findOne(this._selector) - return !container.contains(elem) - }) + const tempActiveData = actives.filter((elem) => container !== elem) activesData = tempActiveData[0] ? Data.getData(tempActiveData[0], DATA_KEY) : null + if (activesData && activesData._isTransitioning) { return } @@ -159,14 +158,14 @@ class Collapse { if (actives) { actives.forEach((elemActive) => { - const container = SelectorEngine.findOne(this._selector) - if (!container.contains(elemActive)) { + if (container !== elemActive) { Collapse._collapseInterface(elemActive, 'hide') } + + if (!activesData) { + Data.setData(elemActive, DATA_KEY, null) + } }) - if (!activesData) { - Data.setData(actives[0], DATA_KEY, null) - } } const dimension = this._getDimension() diff --git a/js/src/dom/data.js b/js/src/dom/data.js index 82ff5eae83..4cee65d2b8 100644 --- a/js/src/dom/data.js +++ b/js/src/dom/data.js @@ -23,10 +23,10 @@ const Data = (() => { key, id } + id++ } - storeData[id] = data - id++ + storeData[element.key.id] = data }, get(element, key) { if (typeof element === 'undefined' || typeof element.key === 'undefined') { diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 85d8738e0d..ddc783c0dd 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -460,7 +460,7 @@ class Dropdown { if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || - $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { + SelectorEngine.closest(event.target, Selector.MENU)) : !REGEXP_KEYDOWN.test(event.which)) { return } diff --git a/js/src/index.js b/js/src/index.js index 665b889c55..327de242b2 100644 --- a/js/src/index.js +++ b/js/src/index.js @@ -17,21 +17,6 @@ import Util from './util' * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -(() => { - // only check jQuery version if jQuery is available - if (typeof window.$ !== 'undefined' || typeof window.jQuery !== 'undefined') { - const version = window.$.fn.jquery.split(' ')[0].split('.') - const minMajor = 1 - const ltMajor = 2 - const minMinor = 9 - const minPatch = 1 - const maxMajor = 4 - - if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { - throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0') - } - } -})() export { Util, diff --git a/js/src/modal.js b/js/src/modal.js index 898d1c73d7..6da3d25aa8 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -232,7 +232,7 @@ class Modal { } _showElement(relatedTarget) { - const transition = $(this._element).hasClass(ClassName.FADE) + const transition = this._element.classList.contains(ClassName.FADE) if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { @@ -295,14 +295,14 @@ class Modal { _setEscapeEvent() { if (this._isShown && this._config.keyboard) { - $(this._element).on(Event.KEYDOWN_DISMISS, (event) => { + EventHandler.on(this._element, Event.KEYDOWN_DISMISS, (event) => { if (event.which === ESCAPE_KEYCODE) { event.preventDefault() this.hide() } }) } else if (!this._isShown) { - $(this._element).off(Event.KEYDOWN_DISMISS) + EventHandler.off(this._element, Event.KEYDOWN_DISMISS) } } diff --git a/js/src/util.js b/js/src/util.js index 667f46076f..78f5fe3fbe 100644 --- a/js/src/util.js +++ b/js/src/util.js @@ -69,8 +69,8 @@ const Util = { } // Get transition-duration of the element - let transitionDuration = element.style.transitionDuration - let transitionDelay = element.style.transitionDelay + let transitionDuration = window.getComputedStyle(element).transitionDuration + let transitionDelay = window.getComputedStyle(element).transitionDelay const floatTransitionDuration = parseFloat(transitionDuration) const floatTransitionDelay = parseFloat(transitionDelay) @@ -92,7 +92,7 @@ const Util = { }, triggerTransitionEnd(element) { - EventHandler.trigger(element, Util.TRANSITION_END) + element.dispatchEvent(new Event(Util.TRANSITION_END)) }, // TODO: Remove in v5 diff --git a/js/tests/unit/alert.js b/js/tests/unit/alert.js index 588908d66e..3fe796e28b 100644 --- a/js/tests/unit/alert.js +++ b/js/tests/unit/alert.js @@ -91,7 +91,7 @@ $(function () { var done = assert.async() var $el = $('
') var $alert = $el.bootstrapAlert() - var alertInstance = $alert.data('bs.alert') + var alertInstance = Data.getData($alert[0], 'bs.alert') $alert.one('closed.bs.alert', function () { assert.ok('alert closed') @@ -107,11 +107,11 @@ $(function () { var $el = $('
') var $alert = $el.bootstrapAlert() - assert.ok(typeof $alert.data('bs.alert') !== 'undefined') + assert.ok(typeof Data.getData($alert[0], 'bs.alert') !== 'undefined') - $alert.data('bs.alert').dispose() + Data.getData($alert[0], 'bs.alert').dispose() - assert.ok(typeof $alert.data('bs.button') === 'undefined') + assert.ok(Data.getData($alert[0], 'bs.alert') === null) }) QUnit.test('should return alert version', function (assert) { diff --git a/js/tests/unit/button.js b/js/tests/unit/button.js index c162e3a9fd..0fa19d1548 100644 --- a/js/tests/unit/button.js +++ b/js/tests/unit/button.js @@ -208,11 +208,11 @@ $(function () { var $el = $('
') var $button = $el.bootstrapButton() - assert.ok(typeof $button.data('bs.button') !== 'undefined') + assert.ok(typeof Data.getData($button[0], 'bs.button') !== 'undefined') - $button.data('bs.button').dispose() + Data.getData($button[0], 'bs.button').dispose() - assert.ok(typeof $button.data('bs.button') === 'undefined') + assert.ok(Data.getData($button[0], 'bs.button') === null) }) QUnit.test('should return button version', function (assert) { diff --git a/js/tests/unit/dropdown.js b/js/tests/unit/dropdown.js index 2595ec27b2..c94b8a4410 100644 --- a/js/tests/unit/dropdown.js +++ b/js/tests/unit/dropdown.js @@ -1025,7 +1025,7 @@ $(function () { .find('[data-toggle="dropdown"]') .bootstrapDropdown() - var dropdown = $dropdown.data('bs.dropdown') + var dropdown = Data.getData($dropdown[0], 'bs.dropdown') dropdown.toggle() assert.ok(dropdown._popper) @@ -1053,7 +1053,7 @@ $(function () { .find('[data-toggle="dropdown"]') .bootstrapDropdown() - var dropdown = $dropdown.data('bs.dropdown') + var dropdown = Data.getData($dropdown[0], 'bs.dropdown') var spyDetectNavbar = sinon.spy(dropdown, '_detectNavbar') dropdown.update() @@ -1078,7 +1078,7 @@ $(function () { .find('[data-toggle="dropdown"]') .bootstrapDropdown() - var dropdown = $dropdown.data('bs.dropdown') + var dropdown = Data.getData($dropdown[0], 'bs.dropdown') dropdown.toggle() assert.ok(dropdown._popper) @@ -1109,7 +1109,7 @@ $(function () { .find('[data-toggle="dropdown"]') .bootstrapDropdown() - var dropdown = $dropdown.data('bs.dropdown') + var dropdown = Data.getData($dropdown[0], 'bs.dropdown') assert.notOk(dropdown._popper) assert.ok(dropdown._menu !== null) diff --git a/js/tests/unit/popover.js b/js/tests/unit/popover.js index da436ad283..0dd9c98e39 100644 --- a/js/tests/unit/popover.js +++ b/js/tests/unit/popover.js @@ -279,14 +279,14 @@ $(function () { }) .one('shown.bs.popover', function () { assert.notEqual($('.popover').length, 0, 'popover was inserted') - $div.find('a').trigger('click') + EventHandler.trigger($div.find('a')[0], 'click') }) .one('hidden.bs.popover', function () { assert.strictEqual($('.popover').length, 0, 'popover was removed') done() }) - $div.find('a').trigger('click') + EventHandler.trigger($div.find('a')[0], 'click') }) QUnit.test('should detach popover content rather than removing it so that event handlers are left intact', function (assert) { diff --git a/js/tests/unit/tooltip.js b/js/tests/unit/tooltip.js index d2729fa64f..081cbb1099 100644 --- a/js/tests/unit/tooltip.js +++ b/js/tests/unit/tooltip.js @@ -1000,7 +1000,7 @@ $(function () { .appendTo('#qunit-fixture') .bootstrapTooltip() - var tooltip = $tooltip.data('bs.tooltip') + var tooltip = Data.getData($tooltip[0], 'bs.tooltip') tooltip.show() assert.ok(tooltip._popper) @@ -1016,7 +1016,7 @@ $(function () { .appendTo('#qunit-fixture') .bootstrapTooltip() - var tooltip = $tooltip.data('bs.tooltip') + var tooltip = Data.getData($tooltip[0], 'bs.tooltip') tooltip.update() assert.ok(tooltip._popper === null)