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
diff options
context:
space:
mode:
authorMartijn Cuppens <martijn.cuppens@gmail.com>2018-03-13 11:59:20 +0300
committerJohann-S <johann.servoire@gmail.com>2018-03-13 11:59:20 +0300
commit1fadad1c33b99b94a4a821fe5c62c8064d129424 (patch)
tree8ea41f4bf03696e7718cc7c3e1216b7153b2fc85 /js
parent1859595cb6e1c92ba8134a7c12a087cb05f89688 (diff)
Variable transition durations (#25662)
Diffstat (limited to 'js')
-rw-r--r--js/src/alert.js5
-rw-r--r--js/src/carousel.js43
-rw-r--r--js/src/collapse.js8
-rw-r--r--js/src/modal.js33
-rw-r--r--js/src/tab.js17
-rw-r--r--js/src/tooltip.js21
-rw-r--r--js/src/util.js18
-rw-r--r--js/tests/unit/util.js44
-rw-r--r--js/tests/visual/alert.html7
-rw-r--r--js/tests/visual/modal.html37
10 files changed, 167 insertions, 66 deletions
diff --git a/js/src/alert.js b/js/src/alert.js
index a1f3c1cb7f..a072b2e4eb 100644
--- a/js/src/alert.js
+++ b/js/src/alert.js
@@ -21,7 +21,6 @@ const Alert = (($) => {
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]
- const TRANSITION_DURATION = 150
const Selector = {
DISMISS : '[data-dismiss="alert"]'
@@ -109,9 +108,11 @@ const Alert = (($) => {
return
}
+ const transitionDuration = Util.getTransitionDurationFromElement(element)
+
$(element)
.one(Util.TRANSITION_END, (event) => this._destroyElement(element, event))
- .emulateTransitionEnd(TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
}
_destroyElement(element) {
diff --git a/js/src/carousel.js b/js/src/carousel.js
index 4a64e7cc8f..54bb0791c9 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -15,16 +15,15 @@ const Carousel = (($) => {
* ------------------------------------------------------------------------
*/
- const NAME = 'carousel'
- const VERSION = '4.0.0'
- const DATA_KEY = 'bs.carousel'
- const EVENT_KEY = `.${DATA_KEY}`
- const DATA_API_KEY = '.data-api'
- const JQUERY_NO_CONFLICT = $.fn[NAME]
- const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key
- const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key
- const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
- const MILLISECONDS_MULTIPLIER = 1000
+ const NAME = 'carousel'
+ const VERSION = '4.0.0'
+ const DATA_KEY = 'bs.carousel'
+ const EVENT_KEY = `.${DATA_KEY}`
+ const DATA_API_KEY = '.data-api'
+ const JQUERY_NO_CONFLICT = $.fn[NAME]
+ const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key
+ const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key
+ const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
const Default = {
interval : 5000,
@@ -102,8 +101,6 @@ const Carousel = (($) => {
this._element = $(element)[0]
this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0]
- this._transitionDuration = this._getTransitionDuration()
-
this._addEventListeners()
}
@@ -225,24 +222,6 @@ const Carousel = (($) => {
return config
}
- _getTransitionDuration() {
- // Get transition-duration of first element in the carousel
- let transitionDuration = $(this._element).find(Selector.ITEM).css('transition-duration')
-
- // Return 0 carousel item is not found
- if (!transitionDuration) {
- return 0
- }
-
- // If multiple durations are defined, take the first
- transitionDuration = transitionDuration.split(',')[0]
-
- // Multiply by 1000 if transition-duration is defined in seconds
- return transitionDuration.indexOf('ms') > -1
- ? parseFloat(transitionDuration)
- : parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER
- }
-
_addEventListeners() {
if (this._config.keyboard) {
$(this._element)
@@ -406,6 +385,8 @@ const Carousel = (($) => {
$(activeElement).addClass(directionalClassName)
$(nextElement).addClass(directionalClassName)
+ const transitionDuration = Util.getTransitionDurationFromElement(activeElement)
+
$(activeElement)
.one(Util.TRANSITION_END, () => {
$(nextElement)
@@ -418,7 +399,7 @@ const Carousel = (($) => {
setTimeout(() => $(this._element).trigger(slidEvent), 0)
})
- .emulateTransitionEnd(this._transitionDuration)
+ .emulateTransitionEnd(transitionDuration)
} else {
$(activeElement).removeClass(ClassName.ACTIVE)
$(nextElement).addClass(ClassName.ACTIVE)
diff --git a/js/src/collapse.js b/js/src/collapse.js
index 3f45d651da..ee357e37a6 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -21,7 +21,6 @@ const Collapse = (($) => {
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'
const JQUERY_NO_CONFLICT = $.fn[NAME]
- const TRANSITION_DURATION = 600
const Default = {
toggle : true,
@@ -190,10 +189,11 @@ const Collapse = (($) => {
const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)
const scrollSize = `scroll${capitalizedDimension}`
+ const transitionDuration = Util.getTransitionDurationFromElement(this._element)
$(this._element)
.one(Util.TRANSITION_END, complete)
- .emulateTransitionEnd(TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
this._element.style[dimension] = `${this._element[scrollSize]}px`
}
@@ -252,9 +252,11 @@ const Collapse = (($) => {
return
}
+ const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+
$(this._element)
.one(Util.TRANSITION_END, complete)
- .emulateTransitionEnd(TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
}
setTransitioning(isTransitioning) {
diff --git a/js/src/modal.js b/js/src/modal.js
index 12ab8bfd73..414359e97a 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -15,15 +15,13 @@ const Modal = (($) => {
* ------------------------------------------------------------------------
*/
- const NAME = 'modal'
- const VERSION = '4.0.0'
- const DATA_KEY = 'bs.modal'
- const EVENT_KEY = `.${DATA_KEY}`
- const DATA_API_KEY = '.data-api'
- const JQUERY_NO_CONFLICT = $.fn[NAME]
- const TRANSITION_DURATION = 300
- const BACKDROP_TRANSITION_DURATION = 150
- const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key
+ const NAME = 'modal'
+ const VERSION = '4.0.0'
+ const DATA_KEY = 'bs.modal'
+ const EVENT_KEY = `.${DATA_KEY}`
+ const DATA_API_KEY = '.data-api'
+ const JQUERY_NO_CONFLICT = $.fn[NAME]
+ const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key
const Default = {
backdrop : true,
@@ -187,10 +185,13 @@ const Modal = (($) => {
$(this._element).off(Event.CLICK_DISMISS)
$(this._dialog).off(Event.MOUSEDOWN_DISMISS)
+
if (transition) {
+ const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+
$(this._element)
.one(Util.TRANSITION_END, (event) => this._hideModal(event))
- .emulateTransitionEnd(TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
} else {
this._hideModal()
}
@@ -263,9 +264,11 @@ const Modal = (($) => {
}
if (transition) {
+ const transitionDuration = Util.getTransitionDurationFromElement(this._element)
+
$(this._dialog)
.one(Util.TRANSITION_END, transitionComplete)
- .emulateTransitionEnd(TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
} else {
transitionComplete()
}
@@ -369,9 +372,11 @@ const Modal = (($) => {
return
}
+ const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)
+
$(this._backdrop)
.one(Util.TRANSITION_END, callback)
- .emulateTransitionEnd(BACKDROP_TRANSITION_DURATION)
+ .emulateTransitionEnd(backdropTransitionDuration)
} else if (!this._isShown && this._backdrop) {
$(this._backdrop).removeClass(ClassName.SHOW)
@@ -384,9 +389,11 @@ const Modal = (($) => {
if (Util.supportsTransitionEnd() &&
$(this._element).hasClass(ClassName.FADE)) {
+ const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)
+
$(this._backdrop)
.one(Util.TRANSITION_END, callbackRemove)
- .emulateTransitionEnd(BACKDROP_TRANSITION_DURATION)
+ .emulateTransitionEnd(backdropTransitionDuration)
} else {
callbackRemove()
}
diff --git a/js/src/tab.js b/js/src/tab.js
index d3da382764..ebf28d76c7 100644
--- a/js/src/tab.js
+++ b/js/src/tab.js
@@ -15,13 +15,12 @@ const Tab = (($) => {
* ------------------------------------------------------------------------
*/
- const NAME = 'tab'
- const VERSION = '4.0.0'
- const DATA_KEY = 'bs.tab'
- const EVENT_KEY = `.${DATA_KEY}`
- const DATA_API_KEY = '.data-api'
- const JQUERY_NO_CONFLICT = $.fn[NAME]
- const TRANSITION_DURATION = 150
+ const NAME = 'tab'
+ const VERSION = '4.0.0'
+ const DATA_KEY = 'bs.tab'
+ const EVENT_KEY = `.${DATA_KEY}`
+ const DATA_API_KEY = '.data-api'
+ const JQUERY_NO_CONFLICT = $.fn[NAME]
const Event = {
HIDE : `hide${EVENT_KEY}`,
@@ -162,9 +161,11 @@ const Tab = (($) => {
)
if (active && isTransitioning) {
+ const transitionDuration = Util.getTransitionDurationFromElement(active)
+
$(active)
.one(Util.TRANSITION_END, complete)
- .emulateTransitionEnd(TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
} else {
complete()
}
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index 861f45a86a..19a020d43d 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -16,13 +16,12 @@ const Tooltip = (($) => {
* ------------------------------------------------------------------------
*/
- const NAME = 'tooltip'
- const VERSION = '4.0.0'
- const DATA_KEY = 'bs.tooltip'
- const EVENT_KEY = `.${DATA_KEY}`
- const JQUERY_NO_CONFLICT = $.fn[NAME]
- const TRANSITION_DURATION = 150
- const CLASS_PREFIX = 'bs-tooltip'
+ const NAME = 'tooltip'
+ const VERSION = '4.0.0'
+ const DATA_KEY = 'bs.tooltip'
+ const EVENT_KEY = `.${DATA_KEY}`
+ const JQUERY_NO_CONFLICT = $.fn[NAME]
+ const CLASS_PREFIX = 'bs-tooltip'
const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g')
const DefaultType = {
@@ -335,9 +334,11 @@ const Tooltip = (($) => {
}
if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+ const transitionDuration = Util.getTransitionDurationFromElement(this.tip)
+
$(this.tip)
.one(Util.TRANSITION_END, complete)
- .emulateTransitionEnd(Tooltip._TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
} else {
complete()
}
@@ -384,9 +385,11 @@ const Tooltip = (($) => {
if (Util.supportsTransitionEnd() &&
$(this.tip).hasClass(ClassName.FADE)) {
+ const transitionDuration = Util.getTransitionDurationFromElement(tip)
+
$(tip)
.one(Util.TRANSITION_END, complete)
- .emulateTransitionEnd(TRANSITION_DURATION)
+ .emulateTransitionEnd(transitionDuration)
} else {
complete()
}
diff --git a/js/src/util.js b/js/src/util.js
index 7e5d5de5c6..05a69977c2 100644
--- a/js/src/util.js
+++ b/js/src/util.js
@@ -17,6 +17,7 @@ const Util = (($) => {
let transition = false
const MAX_UID = 1000000
+ const MILLISECONDS_MULTIPLIER = 1000
// Shoutout AngusCroll (https://goo.gl/pxwQGp)
function toType(obj) {
@@ -104,6 +105,23 @@ const Util = (($) => {
}
},
+ getTransitionDurationFromElement(element) {
+ // Get transition-duration of the element
+ let transitionDuration = $(element).css('transition-duration')
+
+ // Return 0 if element or transition duration is not found
+ if (!transitionDuration) {
+ return 0
+ }
+
+ // If multiple durations are defined, take the first
+ transitionDuration = transitionDuration.split(',')[0]
+
+ // jQuery always converts transition durations into seconds,
+ // so multiply by 1000
+ return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER
+ },
+
reflow(element) {
return element.offsetHeight
},
diff --git a/js/tests/unit/util.js b/js/tests/unit/util.js
index 83eb601a51..46b1e35fec 100644
--- a/js/tests/unit/util.js
+++ b/js/tests/unit/util.js
@@ -42,6 +42,50 @@ $(function () {
assert.strictEqual(typeof Util.isElement({}) === 'undefined', true)
})
+ QUnit.test('Util.getTransitionDurationFromElement should accept transition durations in milliseconds', function (assert) {
+ assert.expect(1)
+ var $div = $('<div style="transition: all 300ms ease-out;"></div>').appendTo($('#qunit-fixture'))
+
+ assert.strictEqual(Util.getTransitionDurationFromElement($div), 300)
+ })
+
+ QUnit.test('Util.getTransitionDurationFromElement should accept transition durations in seconds', function (assert) {
+ assert.expect(1)
+ var $div = $('<div style="transition: all .4s ease-out;"></div>').appendTo($('#qunit-fixture'))
+
+ assert.strictEqual(Util.getTransitionDurationFromElement($div), 400)
+ })
+
+ QUnit.test('Util.getTransitionDurationFromElement should get the first transition duration if multiple transition durations are defined', function (assert) {
+ assert.expect(1)
+ var $div = $('<div style="transition: transform .3s ease-out, opacity .2s;"></div>').appendTo($('#qunit-fixture'))
+
+ assert.strictEqual(Util.getTransitionDurationFromElement($div), 300)
+ })
+
+ QUnit.test('Util.getTransitionDurationFromElement should return 0 if transition duration is not defined', function (assert) {
+ assert.expect(1)
+ var $div = $('<div></div>').appendTo($('#qunit-fixture'))
+
+ assert.strictEqual(Util.getTransitionDurationFromElement($div), 0)
+ })
+
+ QUnit.test('Util.getTransitionDurationFromElement should return 0 if element is not found in DOM', function (assert) {
+ assert.expect(1)
+ var $div = $('#fake-id')
+
+ assert.strictEqual(Util.getTransitionDurationFromElement($div), 0)
+ })
+
+ QUnit.test('Util.getTransitionDurationFromElement should properly handle inherited transition durations', function (assert) {
+ assert.expect(1)
+ var $parent = $('<div style="transition-duration: 5s;"></div>')
+ var $child = $('<div style="transition-duration: inherit;"></div>')
+ $('#qunit-fixture').append($parent.append($child))
+
+ assert.strictEqual(Util.getTransitionDurationFromElement($child), 5000)
+ })
+
QUnit.test('Util.getUID should generate a new id uniq', function (assert) {
assert.expect(2)
var id = Util.getUID('test')
diff --git a/js/tests/visual/alert.html b/js/tests/visual/alert.html
index 9baee6f506..d6b5cc350c 100644
--- a/js/tests/visual/alert.html
+++ b/js/tests/visual/alert.html
@@ -42,6 +42,13 @@
<button type="button" class="btn btn-primary">Or do this</button>
</p>
</div>
+
+ <div class="alert alert-warning alert-dismissible fade show" role="alert" style="transition-duration: 5s;">
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ This alert will take 5 seconds to fade out.
+ </div>
</div>
<script src="../../../assets/js/vendor/jquery-slim.min.js"></script>
diff --git a/js/tests/visual/modal.html b/js/tests/visual/modal.html
index 3b4cd4d3e1..d7e7767eba 100644
--- a/js/tests/visual/modal.html
+++ b/js/tests/visual/modal.html
@@ -147,6 +147,26 @@
</div>
</div>
+ <div class="modal fade" id="slowModal" tabindex="-1" role="dialog" aria-labelledby="slowModalLabel" aria-hidden="true" style="transition-duration: 5s;">
+ <div class="modal-dialog" role="document" style="transition-duration: inherit;">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ <h4 class="modal-title" id="slowModalLabel">Lorem slowly</h4>
+ </div>
+ <div class="modal-body">
+ <p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec sed odio dui. Nullam quis risus eget urna mollis ornare vel eu leo. Nulla vitae elit libero, a pharetra augue.</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-primary">Save changes</button>
+ </div>
+ </div>
+ </div>
+ </div>
+
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Launch demo modal
</button>
@@ -164,6 +184,12 @@
<br><br>
+ <button type="button" class="btn btn-secondary btn-lg" data-toggle="modal" data-target="#slowModal">
+ Launch modal with slow transition
+ </button>
+
+ <br><br>
+
<div class="bg-dark text-white p-2" id="tall" style="display: none;">
Tall body content to force the page to have a scrollbar.
</div>
@@ -225,6 +251,17 @@
})
.modal('show')
})
+
+ // Test transition duration
+ var t0, t1;
+
+ $('#slowModal').on('shown.bs.modal', function(){
+ t1 = performance.now()
+ console.log('transition-duration took ' + (t1 - t0) + 'ms.')
+ }).on('show.bs.modal', function(){
+ t0 = performance.now()
+ })
+
})
</script>
</body>