aboutsummaryrefslogtreecommitdiff
path: root/js/src
diff options
context:
space:
mode:
authorPatrick H. Lauke <[email protected]>2017-04-17 13:26:46 +0100
committerGitHub <[email protected]>2017-04-17 13:26:46 +0100
commit6ae5fb12e6c996a6526250e8cb703b007e4213fc (patch)
tree620408de7fc859370c7abfad37404d0229439e98 /js/src
parent7ffb61ac5216493bd35a3ff9283f75d58c9ad94f (diff)
downloadbootstrap-6ae5fb12e6c996a6526250e8cb703b007e4213fc.tar.xz
bootstrap-6ae5fb12e6c996a6526250e8cb703b007e4213fc.zip
Fix carousel "hover" behavior on touch-enabled devices
* Add carousel mouse listeners even if touch events enabled - touch events are enabled not just on "mobile", just also on touch-enabled desktop/laptop devices; additionally, it's possible to pair a mouse with traditionally touch-only devices (e.g. Android phones/tablets); currently, in these situations the carousel WON'T pause even when using a mouse * Restart cycle after touchend as `mouseenter` is fired as part of the touch compatibility events, the previous change results in carousels which cycle until the user tapped/interacted with them. after that they stop cycling (as `mouseleave` is not sent to the carousel after user scrolled/tapped away). this fix resets the cycling after `touchend` - essentially returning to the previous behavior, where on touch the carousel essentially never pauses, but now with the previous fix it at least pauses correctly for mouse users on touch-enabled devices. includes documentation for this new behavior.
Diffstat (limited to 'js/src')
-rw-r--r--js/src/carousel.js41
1 files changed, 30 insertions, 11 deletions
diff --git a/js/src/carousel.js b/js/src/carousel.js
index 7c2da45ad..5993de256 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -17,15 +17,16 @@ const Carousel = (($) => {
* ------------------------------------------------------------------------
*/
- const NAME = 'carousel'
- const VERSION = '4.0.0-alpha.6'
- const DATA_KEY = 'bs.carousel'
- const EVENT_KEY = `.${DATA_KEY}`
- const DATA_API_KEY = '.data-api'
- const JQUERY_NO_CONFLICT = $.fn[NAME]
- const TRANSITION_DURATION = 600
- 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 NAME = 'carousel'
+ const VERSION = '4.0.0-alpha.6'
+ const DATA_KEY = 'bs.carousel'
+ const EVENT_KEY = `.${DATA_KEY}`
+ const DATA_API_KEY = '.data-api'
+ const JQUERY_NO_CONFLICT = $.fn[NAME]
+ const TRANSITION_DURATION = 600
+ 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,
@@ -56,6 +57,7 @@ const Carousel = (($) => {
KEYDOWN : `keydown${EVENT_KEY}`,
MOUSEENTER : `mouseenter${EVENT_KEY}`,
MOUSELEAVE : `mouseleave${EVENT_KEY}`,
+ TOUCHEND : `touchend${EVENT_KEY}`,
LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
}
@@ -98,6 +100,8 @@ const Carousel = (($) => {
this._isPaused = false
this._isSliding = false
+ this.touchTimeout = null
+
this._config = this._getConfig(config)
this._element = $(element)[0]
this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0]
@@ -227,11 +231,26 @@ const Carousel = (($) => {
.on(Event.KEYDOWN, (event) => this._keydown(event))
}
- if (this._config.pause === 'hover' &&
- !('ontouchstart' in document.documentElement)) {
+ if (this._config.pause === 'hover') {
$(this._element)
.on(Event.MOUSEENTER, (event) => this.pause(event))
.on(Event.MOUSELEAVE, (event) => this.cycle(event))
+ if ('ontouchstart' in document.documentElement) {
+ // if it's a touch-enabled device, mouseenter/leave are fired as
+ // part of the mouse compatibility events on first tap - the carousel
+ // would stop cycling until user tapped out of it;
+ // here, we listen for touchend, explicitly pause the carousel
+ // (as if it's the second time we tap on it, mouseenter compat event
+ // is NOT fired) and after a timeout (to allow for mouse compatibility
+ // events to fire) we explicitly restart cycling
+ $(this._element).on(Event.TOUCHEND, () => {
+ this.pause()
+ if (this.touchTimeout) {
+ clearTimeout(this.touchTimeout)
+ }
+ this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
+ })
+ }
}
}