@openeuropa/bcl-bootstrap 0.25.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bootstrap-icons.svg +1 -1
- package/icons/apple.svg +2 -2
- package/icons/boombox-fill.svg +2 -2
- package/icons/cup-fill.svg +1 -1
- package/icons/cup.svg +1 -1
- package/js/dist/alert.js +3 -12
- package/js/dist/alert.js.map +1 -1
- package/js/dist/base-component.js +32 -18
- package/js/dist/base-component.js.map +1 -1
- package/js/dist/button.js +3 -12
- package/js/dist/button.js.map +1 -1
- package/js/dist/carousel.js +207 -307
- package/js/dist/carousel.js.map +1 -1
- package/js/dist/collapse.js +57 -88
- package/js/dist/collapse.js.map +1 -1
- package/js/dist/dom/data.js +1 -3
- package/js/dist/dom/data.js.map +1 -1
- package/js/dist/dom/event-handler.js +87 -106
- package/js/dist/dom/event-handler.js.map +1 -1
- package/js/dist/dom/manipulator.js +21 -25
- package/js/dist/dom/manipulator.js.map +1 -1
- package/js/dist/dom/selector-engine.js +11 -10
- package/js/dist/dom/selector-engine.js.map +1 -1
- package/js/dist/dropdown.js +83 -115
- package/js/dist/dropdown.js.map +1 -1
- package/js/dist/modal.js +95 -152
- package/js/dist/modal.js.map +1 -1
- package/js/dist/offcanvas.js +75 -58
- package/js/dist/offcanvas.js.map +1 -1
- package/js/dist/popover.js +29 -56
- package/js/dist/popover.js.map +1 -1
- package/js/dist/scrollspy.js +176 -125
- package/js/dist/scrollspy.js.map +1 -1
- package/js/dist/tab.js +207 -92
- package/js/dist/tab.js.map +1 -1
- package/js/dist/toast.js +23 -37
- package/js/dist/toast.js.map +1 -1
- package/js/dist/tooltip.js +259 -348
- package/js/dist/tooltip.js.map +1 -1
- package/js/dist/util/backdrop.js +62 -39
- package/js/dist/util/backdrop.js.map +1 -1
- package/js/dist/util/component-functions.js +1 -1
- package/js/dist/util/component-functions.js.map +1 -1
- package/js/dist/util/config.js +75 -0
- package/js/dist/util/config.js.map +1 -0
- package/js/dist/util/focustrap.js +41 -34
- package/js/dist/util/focustrap.js.map +1 -1
- package/js/dist/util/index.js +56 -52
- package/js/dist/util/index.js.map +1 -1
- package/js/dist/util/sanitizer.js +12 -19
- package/js/dist/util/sanitizer.js.map +1 -1
- package/js/dist/util/scrollbar.js +49 -34
- package/js/dist/util/scrollbar.js.map +1 -1
- package/js/dist/util/swipe.js +151 -0
- package/js/dist/util/swipe.js.map +1 -0
- package/js/dist/util/template-factory.js +173 -0
- package/js/dist/util/template-factory.js.map +1 -0
- package/js/src/alert.js +3 -15
- package/js/src/base-component.js +28 -18
- package/js/src/button.js +3 -17
- package/js/src/carousel.js +203 -319
- package/js/src/collapse.js +61 -94
- package/js/src/dom/data.js +1 -3
- package/js/src/dom/event-handler.js +80 -108
- package/js/src/dom/manipulator.js +22 -31
- package/js/src/dom/selector-engine.js +10 -19
- package/js/src/dropdown.js +84 -138
- package/js/src/modal.js +94 -158
- package/js/src/offcanvas.js +72 -61
- package/js/src/popover.js +31 -62
- package/js/src/scrollspy.js +166 -171
- package/js/src/tab.js +193 -110
- package/js/src/toast.js +19 -41
- package/js/src/tooltip.js +259 -371
- package/js/src/util/backdrop.js +55 -36
- package/js/src/util/component-functions.js +1 -1
- package/js/src/util/config.js +66 -0
- package/js/src/util/focustrap.js +38 -28
- package/js/src/util/index.js +67 -64
- package/js/src/util/sanitizer.js +11 -19
- package/js/src/util/scrollbar.js +47 -30
- package/js/src/util/swipe.js +146 -0
- package/js/src/util/template-factory.js +160 -0
- package/package.json +4 -4
- package/scss/_accordion.scss +52 -24
- package/scss/_alert.scss +18 -4
- package/scss/_badge.scss +14 -5
- package/scss/_breadcrumb.scss +22 -10
- package/scss/_button-group.scss +3 -0
- package/scss/_buttons.scss +97 -22
- package/scss/_card.scss +55 -37
- package/scss/_close.scss +1 -1
- package/scss/_containers.scss +1 -1
- package/scss/_dropdown.scss +83 -75
- package/scss/_functions.scss +7 -7
- package/scss/_grid.scss +3 -3
- package/scss/_helpers.scss +1 -0
- package/scss/_list-group.scss +44 -27
- package/scss/_maps.scss +54 -0
- package/scss/_modal.scss +71 -43
- package/scss/_nav.scss +53 -20
- package/scss/_navbar.scss +91 -150
- package/scss/_offcanvas.scss +119 -59
- package/scss/_pagination.scss +66 -21
- package/scss/_placeholders.scss +1 -1
- package/scss/_popover.scss +90 -52
- package/scss/_progress.scss +20 -9
- package/scss/_reboot.scss +25 -40
- package/scss/_root.scss +40 -21
- package/scss/_spinners.scss +38 -22
- package/scss/_tables.scss +32 -23
- package/scss/_toasts.scss +35 -16
- package/scss/_tooltip.scss +61 -56
- package/scss/_type.scss +2 -0
- package/scss/_utilities.scss +43 -26
- package/scss/_variables.scss +113 -121
- package/scss/bootstrap-grid.scss +3 -6
- package/scss/bootstrap-reboot.scss +3 -7
- package/scss/bootstrap-utilities.scss +3 -6
- package/scss/bootstrap.scss +4 -6
- package/scss/forms/_floating-labels.scss +14 -3
- package/scss/forms/_form-check.scss +28 -5
- package/scss/forms/_form-control.scss +12 -37
- package/scss/forms/_form-select.scss +0 -1
- package/scss/forms/_input-group.scss +15 -7
- package/scss/helpers/_color-bg.scss +10 -0
- package/scss/helpers/_colored-links.scss +2 -2
- package/scss/helpers/_position.scss +7 -1
- package/scss/helpers/_ratio.scss +2 -2
- package/scss/helpers/_vr.scss +1 -1
- package/scss/mixins/_alert.scss +7 -3
- package/scss/mixins/_banner.scss +9 -0
- package/scss/mixins/_breakpoints.scss +8 -8
- package/scss/mixins/_buttons.scss +32 -95
- package/scss/mixins/_container.scss +4 -2
- package/scss/mixins/_forms.scss +8 -0
- package/scss/mixins/_gradients.scss +1 -1
- package/scss/mixins/_grid.scss +12 -12
- package/scss/mixins/_pagination.scss +4 -25
- package/scss/mixins/_reset-text.scss +1 -1
- package/scss/mixins/_table-variants.scss +12 -9
- package/scss/mixins/_utilities.scss +12 -4
package/js/src/carousel.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* --------------------------------------------------------------------------
|
|
3
|
-
* Bootstrap (v5.
|
|
3
|
+
* Bootstrap (v5.2.0): carousel.js
|
|
4
4
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
5
5
|
* --------------------------------------------------------------------------
|
|
6
6
|
*/
|
|
@@ -8,22 +8,20 @@
|
|
|
8
8
|
import {
|
|
9
9
|
defineJQueryPlugin,
|
|
10
10
|
getElementFromSelector,
|
|
11
|
+
getNextActiveElement,
|
|
11
12
|
isRTL,
|
|
12
13
|
isVisible,
|
|
13
|
-
getNextActiveElement,
|
|
14
14
|
reflow,
|
|
15
|
-
triggerTransitionEnd
|
|
16
|
-
typeCheckConfig
|
|
15
|
+
triggerTransitionEnd
|
|
17
16
|
} from './util/index'
|
|
18
17
|
import EventHandler from './dom/event-handler'
|
|
19
18
|
import Manipulator from './dom/manipulator'
|
|
20
19
|
import SelectorEngine from './dom/selector-engine'
|
|
20
|
+
import Swipe from './util/swipe'
|
|
21
21
|
import BaseComponent from './base-component'
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* ------------------------------------------------------------------------
|
|
25
24
|
* Constants
|
|
26
|
-
* ------------------------------------------------------------------------
|
|
27
25
|
*/
|
|
28
26
|
|
|
29
27
|
const NAME = 'carousel'
|
|
@@ -34,46 +32,17 @@ const DATA_API_KEY = '.data-api'
|
|
|
34
32
|
const ARROW_LEFT_KEY = 'ArrowLeft'
|
|
35
33
|
const ARROW_RIGHT_KEY = 'ArrowRight'
|
|
36
34
|
const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
|
|
37
|
-
const SWIPE_THRESHOLD = 40
|
|
38
|
-
|
|
39
|
-
const Default = {
|
|
40
|
-
interval: 5000,
|
|
41
|
-
keyboard: true,
|
|
42
|
-
slide: false,
|
|
43
|
-
pause: 'hover',
|
|
44
|
-
wrap: true,
|
|
45
|
-
touch: true
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const DefaultType = {
|
|
49
|
-
interval: '(number|boolean)',
|
|
50
|
-
keyboard: 'boolean',
|
|
51
|
-
slide: '(boolean|string)',
|
|
52
|
-
pause: '(string|boolean)',
|
|
53
|
-
wrap: 'boolean',
|
|
54
|
-
touch: 'boolean'
|
|
55
|
-
}
|
|
56
35
|
|
|
57
36
|
const ORDER_NEXT = 'next'
|
|
58
37
|
const ORDER_PREV = 'prev'
|
|
59
38
|
const DIRECTION_LEFT = 'left'
|
|
60
39
|
const DIRECTION_RIGHT = 'right'
|
|
61
40
|
|
|
62
|
-
const KEY_TO_DIRECTION = {
|
|
63
|
-
[ARROW_LEFT_KEY]: DIRECTION_RIGHT,
|
|
64
|
-
[ARROW_RIGHT_KEY]: DIRECTION_LEFT
|
|
65
|
-
}
|
|
66
|
-
|
|
67
41
|
const EVENT_SLIDE = `slide${EVENT_KEY}`
|
|
68
42
|
const EVENT_SLID = `slid${EVENT_KEY}`
|
|
69
43
|
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
|
|
70
44
|
const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`
|
|
71
45
|
const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`
|
|
72
|
-
const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`
|
|
73
|
-
const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`
|
|
74
|
-
const EVENT_TOUCHEND = `touchend${EVENT_KEY}`
|
|
75
|
-
const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`
|
|
76
|
-
const EVENT_POINTERUP = `pointerup${EVENT_KEY}`
|
|
77
46
|
const EVENT_DRAG_START = `dragstart${EVENT_KEY}`
|
|
78
47
|
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
|
|
79
48
|
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
|
|
@@ -85,64 +54,80 @@ const CLASS_NAME_END = 'carousel-item-end'
|
|
|
85
54
|
const CLASS_NAME_START = 'carousel-item-start'
|
|
86
55
|
const CLASS_NAME_NEXT = 'carousel-item-next'
|
|
87
56
|
const CLASS_NAME_PREV = 'carousel-item-prev'
|
|
88
|
-
const CLASS_NAME_POINTER_EVENT = 'pointer-event'
|
|
89
57
|
|
|
90
58
|
const SELECTOR_ACTIVE = '.active'
|
|
91
|
-
const SELECTOR_ACTIVE_ITEM = '.active.carousel-item'
|
|
92
59
|
const SELECTOR_ITEM = '.carousel-item'
|
|
60
|
+
const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM
|
|
93
61
|
const SELECTOR_ITEM_IMG = '.carousel-item img'
|
|
94
|
-
const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev'
|
|
95
62
|
const SELECTOR_INDICATORS = '.carousel-indicators'
|
|
96
|
-
const SELECTOR_INDICATOR = '[data-bs-target]'
|
|
97
63
|
const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'
|
|
98
64
|
const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'
|
|
99
65
|
|
|
100
|
-
const
|
|
101
|
-
|
|
66
|
+
const KEY_TO_DIRECTION = {
|
|
67
|
+
[ARROW_LEFT_KEY]: DIRECTION_RIGHT,
|
|
68
|
+
[ARROW_RIGHT_KEY]: DIRECTION_LEFT
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const Default = {
|
|
72
|
+
interval: 5000,
|
|
73
|
+
keyboard: true,
|
|
74
|
+
pause: 'hover',
|
|
75
|
+
ride: false,
|
|
76
|
+
touch: true,
|
|
77
|
+
wrap: true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const DefaultType = {
|
|
81
|
+
interval: '(number|boolean)', // TODO:v6 remove boolean support
|
|
82
|
+
keyboard: 'boolean',
|
|
83
|
+
pause: '(string|boolean)',
|
|
84
|
+
ride: '(boolean|string)',
|
|
85
|
+
touch: 'boolean',
|
|
86
|
+
wrap: 'boolean'
|
|
87
|
+
}
|
|
102
88
|
|
|
103
89
|
/**
|
|
104
|
-
*
|
|
105
|
-
* Class Definition
|
|
106
|
-
* ------------------------------------------------------------------------
|
|
90
|
+
* Class definition
|
|
107
91
|
*/
|
|
92
|
+
|
|
108
93
|
class Carousel extends BaseComponent {
|
|
109
94
|
constructor(element, config) {
|
|
110
|
-
super(element)
|
|
95
|
+
super(element, config)
|
|
111
96
|
|
|
112
|
-
this._items = null
|
|
113
97
|
this._interval = null
|
|
114
98
|
this._activeElement = null
|
|
115
|
-
this._isPaused = false
|
|
116
99
|
this._isSliding = false
|
|
117
100
|
this.touchTimeout = null
|
|
118
|
-
this.
|
|
119
|
-
this.touchDeltaX = 0
|
|
101
|
+
this._swipeHelper = null
|
|
120
102
|
|
|
121
|
-
this._config = this._getConfig(config)
|
|
122
103
|
this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)
|
|
123
|
-
this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
|
|
124
|
-
this._pointerEvent = Boolean(window.PointerEvent)
|
|
125
|
-
|
|
126
104
|
this._addEventListeners()
|
|
105
|
+
|
|
106
|
+
if (this._config.ride === CLASS_NAME_CAROUSEL) {
|
|
107
|
+
this.cycle()
|
|
108
|
+
}
|
|
127
109
|
}
|
|
128
110
|
|
|
129
111
|
// Getters
|
|
130
|
-
|
|
131
112
|
static get Default() {
|
|
132
113
|
return Default
|
|
133
114
|
}
|
|
134
115
|
|
|
116
|
+
static get DefaultType() {
|
|
117
|
+
return DefaultType
|
|
118
|
+
}
|
|
119
|
+
|
|
135
120
|
static get NAME() {
|
|
136
121
|
return NAME
|
|
137
122
|
}
|
|
138
123
|
|
|
139
124
|
// Public
|
|
140
|
-
|
|
141
125
|
next() {
|
|
142
126
|
this._slide(ORDER_NEXT)
|
|
143
127
|
}
|
|
144
128
|
|
|
145
129
|
nextWhenVisible() {
|
|
130
|
+
// FIXME TODO use `document.visibilityState`
|
|
146
131
|
// Don't call next when the page isn't visible
|
|
147
132
|
// or the carousel or its parent isn't visible
|
|
148
133
|
if (!document.hidden && isVisible(this._element)) {
|
|
@@ -154,45 +139,37 @@ class Carousel extends BaseComponent {
|
|
|
154
139
|
this._slide(ORDER_PREV)
|
|
155
140
|
}
|
|
156
141
|
|
|
157
|
-
pause(
|
|
158
|
-
if (
|
|
159
|
-
this._isPaused = true
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (SelectorEngine.findOne(SELECTOR_NEXT_PREV, this._element)) {
|
|
142
|
+
pause() {
|
|
143
|
+
if (this._isSliding) {
|
|
163
144
|
triggerTransitionEnd(this._element)
|
|
164
|
-
this.cycle(true)
|
|
165
145
|
}
|
|
166
146
|
|
|
167
|
-
|
|
168
|
-
this._interval = null
|
|
147
|
+
this._clearInterval()
|
|
169
148
|
}
|
|
170
149
|
|
|
171
|
-
cycle(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
150
|
+
cycle() {
|
|
151
|
+
this._clearInterval()
|
|
152
|
+
this._updateInterval()
|
|
175
153
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
this._interval = null
|
|
179
|
-
}
|
|
154
|
+
this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval)
|
|
155
|
+
}
|
|
180
156
|
|
|
181
|
-
|
|
182
|
-
|
|
157
|
+
_maybeEnableCycle() {
|
|
158
|
+
if (!this._config.ride) {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
183
161
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
162
|
+
if (this._isSliding) {
|
|
163
|
+
EventHandler.one(this._element, EVENT_SLID, () => this.cycle())
|
|
164
|
+
return
|
|
188
165
|
}
|
|
166
|
+
|
|
167
|
+
this.cycle()
|
|
189
168
|
}
|
|
190
169
|
|
|
191
170
|
to(index) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (index > this._items.length - 1 || index < 0) {
|
|
171
|
+
const items = this._getItems()
|
|
172
|
+
if (index > items.length - 1 || index < 0) {
|
|
196
173
|
return
|
|
197
174
|
}
|
|
198
175
|
|
|
@@ -201,47 +178,28 @@ class Carousel extends BaseComponent {
|
|
|
201
178
|
return
|
|
202
179
|
}
|
|
203
180
|
|
|
181
|
+
const activeIndex = this._getItemIndex(this._getActive())
|
|
204
182
|
if (activeIndex === index) {
|
|
205
|
-
this.pause()
|
|
206
|
-
this.cycle()
|
|
207
183
|
return
|
|
208
184
|
}
|
|
209
185
|
|
|
210
|
-
const order = index > activeIndex ?
|
|
211
|
-
ORDER_NEXT :
|
|
212
|
-
ORDER_PREV
|
|
186
|
+
const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV
|
|
213
187
|
|
|
214
|
-
this._slide(order,
|
|
188
|
+
this._slide(order, items[index])
|
|
215
189
|
}
|
|
216
190
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
config = {
|
|
221
|
-
...Default,
|
|
222
|
-
...Manipulator.getDataAttributes(this._element),
|
|
223
|
-
...(typeof config === 'object' ? config : {})
|
|
191
|
+
dispose() {
|
|
192
|
+
if (this._swipeHelper) {
|
|
193
|
+
this._swipeHelper.dispose()
|
|
224
194
|
}
|
|
225
|
-
typeCheckConfig(NAME, config, DefaultType)
|
|
226
|
-
return config
|
|
227
|
-
}
|
|
228
195
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (absDeltax <= SWIPE_THRESHOLD) {
|
|
233
|
-
return
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const direction = absDeltax / this.touchDeltaX
|
|
237
|
-
|
|
238
|
-
this.touchDeltaX = 0
|
|
239
|
-
|
|
240
|
-
if (!direction) {
|
|
241
|
-
return
|
|
242
|
-
}
|
|
196
|
+
super.dispose()
|
|
197
|
+
}
|
|
243
198
|
|
|
244
|
-
|
|
199
|
+
// Private
|
|
200
|
+
_configAfterMerge(config) {
|
|
201
|
+
config.defaultInterval = config.interval
|
|
202
|
+
return config
|
|
245
203
|
}
|
|
246
204
|
|
|
247
205
|
_addEventListeners() {
|
|
@@ -250,74 +208,48 @@ class Carousel extends BaseComponent {
|
|
|
250
208
|
}
|
|
251
209
|
|
|
252
210
|
if (this._config.pause === 'hover') {
|
|
253
|
-
EventHandler.on(this._element, EVENT_MOUSEENTER,
|
|
254
|
-
EventHandler.on(this._element, EVENT_MOUSELEAVE,
|
|
211
|
+
EventHandler.on(this._element, EVENT_MOUSEENTER, () => this.pause())
|
|
212
|
+
EventHandler.on(this._element, EVENT_MOUSELEAVE, () => this._maybeEnableCycle())
|
|
255
213
|
}
|
|
256
214
|
|
|
257
|
-
if (this._config.touch &&
|
|
215
|
+
if (this._config.touch && Swipe.isSupported()) {
|
|
258
216
|
this._addTouchEventListeners()
|
|
259
217
|
}
|
|
260
218
|
}
|
|
261
219
|
|
|
262
220
|
_addTouchEventListeners() {
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
(event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
|
|
221
|
+
for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {
|
|
222
|
+
EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault())
|
|
266
223
|
}
|
|
267
224
|
|
|
268
|
-
const
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
} else if (!this._pointerEvent) {
|
|
272
|
-
this.touchStartX = event.touches[0].clientX
|
|
225
|
+
const endCallBack = () => {
|
|
226
|
+
if (this._config.pause !== 'hover') {
|
|
227
|
+
return
|
|
273
228
|
}
|
|
274
|
-
}
|
|
275
229
|
|
|
276
|
-
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
230
|
+
// If it's a touch-enabled device, mouseenter/leave are fired as
|
|
231
|
+
// part of the mouse compatibility events on first tap - the carousel
|
|
232
|
+
// would stop cycling until user tapped out of it;
|
|
233
|
+
// here, we listen for touchend, explicitly pause the carousel
|
|
234
|
+
// (as if it's the second time we tap on it, mouseenter compat event
|
|
235
|
+
// is NOT fired) and after a timeout (to allow for mouse compatibility
|
|
236
|
+
// events to fire) we explicitly restart cycling
|
|
282
237
|
|
|
283
|
-
|
|
284
|
-
if (
|
|
285
|
-
this.
|
|
238
|
+
this.pause()
|
|
239
|
+
if (this.touchTimeout) {
|
|
240
|
+
clearTimeout(this.touchTimeout)
|
|
286
241
|
}
|
|
287
242
|
|
|
288
|
-
this.
|
|
289
|
-
if (this._config.pause === 'hover') {
|
|
290
|
-
// If it's a touch-enabled device, mouseenter/leave are fired as
|
|
291
|
-
// part of the mouse compatibility events on first tap - the carousel
|
|
292
|
-
// would stop cycling until user tapped out of it;
|
|
293
|
-
// here, we listen for touchend, explicitly pause the carousel
|
|
294
|
-
// (as if it's the second time we tap on it, mouseenter compat event
|
|
295
|
-
// is NOT fired) and after a timeout (to allow for mouse compatibility
|
|
296
|
-
// events to fire) we explicitly restart cycling
|
|
297
|
-
|
|
298
|
-
this.pause()
|
|
299
|
-
if (this.touchTimeout) {
|
|
300
|
-
clearTimeout(this.touchTimeout)
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
|
|
304
|
-
}
|
|
243
|
+
this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
|
|
305
244
|
}
|
|
306
245
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (this._pointerEvent) {
|
|
312
|
-
EventHandler.on(this._element, EVENT_POINTERDOWN, event => start(event))
|
|
313
|
-
EventHandler.on(this._element, EVENT_POINTERUP, event => end(event))
|
|
314
|
-
|
|
315
|
-
this._element.classList.add(CLASS_NAME_POINTER_EVENT)
|
|
316
|
-
} else {
|
|
317
|
-
EventHandler.on(this._element, EVENT_TOUCHSTART, event => start(event))
|
|
318
|
-
EventHandler.on(this._element, EVENT_TOUCHMOVE, event => move(event))
|
|
319
|
-
EventHandler.on(this._element, EVENT_TOUCHEND, event => end(event))
|
|
246
|
+
const swipeConfig = {
|
|
247
|
+
leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),
|
|
248
|
+
rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),
|
|
249
|
+
endCallback: endCallBack
|
|
320
250
|
}
|
|
251
|
+
|
|
252
|
+
this._swipeHelper = new Swipe(this._element, swipeConfig)
|
|
321
253
|
}
|
|
322
254
|
|
|
323
255
|
_keydown(event) {
|
|
@@ -328,56 +260,34 @@ class Carousel extends BaseComponent {
|
|
|
328
260
|
const direction = KEY_TO_DIRECTION[event.key]
|
|
329
261
|
if (direction) {
|
|
330
262
|
event.preventDefault()
|
|
331
|
-
this._slide(direction)
|
|
263
|
+
this._slide(this._directionToOrder(direction))
|
|
332
264
|
}
|
|
333
265
|
}
|
|
334
266
|
|
|
335
267
|
_getItemIndex(element) {
|
|
336
|
-
this.
|
|
337
|
-
SelectorEngine.find(SELECTOR_ITEM, element.parentNode) :
|
|
338
|
-
[]
|
|
339
|
-
|
|
340
|
-
return this._items.indexOf(element)
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
_getItemByOrder(order, activeElement) {
|
|
344
|
-
const isNext = order === ORDER_NEXT
|
|
345
|
-
return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap)
|
|
268
|
+
return this._getItems().indexOf(element)
|
|
346
269
|
}
|
|
347
270
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return EventHandler.trigger(this._element, EVENT_SLIDE, {
|
|
353
|
-
relatedTarget,
|
|
354
|
-
direction: eventDirectionName,
|
|
355
|
-
from: fromIndex,
|
|
356
|
-
to: targetIndex
|
|
357
|
-
})
|
|
358
|
-
}
|
|
271
|
+
_setActiveIndicatorElement(index) {
|
|
272
|
+
if (!this._indicatorsElement) {
|
|
273
|
+
return
|
|
274
|
+
}
|
|
359
275
|
|
|
360
|
-
|
|
361
|
-
if (this._indicatorsElement) {
|
|
362
|
-
const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement)
|
|
276
|
+
const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement)
|
|
363
277
|
|
|
364
|
-
|
|
365
|
-
|
|
278
|
+
activeIndicator.classList.remove(CLASS_NAME_ACTIVE)
|
|
279
|
+
activeIndicator.removeAttribute('aria-current')
|
|
366
280
|
|
|
367
|
-
|
|
281
|
+
const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement)
|
|
368
282
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
indicators[i].setAttribute('aria-current', 'true')
|
|
373
|
-
break
|
|
374
|
-
}
|
|
375
|
-
}
|
|
283
|
+
if (newActiveIndicator) {
|
|
284
|
+
newActiveIndicator.classList.add(CLASS_NAME_ACTIVE)
|
|
285
|
+
newActiveIndicator.setAttribute('aria-current', 'true')
|
|
376
286
|
}
|
|
377
287
|
}
|
|
378
288
|
|
|
379
289
|
_updateInterval() {
|
|
380
|
-
const element = this._activeElement ||
|
|
290
|
+
const element = this._activeElement || this._getActive()
|
|
381
291
|
|
|
382
292
|
if (!element) {
|
|
383
293
|
return
|
|
@@ -385,103 +295,101 @@ class Carousel extends BaseComponent {
|
|
|
385
295
|
|
|
386
296
|
const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10)
|
|
387
297
|
|
|
388
|
-
|
|
389
|
-
this._config.defaultInterval = this._config.defaultInterval || this._config.interval
|
|
390
|
-
this._config.interval = elementInterval
|
|
391
|
-
} else {
|
|
392
|
-
this._config.interval = this._config.defaultInterval || this._config.interval
|
|
393
|
-
}
|
|
298
|
+
this._config.interval = elementInterval || this._config.defaultInterval
|
|
394
299
|
}
|
|
395
300
|
|
|
396
|
-
_slide(
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const nextElement = element || this._getItemByOrder(order, activeElement)
|
|
401
|
-
|
|
402
|
-
const nextElementIndex = this._getItemIndex(nextElement)
|
|
403
|
-
const isCycling = Boolean(this._interval)
|
|
301
|
+
_slide(order, element = null) {
|
|
302
|
+
if (this._isSliding) {
|
|
303
|
+
return
|
|
304
|
+
}
|
|
404
305
|
|
|
306
|
+
const activeElement = this._getActive()
|
|
405
307
|
const isNext = order === ORDER_NEXT
|
|
406
|
-
const
|
|
407
|
-
const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV
|
|
408
|
-
const eventDirectionName = this._orderToDirection(order)
|
|
308
|
+
const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap)
|
|
409
309
|
|
|
410
|
-
if (nextElement
|
|
411
|
-
this._isSliding = false
|
|
310
|
+
if (nextElement === activeElement) {
|
|
412
311
|
return
|
|
413
312
|
}
|
|
414
313
|
|
|
415
|
-
|
|
416
|
-
|
|
314
|
+
const nextElementIndex = this._getItemIndex(nextElement)
|
|
315
|
+
|
|
316
|
+
const triggerEvent = eventName => {
|
|
317
|
+
return EventHandler.trigger(this._element, eventName, {
|
|
318
|
+
relatedTarget: nextElement,
|
|
319
|
+
direction: this._orderToDirection(order),
|
|
320
|
+
from: this._getItemIndex(activeElement),
|
|
321
|
+
to: nextElementIndex
|
|
322
|
+
})
|
|
417
323
|
}
|
|
418
324
|
|
|
419
|
-
const slideEvent =
|
|
325
|
+
const slideEvent = triggerEvent(EVENT_SLIDE)
|
|
326
|
+
|
|
420
327
|
if (slideEvent.defaultPrevented) {
|
|
421
328
|
return
|
|
422
329
|
}
|
|
423
330
|
|
|
424
331
|
if (!activeElement || !nextElement) {
|
|
425
332
|
// Some weirdness is happening, so we bail
|
|
333
|
+
// todo: change tests that use empty divs to avoid this check
|
|
426
334
|
return
|
|
427
335
|
}
|
|
428
336
|
|
|
429
|
-
|
|
337
|
+
const isCycling = Boolean(this._interval)
|
|
338
|
+
this.pause()
|
|
430
339
|
|
|
431
|
-
|
|
432
|
-
this.pause()
|
|
433
|
-
}
|
|
340
|
+
this._isSliding = true
|
|
434
341
|
|
|
435
|
-
this._setActiveIndicatorElement(
|
|
342
|
+
this._setActiveIndicatorElement(nextElementIndex)
|
|
436
343
|
this._activeElement = nextElement
|
|
437
344
|
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
relatedTarget: nextElement,
|
|
441
|
-
direction: eventDirectionName,
|
|
442
|
-
from: activeElementIndex,
|
|
443
|
-
to: nextElementIndex
|
|
444
|
-
})
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
if (this._element.classList.contains(CLASS_NAME_SLIDE)) {
|
|
448
|
-
nextElement.classList.add(orderClassName)
|
|
449
|
-
|
|
450
|
-
reflow(nextElement)
|
|
451
|
-
|
|
452
|
-
activeElement.classList.add(directionalClassName)
|
|
453
|
-
nextElement.classList.add(directionalClassName)
|
|
454
|
-
|
|
455
|
-
const completeCallBack = () => {
|
|
456
|
-
nextElement.classList.remove(directionalClassName, orderClassName)
|
|
457
|
-
nextElement.classList.add(CLASS_NAME_ACTIVE)
|
|
345
|
+
const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END
|
|
346
|
+
const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV
|
|
458
347
|
|
|
459
|
-
|
|
348
|
+
nextElement.classList.add(orderClassName)
|
|
460
349
|
|
|
461
|
-
|
|
350
|
+
reflow(nextElement)
|
|
462
351
|
|
|
463
|
-
|
|
464
|
-
|
|
352
|
+
activeElement.classList.add(directionalClassName)
|
|
353
|
+
nextElement.classList.add(directionalClassName)
|
|
465
354
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
activeElement.classList.remove(CLASS_NAME_ACTIVE)
|
|
355
|
+
const completeCallBack = () => {
|
|
356
|
+
nextElement.classList.remove(directionalClassName, orderClassName)
|
|
469
357
|
nextElement.classList.add(CLASS_NAME_ACTIVE)
|
|
470
358
|
|
|
359
|
+
activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName)
|
|
360
|
+
|
|
471
361
|
this._isSliding = false
|
|
472
|
-
|
|
362
|
+
|
|
363
|
+
triggerEvent(EVENT_SLID)
|
|
473
364
|
}
|
|
474
365
|
|
|
366
|
+
this._queueCallback(completeCallBack, activeElement, this._isAnimated())
|
|
367
|
+
|
|
475
368
|
if (isCycling) {
|
|
476
369
|
this.cycle()
|
|
477
370
|
}
|
|
478
371
|
}
|
|
479
372
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
373
|
+
_isAnimated() {
|
|
374
|
+
return this._element.classList.contains(CLASS_NAME_SLIDE)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
_getActive() {
|
|
378
|
+
return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
_getItems() {
|
|
382
|
+
return SelectorEngine.find(SELECTOR_ITEM, this._element)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
_clearInterval() {
|
|
386
|
+
if (this._interval) {
|
|
387
|
+
clearInterval(this._interval)
|
|
388
|
+
this._interval = null
|
|
483
389
|
}
|
|
390
|
+
}
|
|
484
391
|
|
|
392
|
+
_directionToOrder(direction) {
|
|
485
393
|
if (isRTL()) {
|
|
486
394
|
return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT
|
|
487
395
|
}
|
|
@@ -490,10 +398,6 @@ class Carousel extends BaseComponent {
|
|
|
490
398
|
}
|
|
491
399
|
|
|
492
400
|
_orderToDirection(order) {
|
|
493
|
-
if (![ORDER_NEXT, ORDER_PREV].includes(order)) {
|
|
494
|
-
return order
|
|
495
|
-
}
|
|
496
|
-
|
|
497
401
|
if (isRTL()) {
|
|
498
402
|
return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT
|
|
499
403
|
}
|
|
@@ -502,88 +406,68 @@ class Carousel extends BaseComponent {
|
|
|
502
406
|
}
|
|
503
407
|
|
|
504
408
|
// Static
|
|
409
|
+
static jQueryInterface(config) {
|
|
410
|
+
return this.each(function () {
|
|
411
|
+
const data = Carousel.getOrCreateInstance(this, config)
|
|
505
412
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
let { _config } = data
|
|
510
|
-
if (typeof config === 'object') {
|
|
511
|
-
_config = {
|
|
512
|
-
..._config,
|
|
513
|
-
...config
|
|
413
|
+
if (typeof config === 'number') {
|
|
414
|
+
data.to(config)
|
|
415
|
+
return
|
|
514
416
|
}
|
|
515
|
-
}
|
|
516
417
|
|
|
517
|
-
|
|
418
|
+
if (typeof config === 'string') {
|
|
419
|
+
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
|
|
420
|
+
throw new TypeError(`No method named "${config}"`)
|
|
421
|
+
}
|
|
518
422
|
|
|
519
|
-
|
|
520
|
-
data.to(config)
|
|
521
|
-
} else if (typeof action === 'string') {
|
|
522
|
-
if (typeof data[action] === 'undefined') {
|
|
523
|
-
throw new TypeError(`No method named "${action}"`)
|
|
423
|
+
data[config]()
|
|
524
424
|
}
|
|
525
|
-
|
|
526
|
-
data[action]()
|
|
527
|
-
} else if (_config.interval && _config.ride) {
|
|
528
|
-
data.pause()
|
|
529
|
-
data.cycle()
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
static jQueryInterface(config) {
|
|
534
|
-
return this.each(function () {
|
|
535
|
-
Carousel.carouselInterface(this, config)
|
|
536
425
|
})
|
|
537
426
|
}
|
|
427
|
+
}
|
|
538
428
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
|
|
543
|
-
return
|
|
544
|
-
}
|
|
429
|
+
/**
|
|
430
|
+
* Data API implementation
|
|
431
|
+
*/
|
|
545
432
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
...Manipulator.getDataAttributes(this)
|
|
549
|
-
}
|
|
550
|
-
const slideIndex = this.getAttribute('data-bs-slide-to')
|
|
433
|
+
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, function (event) {
|
|
434
|
+
const target = getElementFromSelector(this)
|
|
551
435
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
436
|
+
if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
|
|
437
|
+
return
|
|
438
|
+
}
|
|
555
439
|
|
|
556
|
-
|
|
440
|
+
event.preventDefault()
|
|
557
441
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
}
|
|
442
|
+
const carousel = Carousel.getOrCreateInstance(target)
|
|
443
|
+
const slideIndex = this.getAttribute('data-bs-slide-to')
|
|
561
444
|
|
|
562
|
-
|
|
445
|
+
if (slideIndex) {
|
|
446
|
+
carousel.to(slideIndex)
|
|
447
|
+
carousel._maybeEnableCycle()
|
|
448
|
+
return
|
|
563
449
|
}
|
|
564
|
-
}
|
|
565
450
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
451
|
+
if (Manipulator.getDataAttribute(this, 'slide') === 'next') {
|
|
452
|
+
carousel.next()
|
|
453
|
+
carousel._maybeEnableCycle()
|
|
454
|
+
return
|
|
455
|
+
}
|
|
571
456
|
|
|
572
|
-
|
|
457
|
+
carousel.prev()
|
|
458
|
+
carousel._maybeEnableCycle()
|
|
459
|
+
})
|
|
573
460
|
|
|
574
461
|
EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
|
|
575
462
|
const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)
|
|
576
463
|
|
|
577
|
-
for (
|
|
578
|
-
Carousel.
|
|
464
|
+
for (const carousel of carousels) {
|
|
465
|
+
Carousel.getOrCreateInstance(carousel)
|
|
579
466
|
}
|
|
580
467
|
})
|
|
581
468
|
|
|
582
469
|
/**
|
|
583
|
-
* ------------------------------------------------------------------------
|
|
584
470
|
* jQuery
|
|
585
|
-
* ------------------------------------------------------------------------
|
|
586
|
-
* add .Carousel to jQuery only if jQuery is present
|
|
587
471
|
*/
|
|
588
472
|
|
|
589
473
|
defineJQueryPlugin(Carousel)
|