aboutsummaryrefslogtreecommitdiff
path: root/js/src/carousel.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/carousel.js')
-rw-r--r--js/src/carousel.js155
1 files changed, 46 insertions, 109 deletions
diff --git a/js/src/carousel.js b/js/src/carousel.js
index 3f49ded40..3589f2206 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -1,6 +1,6 @@
/**
* --------------------------------------------------------------------------
- * Bootstrap (v5.1.2): carousel.js
+ * Bootstrap (v5.1.3): carousel.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
@@ -8,9 +8,9 @@
import {
defineJQueryPlugin,
getElementFromSelector,
+ getNextActiveElement,
isRTL,
isVisible,
- getNextActiveElement,
reflow,
triggerTransitionEnd,
typeCheckConfig
@@ -18,12 +18,11 @@ import {
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selector-engine'
+import Swipe from './util/swipe'
import BaseComponent from './base-component'
/**
- * ------------------------------------------------------------------------
* Constants
- * ------------------------------------------------------------------------
*/
const NAME = 'carousel'
@@ -34,46 +33,17 @@ const DATA_API_KEY = '.data-api'
const ARROW_LEFT_KEY = 'ArrowLeft'
const ARROW_RIGHT_KEY = 'ArrowRight'
const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
-const SWIPE_THRESHOLD = 40
-
-const Default = {
- interval: 5000,
- keyboard: true,
- slide: false,
- pause: 'hover',
- wrap: true,
- touch: true
-}
-
-const DefaultType = {
- interval: '(number|boolean)',
- keyboard: 'boolean',
- slide: '(boolean|string)',
- pause: '(string|boolean)',
- wrap: 'boolean',
- touch: 'boolean'
-}
const ORDER_NEXT = 'next'
const ORDER_PREV = 'prev'
const DIRECTION_LEFT = 'left'
const DIRECTION_RIGHT = 'right'
-const KEY_TO_DIRECTION = {
- [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
- [ARROW_RIGHT_KEY]: DIRECTION_LEFT
-}
-
const EVENT_SLIDE = `slide${EVENT_KEY}`
const EVENT_SLID = `slid${EVENT_KEY}`
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`
const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`
-const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`
-const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`
-const EVENT_TOUCHEND = `touchend${EVENT_KEY}`
-const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`
-const EVENT_POINTERUP = `pointerup${EVENT_KEY}`
const EVENT_DRAG_START = `dragstart${EVENT_KEY}`
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
@@ -85,7 +55,6 @@ const CLASS_NAME_END = 'carousel-item-end'
const CLASS_NAME_START = 'carousel-item-start'
const CLASS_NAME_NEXT = 'carousel-item-next'
const CLASS_NAME_PREV = 'carousel-item-prev'
-const CLASS_NAME_POINTER_EVENT = 'pointer-event'
const SELECTOR_ACTIVE = '.active'
const SELECTOR_ACTIVE_ITEM = '.active.carousel-item'
@@ -97,14 +66,33 @@ const SELECTOR_INDICATOR = '[data-bs-target]'
const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'
const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'
-const POINTER_TYPE_TOUCH = 'touch'
-const POINTER_TYPE_PEN = 'pen'
+const KEY_TO_DIRECTION = {
+ [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
+ [ARROW_RIGHT_KEY]: DIRECTION_LEFT
+}
+
+const Default = {
+ interval: 5000,
+ keyboard: true,
+ slide: false,
+ pause: 'hover',
+ wrap: true,
+ touch: true
+}
+
+const DefaultType = {
+ interval: '(number|boolean)',
+ keyboard: 'boolean',
+ slide: '(boolean|string)',
+ pause: '(string|boolean)',
+ wrap: 'boolean',
+ touch: 'boolean'
+}
/**
- * ------------------------------------------------------------------------
- * Class Definition
- * ------------------------------------------------------------------------
+ * Class definition
*/
+
class Carousel extends BaseComponent {
constructor(element, config) {
super(element)
@@ -115,19 +103,14 @@ class Carousel extends BaseComponent {
this._isPaused = false
this._isSliding = false
this.touchTimeout = null
- this.touchStartX = 0
- this.touchDeltaX = 0
+ this._swipeHelper = null
this._config = this._getConfig(config)
this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)
- this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
- this._pointerEvent = Boolean(window.PointerEvent)
-
this._addEventListeners()
}
// Getters
-
static get Default() {
return Default
}
@@ -137,7 +120,6 @@ class Carousel extends BaseComponent {
}
// Public
-
next() {
this._slide(ORDER_NEXT)
}
@@ -214,8 +196,15 @@ class Carousel extends BaseComponent {
this._slide(order, this._items[index])
}
- // Private
+ dispose() {
+ if (this._swipeHelper) {
+ this._swipeHelper.dispose()
+ }
+
+ super.dispose()
+ }
+ // Private
_getConfig(config) {
config = {
...Default,
@@ -226,24 +215,6 @@ class Carousel extends BaseComponent {
return config
}
- _handleSwipe() {
- const absDeltax = Math.abs(this.touchDeltaX)
-
- if (absDeltax <= SWIPE_THRESHOLD) {
- return
- }
-
- const direction = absDeltax / this.touchDeltaX
-
- this.touchDeltaX = 0
-
- if (!direction) {
- return
- }
-
- this._slide(direction > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT)
- }
-
_addEventListeners() {
if (this._config.keyboard) {
EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event))
@@ -254,38 +225,17 @@ class Carousel extends BaseComponent {
EventHandler.on(this._element, EVENT_MOUSELEAVE, event => this.cycle(event))
}
- if (this._config.touch && this._touchSupported) {
+ if (this._config.touch && Swipe.isSupported()) {
this._addTouchEventListeners()
}
}
_addTouchEventListeners() {
- const hasPointerPenTouch = event => {
- return this._pointerEvent &&
- (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
- }
-
- const start = event => {
- if (hasPointerPenTouch(event)) {
- this.touchStartX = event.clientX
- } else if (!this._pointerEvent) {
- this.touchStartX = event.touches[0].clientX
- }
- }
-
- const move = event => {
- // ensure swiping with one touch and not pinching
- this.touchDeltaX = event.touches && event.touches.length > 1 ?
- 0 :
- event.touches[0].clientX - this.touchStartX
+ for (const itemImg of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {
+ EventHandler.on(itemImg, EVENT_DRAG_START, event => event.preventDefault())
}
- const end = event => {
- if (hasPointerPenTouch(event)) {
- this.touchDeltaX = event.clientX - this.touchStartX
- }
-
- this._handleSwipe()
+ const endCallBack = () => {
if (this._config.pause === 'hover') {
// If it's a touch-enabled device, mouseenter/leave are fired as
// part of the mouse compatibility events on first tap - the carousel
@@ -304,20 +254,13 @@ class Carousel extends BaseComponent {
}
}
- for (const itemImg of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {
- EventHandler.on(itemImg, EVENT_DRAG_START, event => event.preventDefault())
+ const swipeConfig = {
+ leftCallback: () => this._slide(DIRECTION_LEFT),
+ rightCallback: () => this._slide(DIRECTION_RIGHT),
+ endCallback: endCallBack
}
- if (this._pointerEvent) {
- EventHandler.on(this._element, EVENT_POINTERDOWN, event => start(event))
- EventHandler.on(this._element, EVENT_POINTERUP, event => end(event))
-
- this._element.classList.add(CLASS_NAME_POINTER_EVENT)
- } else {
- EventHandler.on(this._element, EVENT_TOUCHSTART, event => start(event))
- EventHandler.on(this._element, EVENT_TOUCHMOVE, event => move(event))
- EventHandler.on(this._element, EVENT_TOUCHEND, event => end(event))
- }
+ this._swipeHelper = new Swipe(this._element, swipeConfig)
}
_keydown(event) {
@@ -502,7 +445,6 @@ class Carousel extends BaseComponent {
}
// Static
-
static carouselInterface(element, config) {
const data = Carousel.getOrCreateInstance(element, config)
@@ -564,9 +506,7 @@ class Carousel extends BaseComponent {
}
/**
- * ------------------------------------------------------------------------
- * Data Api implementation
- * ------------------------------------------------------------------------
+ * Data API implementation
*/
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler)
@@ -580,10 +520,7 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
})
/**
- * ------------------------------------------------------------------------
* jQuery
- * ------------------------------------------------------------------------
- * add .Carousel to jQuery only if jQuery is present
*/
defineJQueryPlugin(Carousel)