aboutsummaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorJohann <[email protected]>2016-12-02 18:52:19 +0100
committerMark Otto <[email protected]>2016-12-02 09:52:19 -0800
commit297c47c3fdbb58e3d9824afdee83ef3c4b9d141a (patch)
treeca90559ff2025eca6400b6b88b3d609d91f9653f /js
parent1fb6d8c46a560e2e35295440721ba2929f9721b6 (diff)
downloadbootstrap-297c47c3fdbb58e3d9824afdee83ef3c4b9d141a.tar.xz
bootstrap-297c47c3fdbb58e3d9824afdee83ef3c4b9d141a.zip
[V4] Throw error when a plugin is in transition (#17823)
* Throw error when a plugin is in transition * Add unit tests about plugins in transition
Diffstat (limited to 'js')
-rw-r--r--js/src/carousel.js10
-rw-r--r--js/src/collapse.js14
-rw-r--r--js/src/modal.js28
-rw-r--r--js/src/tooltip.js26
-rw-r--r--js/tests/visual/carousel.html24
-rw-r--r--js/tests/visual/collapse.html25
-rw-r--r--js/tests/visual/modal.html21
-rw-r--r--js/tests/visual/tooltip.html19
8 files changed, 144 insertions, 23 deletions
diff --git a/js/src/carousel.js b/js/src/carousel.js
index e56d4f0f2..7fda8f615 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -116,9 +116,10 @@ const Carousel = (($) => {
// public
next() {
- if (!this._isSliding) {
- this._slide(Direction.NEXT)
+ if (this._isSliding) {
+ throw new Error('Carousel is sliding')
}
+ this._slide(Direction.NEXT)
}
nextWhenVisible() {
@@ -129,9 +130,10 @@ const Carousel = (($) => {
}
prev() {
- if (!this._isSliding) {
- this._slide(Direction.PREVIOUS)
+ if (this._isSliding) {
+ throw new Error('Carousel is sliding')
}
+ this._slide(Direction.PREVIOUS)
}
pause(event) {
diff --git a/js/src/collapse.js b/js/src/collapse.js
index ebc3e24cf..1e4730ff7 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -112,8 +112,11 @@ const Collapse = (($) => {
}
show() {
- if (this._isTransitioning ||
- $(this._element).hasClass(ClassName.ACTIVE)) {
+ if (this._isTransitioning) {
+ throw new Error('Collapse is transitioning')
+ }
+
+ if ($(this._element).hasClass(ClassName.ACTIVE)) {
return
}
@@ -193,8 +196,11 @@ const Collapse = (($) => {
}
hide() {
- if (this._isTransitioning ||
- !$(this._element).hasClass(ClassName.ACTIVE)) {
+ if (this._isTransitioning) {
+ throw new Error('Collapse is transitioning')
+ }
+
+ if (!$(this._element).hasClass(ClassName.ACTIVE)) {
return
}
diff --git a/js/src/modal.js b/js/src/modal.js
index 61a28dbf5..70bb68e42 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -87,6 +87,7 @@ const Modal = (($) => {
this._isShown = false
this._isBodyOverflowing = false
this._ignoreBackdropClick = false
+ this._isTransitioning = false
this._originalBodyPadding = 0
this._scrollbarWidth = 0
}
@@ -110,6 +111,14 @@ const Modal = (($) => {
}
show(relatedTarget) {
+ if (this._isTransitioning) {
+ throw new Error('Modal is transitioning')
+ }
+
+ if (Util.supportsTransitionEnd() &&
+ $(this._element).hasClass(ClassName.FADE)) {
+ this._isTransitioning = true
+ }
const showEvent = $.Event(Event.SHOW, {
relatedTarget
})
@@ -152,8 +161,17 @@ const Modal = (($) => {
event.preventDefault()
}
- const hideEvent = $.Event(Event.HIDE)
+ if (this._isTransitioning) {
+ throw new Error('Modal is transitioning')
+ }
+ const transition = Util.supportsTransitionEnd() &&
+ $(this._element).hasClass(ClassName.FADE)
+ if (transition) {
+ this._isTransitioning = true
+ }
+
+ const hideEvent = $.Event(Event.HIDE)
$(this._element).trigger(hideEvent)
if (!this._isShown || hideEvent.isDefaultPrevented()) {
@@ -172,9 +190,7 @@ const Modal = (($) => {
$(this._element).off(Event.CLICK_DISMISS)
$(this._dialog).off(Event.MOUSEDOWN_DISMISS)
- if (Util.supportsTransitionEnd() &&
- $(this._element).hasClass(ClassName.FADE)) {
-
+ if (transition) {
$(this._element)
.one(Util.TRANSITION_END, (event) => this._hideModal(event))
.emulateTransitionEnd(TRANSITION_DURATION)
@@ -240,6 +256,7 @@ const Modal = (($) => {
if (this._config.focus) {
this._element.focus()
}
+ this._isTransitioning = false
$(this._element).trigger(shownEvent)
}
@@ -287,7 +304,8 @@ const Modal = (($) => {
_hideModal() {
this._element.style.display = 'none'
- this._element.setAttribute('aria-hidden', true)
+ this._element.setAttribute('aria-hidden', 'true')
+ this._isTransitioning = false
this._showBackdrop(() => {
$(document.body).removeClass(ClassName.OPEN)
this._resetAdjustments()
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index 2b659b885..dc291a72c 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -123,11 +123,12 @@ const Tooltip = (($) => {
constructor(element, config) {
// private
- this._isEnabled = true
- this._timeout = 0
- this._hoverState = ''
- this._activeTrigger = {}
- this._tether = null
+ this._isEnabled = true
+ this._timeout = 0
+ this._hoverState = ''
+ this._activeTrigger = {}
+ this._isTransitioning = false
+ this._tether = null
// protected
this.element = element
@@ -245,9 +246,12 @@ const Tooltip = (($) => {
if ($(this.element).css('display') === 'none') {
throw new Error('Please use show on visible elements')
}
- const showEvent = $.Event(this.constructor.Event.SHOW)
+ const showEvent = $.Event(this.constructor.Event.SHOW)
if (this.isWithContent() && this._isEnabled) {
+ if (this._isTransitioning) {
+ throw new Error('Tooltip is transitioning')
+ }
$(this.element).trigger(showEvent)
const isInTheDom = $.contains(
@@ -303,7 +307,8 @@ const Tooltip = (($) => {
const complete = () => {
const prevHoverState = this._hoverState
- this._hoverState = null
+ this._hoverState = null
+ this._isTransitioning = false
$(this.element).trigger(this.constructor.Event.SHOWN)
@@ -313,6 +318,7 @@ const Tooltip = (($) => {
}
if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+ this._isTransitioning = true
$(this.tip)
.one(Util.TRANSITION_END, complete)
.emulateTransitionEnd(Tooltip._TRANSITION_DURATION)
@@ -326,6 +332,9 @@ const Tooltip = (($) => {
hide(callback) {
const tip = this.getTipElement()
const hideEvent = $.Event(this.constructor.Event.HIDE)
+ if (this._isTransitioning) {
+ throw new Error('Tooltip is transitioning')
+ }
const complete = () => {
if (this._hoverState !== HoverState.ACTIVE && tip.parentNode) {
tip.parentNode.removeChild(tip)
@@ -333,6 +342,7 @@ const Tooltip = (($) => {
this.element.removeAttribute('aria-describedby')
$(this.element).trigger(this.constructor.Event.HIDDEN)
+ this._isTransitioning = false
this.cleanupTether()
if (callback) {
@@ -350,7 +360,7 @@ const Tooltip = (($) => {
if (Util.supportsTransitionEnd() &&
$(this.tip).hasClass(ClassName.FADE)) {
-
+ this._isTransitioning = true
$(tip)
.one(Util.TRANSITION_END, complete)
.emulateTransitionEnd(TRANSITION_DURATION)
diff --git a/js/tests/visual/carousel.html b/js/tests/visual/carousel.html
index 2017f338b..b26fb4a0d 100644
--- a/js/tests/visual/carousel.html
+++ b/js/tests/visual/carousel.html
@@ -46,11 +46,31 @@
<script src="../../dist/carousel.js"></script>
<script>
- $(function() {
+ // Should throw an error because carousel is in transition
+ function testCarouselTransitionError() {
+ var err = false
+ var $carousel = $('#carousel-example-generic')
+ $carousel.on('slid.bs.carousel', function () {
+ $carousel.off('slid.bs.carousel')
+ if (!err) {
+ alert('No error thrown for : testCarouselTransitionError')
+ }
+ })
+ try {
+ $carousel.carousel('next').carousel('prev')
+ }
+ catch (e) {
+ err = true
+ console.error(e.message)
+ }
+ }
+
+ $(function () {
// Test to show that the carousel doesn't slide when the current tab isn't visible
- $('#carousel-example-generic').on('slid.bs.carousel', function(event) {
+ $('#carousel-example-generic').on('slid.bs.carousel', function (event) {
console.log('slid at ', event.timeStamp)
})
+ testCarouselTransitionError()
})
</script>
</body>
diff --git a/js/tests/visual/collapse.html b/js/tests/visual/collapse.html
index e13597984..973d3c5ee 100644
--- a/js/tests/visual/collapse.html
+++ b/js/tests/visual/collapse.html
@@ -61,5 +61,30 @@
<script src="../vendor/jquery.min.js"></script>
<script src="../../dist/util.js"></script>
<script src="../../dist/collapse.js"></script>
+ <script>
+ // JavaScript Test
+ $(function () {
+ testCollapseTransitionError()
+ });
+
+ // Should throw an error because carousel is in transition
+ function testCollapseTransitionError() {
+ var err = false
+ $('#collapseOne').on('hidden.bs.collapse', function (e) {
+ $(this).off('hidden.bs.collapse')
+ if (!err) {
+ alert('No error thrown for : testCollapseTransitionError')
+ }
+ })
+
+ try {
+ $('#collapseOne').collapse('hide').collapse('show')
+ }
+ catch (e) {
+ err = true
+ console.error(e.message)
+ }
+ }
+ </script>
</body>
</html>
diff --git a/js/tests/visual/modal.html b/js/tests/visual/modal.html
index fa5bd368a..69d392350 100644
--- a/js/tests/visual/modal.html
+++ b/js/tests/visual/modal.html
@@ -188,6 +188,26 @@
}
}
+ // Should throw an error because modal is in transition
+ function testModalTransitionError() {
+ var err = false
+ // Close #myModal
+ $('#myModal').on('shown.bs.modal', function () {
+ $('#myModal').modal('hide').off('shown.bs.modal')
+ if (!err) {
+ alert('No error thrown for : testModalTransitionError')
+ }
+ })
+
+ try {
+ $('#myModal').modal('show').modal('hide')
+ }
+ catch (e) {
+ err = true
+ console.error(e.message)
+ }
+ }
+
$(function () {
$('[data-toggle="popover"]').popover()
$('[data-toggle="tooltip"]').tooltip()
@@ -200,6 +220,7 @@
$('#firefoxModal').on('focus', reportFirefoxTestResult.bind(false))
$('#ff-bug-input').on('focus', reportFirefoxTestResult.bind(true))
})
+ testModalTransitionError()
})
</script>
</body>
diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html
index 999e7eda6..6cd33e7e6 100644
--- a/js/tests/visual/tooltip.html
+++ b/js/tests/visual/tooltip.html
@@ -42,7 +42,26 @@
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip()
+ testTooltipTransitionError()
})
+
+ // Should throw an error because tooltip is in transition
+ function testTooltipTransitionError() {
+ var err = false
+ $('#btnOne').on('shown.bs.tooltip', function () {
+ $('#btnOne').tooltip('hide').off('shown.bs.tooltip')
+ if (!err) {
+ alert('No error thrown for : testTooltipTransitionError')
+ }
+ })
+ try {
+ $('#btnOne').tooltip('show').tooltip('hide')
+ }
+ catch (e) {
+ err = true
+ console.error(e.message)
+ }
+ }
</script>
</body>
</html>