Proyectos de Subversion Moodle

Rev

Rev 1 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 1 Rev 1441
Línea 1... Línea 1...
1
/**
1
/**
2
 * --------------------------------------------------------------------------
2
 * --------------------------------------------------------------------------
3
 * Bootstrap (v4.6.2): carousel.js
3
 * Bootstrap carousel.js
4
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
4
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
 * --------------------------------------------------------------------------
5
 * --------------------------------------------------------------------------
6
 */
6
 */
Línea -... Línea 7...
-
 
7
 
-
 
8
import BaseComponent from './base-component'
7
 
9
import EventHandler from './dom/event-handler'
-
 
10
import Manipulator from './dom/manipulator'
-
 
11
import SelectorEngine from './dom/selector-engine'
-
 
12
import {
-
 
13
  defineJQueryPlugin,
-
 
14
  getNextActiveElement,
-
 
15
  isRTL,
-
 
16
  isVisible,
-
 
17
  reflow,
-
 
18
  triggerTransitionEnd
8
import $ from 'jquery'
19
} from './util/index'
Línea 9... Línea 20...
9
import Util from './util'
20
import Swipe from './util/swipe'
10
 
21
 
11
/**
22
/**
Línea 12... Línea 23...
12
 * Constants
23
 * Constants
13
 */
-
 
14
 
24
 */
15
const NAME = 'carousel'
25
 
16
const VERSION = '4.6.2'
26
const NAME = 'carousel'
17
const DATA_KEY = 'bs.carousel'
-
 
18
const EVENT_KEY = `.${DATA_KEY}`
-
 
19
const DATA_API_KEY = '.data-api'
-
 
20
const JQUERY_NO_CONFLICT = $.fn[NAME]
-
 
21
const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key
-
 
Línea 22... Línea 27...
22
const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key
27
const DATA_KEY = 'bs.carousel'
23
const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
-
 
24
const SWIPE_THRESHOLD = 40
-
 
25
 
28
const EVENT_KEY = `.${DATA_KEY}`
26
const CLASS_NAME_CAROUSEL = 'carousel'
29
const DATA_API_KEY = '.data-api'
27
const CLASS_NAME_ACTIVE = 'active'
-
 
28
const CLASS_NAME_SLIDE = 'slide'
-
 
29
const CLASS_NAME_RIGHT = 'carousel-item-right'
-
 
Línea 30... Línea 30...
30
const CLASS_NAME_LEFT = 'carousel-item-left'
30
 
31
const CLASS_NAME_NEXT = 'carousel-item-next'
31
const ARROW_LEFT_KEY = 'ArrowLeft'
32
const CLASS_NAME_PREV = 'carousel-item-prev'
32
const ARROW_RIGHT_KEY = 'ArrowRight'
33
const CLASS_NAME_POINTER_EVENT = 'pointer-event'
33
const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch
Línea 34... Línea 34...
34
 
34
 
35
const DIRECTION_NEXT = 'next'
35
const ORDER_NEXT = 'next'
36
const DIRECTION_PREV = 'prev'
36
const ORDER_PREV = 'prev'
37
const DIRECTION_LEFT = 'left'
37
const DIRECTION_LEFT = 'left'
38
const DIRECTION_RIGHT = 'right'
38
const DIRECTION_RIGHT = 'right'
39
 
-
 
40
const EVENT_SLIDE = `slide${EVENT_KEY}`
-
 
41
const EVENT_SLID = `slid${EVENT_KEY}`
-
 
42
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
-
 
43
const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`
-
 
44
const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`
39
 
45
const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`
40
const EVENT_SLIDE = `slide${EVENT_KEY}`
46
const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`
41
const EVENT_SLID = `slid${EVENT_KEY}`
Línea -... Línea 42...
-
 
42
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
-
 
43
const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`
-
 
44
const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`
-
 
45
const EVENT_DRAG_START = `dragstart${EVENT_KEY}`
-
 
46
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
-
 
47
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
-
 
48
 
-
 
49
const CLASS_NAME_CAROUSEL = 'carousel'
47
const EVENT_TOUCHEND = `touchend${EVENT_KEY}`
50
const CLASS_NAME_ACTIVE = 'active'
48
const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`
-
 
49
const EVENT_POINTERUP = `pointerup${EVENT_KEY}`
51
const CLASS_NAME_SLIDE = 'slide'
-
 
52
const CLASS_NAME_END = 'carousel-item-end'
50
const EVENT_DRAG_START = `dragstart${EVENT_KEY}`
53
const CLASS_NAME_START = 'carousel-item-start'
51
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
-
 
52
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
54
const CLASS_NAME_NEXT = 'carousel-item-next'
53
 
55
const CLASS_NAME_PREV = 'carousel-item-prev'
54
const SELECTOR_ACTIVE = '.active'
56
 
-
 
57
const SELECTOR_ACTIVE = '.active'
-
 
58
const SELECTOR_ITEM = '.carousel-item'
-
 
59
const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM
-
 
60
const SELECTOR_ITEM_IMG = '.carousel-item img'
-
 
61
const SELECTOR_INDICATORS = '.carousel-indicators'
Línea 55... Línea 62...
55
const SELECTOR_ACTIVE_ITEM = '.active.carousel-item'
62
const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'
56
const SELECTOR_ITEM = '.carousel-item'
63
const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'
57
const SELECTOR_ITEM_IMG = '.carousel-item img'
64
 
58
const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev'
-
 
59
const SELECTOR_INDICATORS = '.carousel-indicators'
65
const KEY_TO_DIRECTION = {
60
const SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]'
66
  [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
61
const SELECTOR_DATA_RIDE = '[data-ride="carousel"]'
67
  [ARROW_RIGHT_KEY]: DIRECTION_LEFT
-
 
68
}
62
 
69
 
Línea 63... Línea 70...
63
const Default = {
70
const Default = {
64
  interval: 5000,
71
  interval: 5000,
65
  keyboard: true,
72
  keyboard: true,
66
  slide: false,
-
 
67
  pause: 'hover',
73
  pause: 'hover',
68
  wrap: true,
74
  ride: false,
69
  touch: true
75
  touch: true,
70
}
-
 
71
 
-
 
72
const DefaultType = {
-
 
73
  interval: '(number|boolean)',
-
 
74
  keyboard: 'boolean',
76
  wrap: true
75
  slide: '(boolean|string)',
77
}
Línea 76... Línea 78...
76
  pause: '(string|boolean)',
78
 
77
  wrap: 'boolean',
79
const DefaultType = {
78
  touch: 'boolean'
80
  interval: '(number|boolean)', // TODO:v6 remove boolean support
Línea 79... Línea 81...
79
}
81
  keyboard: 'boolean',
80
 
82
  pause: '(string|boolean)',
81
const PointerType = {
83
  ride: '(boolean|string)',
-
 
84
  touch: 'boolean',
82
  TOUCH: 'touch',
85
  wrap: 'boolean'
83
  PEN: 'pen'
86
}
84
}
-
 
85
 
87
 
86
/**
88
/**
87
 * Class definition
-
 
88
 */
89
 * Class definition
89
 
-
 
90
class Carousel {
-
 
91
  constructor(element, config) {
-
 
92
    this._items = null
-
 
93
    this._interval = null
-
 
94
    this._activeElement = null
-
 
Línea -... Línea 90...
-
 
90
 */
95
    this._isPaused = false
91
 
96
    this._isSliding = false
-
 
Línea 97... Línea -...
97
    this.touchTimeout = null
-
 
98
    this.touchStartX = 0
92
class Carousel extends BaseComponent {
99
    this.touchDeltaX = 0
93
  constructor(element, config) {
-
 
94
    super(element, config)
100
 
95
 
Línea -... Línea 96...
-
 
96
    this._interval = null
101
    this._config = this._getConfig(config)
97
    this._activeElement = null
102
    this._element = element
98
    this._isSliding = false
103
    this._indicatorsElement = this._element.querySelector(SELECTOR_INDICATORS)
99
    this.touchTimeout = null
Línea -... Línea 100...
-
 
100
    this._swipeHelper = null
-
 
101
 
-
 
102
    this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element)
-
 
103
    this._addEventListeners()
-
 
104
 
-
 
105
    if (this._config.ride === CLASS_NAME_CAROUSEL) {
-
 
106
      this.cycle()
-
 
107
    }
104
    this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
108
  }
105
    this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent)
109
 
106
 
-
 
107
    this._addEventListeners()
110
  // Getters
108
  }
-
 
109
 
111
  static get Default() {
Línea 110... Línea 112...
110
  // Getters
112
    return Default
111
  static get VERSION() {
113
  }
112
    return VERSION
114
 
113
  }
115
  static get DefaultType() {
114
 
116
    return DefaultType
115
  static get Default() {
-
 
116
    return Default
117
  }
117
  }
118
 
118
 
119
  static get NAME() {
Línea 119... Línea 120...
119
  // Public
120
    return NAME
120
  next() {
-
 
121
    if (!this._isSliding) {
121
  }
122
      this._slide(DIRECTION_NEXT)
-
 
123
    }
122
 
Línea 124... Línea 123...
124
  }
123
  // Public
125
 
124
  next() {
126
  nextWhenVisible() {
125
    this._slide(ORDER_NEXT)
127
    const $element = $(this._element)
126
  }
Línea 128... Línea -...
128
    // Don't call next when the page isn't visible
-
 
129
    // or the carousel or its parent isn't visible
-
 
130
    if (!document.hidden &&
127
 
131
      ($element.is(':visible') && $element.css('visibility') !== 'hidden')) {
128
  nextWhenVisible() {
Línea -... Línea 129...
-
 
129
    // FIXME TODO use `document.visibilityState`
132
      this.next()
130
    // Don't call next when the page isn't visible
133
    }
131
    // or the carousel or its parent isn't visible
-
 
132
    if (!document.hidden && isVisible(this._element)) {
-
 
133
      this.next()
134
  }
134
    }
Línea 135... Línea 135...
135
 
135
  }
136
  prev() {
136
 
137
    if (!this._isSliding) {
137
  prev() {
138
      this._slide(DIRECTION_PREV)
138
    this._slide(ORDER_PREV)
Línea 139... Línea 139...
139
    }
139
  }
140
  }
140
 
141
 
141
  pause() {
142
  pause(event) {
142
    if (this._isSliding) {
Línea 143... Línea -...
143
    if (!event) {
-
 
144
      this._isPaused = true
143
      triggerTransitionEnd(this._element)
145
    }
-
 
146
 
-
 
147
    if (this._element.querySelector(SELECTOR_NEXT_PREV)) {
-
 
148
      Util.triggerTransitionEnd(this._element)
-
 
149
      this.cycle(true)
-
 
150
    }
-
 
151
 
144
    }
Línea 152... Línea 145...
152
    clearInterval(this._interval)
145
 
153
    this._interval = null
-
 
154
  }
-
 
155
 
146
    this._clearInterval()
156
  cycle(event) {
-
 
157
    if (!event) {
147
  }
158
      this._isPaused = false
148
 
159
    }
149
  cycle() {
Línea 160... Línea 150...
160
 
150
    this._clearInterval()
161
    if (this._interval) {
151
    this._updateInterval()
162
      clearInterval(this._interval)
152
 
163
      this._interval = null
153
    this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval)
Línea -... Línea 154...
-
 
154
  }
164
    }
155
 
165
 
-
 
166
    if (this._config.interval && !this._isPaused) {
-
 
167
      this._updateInterval()
156
  _maybeEnableCycle() {
168
 
157
    if (!this._config.ride) {
Línea 169... Línea 158...
169
      this._interval = setInterval(
158
      return
170
        (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),
-
 
171
        this._config.interval
-
 
Línea 172... Línea 159...
172
      )
159
    }
173
    }
160
 
Línea 174... Línea 161...
174
  }
161
    if (this._isSliding) {
175
 
162
      EventHandler.one(this._element, EVENT_SLID, () => this.cycle())
176
  to(index) {
163
      return
-
 
164
    }
Línea 177... Línea -...
177
    this._activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM)
-
 
178
 
-
 
179
    const activeIndex = this._getItemIndex(this._activeElement)
-
 
180
 
-
 
181
    if (index > this._items.length - 1 || index < 0) {
165
 
182
      return
-
 
183
    }
-
 
184
 
-
 
185
    if (this._isSliding) {
166
    this.cycle()
Línea 186... Línea 167...
186
      $(this._element).one(EVENT_SLID, () => this.to(index))
167
  }
187
      return
168
 
188
    }
-
 
189
 
-
 
190
    if (activeIndex === index) {
-
 
191
      this.pause()
-
 
192
      this.cycle()
169
  to(index) {
193
      return
170
    const items = this._getItems()
194
    }
171
    if (index > items.length - 1 || index < 0) {
Línea 195... Línea -...
195
 
-
 
196
    const direction = index > activeIndex ?
-
 
197
      DIRECTION_NEXT :
-
 
198
      DIRECTION_PREV
-
 
199
 
-
 
200
    this._slide(direction, this._items[index])
-
 
201
  }
-
 
202
 
-
 
203
  dispose() {
-
 
204
    $(this._element).off(EVENT_KEY)
-
 
205
    $.removeData(this._element, DATA_KEY)
-
 
206
 
-
 
207
    this._items = null
-
 
208
    this._config = null
-
 
209
    this._element = null
-
 
210
    this._interval = null
-
 
211
    this._isPaused = null
-
 
212
    this._isSliding = null
-
 
213
    this._activeElement = null
-
 
214
    this._indicatorsElement = null
-
 
215
  }
-
 
216
 
-
 
217
  // Private
172
      return
218
  _getConfig(config) {
173
    }
219
    config = {
174
 
220
      ...Default,
175
    if (this._isSliding) {
Línea 221... Línea 176...
221
      ...config
176
      EventHandler.one(this._element, EVENT_SLID, () => this.to(index))
222
    }
-
 
223
    Util.typeCheckConfig(NAME, config, DefaultType)
177
      return
224
    return config
178
    }
225
  }
179
 
Línea 226... Línea 180...
226
 
180
    const activeIndex = this._getItemIndex(this._getActive())
227
  _handleSwipe() {
181
    if (activeIndex === index) {
228
    const absDeltax = Math.abs(this.touchDeltaX)
182
      return
229
 
183
    }
Línea 230... Línea 184...
230
    if (absDeltax <= SWIPE_THRESHOLD) {
184
 
231
      return
185
    const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV
232
    }
186
 
233
 
187
    this._slide(order, items[index])
Línea 234... Línea 188...
234
    const direction = absDeltax / this.touchDeltaX
188
  }
235
 
-
 
236
    this.touchDeltaX = 0
189
 
237
 
190
  dispose() {
238
    // swipe left
-
 
239
    if (direction > 0) {
191
    if (this._swipeHelper) {
240
      this.prev()
-
 
Línea -... Línea 192...
-
 
192
      this._swipeHelper.dispose()
241
    }
193
    }
242
 
194
 
243
    // swipe right
195
    super.dispose()
244
    if (direction < 0) {
196
  }
-
 
197
 
245
      this.next()
198
  // Private
246
    }
-
 
Línea 247... Línea 199...
247
  }
199
  _configAfterMerge(config) {
248
 
200
    config.defaultInterval = config.interval
249
  _addEventListeners() {
201
    return config
250
    if (this._config.keyboard) {
202
  }
Línea 251... Línea -...
251
      $(this._element).on(EVENT_KEYDOWN, event => this._keydown(event))
-
 
252
    }
-
 
253
 
-
 
254
    if (this._config.pause === 'hover') {
-
 
255
      $(this._element)
-
 
256
        .on(EVENT_MOUSEENTER, event => this.pause(event))
-
 
257
        .on(EVENT_MOUSELEAVE, event => this.cycle(event))
-
 
258
    }
-
 
259
 
-
 
260
    if (this._config.touch) {
-
 
261
      this._addTouchEventListeners()
-
 
262
    }
-
 
263
  }
-
 
264
 
-
 
265
  _addTouchEventListeners() {
-
 
266
    if (!this._touchSupported) {
203
 
267
      return
-
 
268
    }
204
  _addEventListeners() {
Línea 269... Línea -...
269
 
-
 
270
    const start = event => {
-
 
271
      if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {
-
 
272
        this.touchStartX = event.originalEvent.clientX
205
    if (this._config.keyboard) {
273
      } else if (!this._pointerEvent) {
-
 
274
        this.touchStartX = event.originalEvent.touches[0].clientX
206
      EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event))
275
      }
-
 
276
    }
207
    }
277
 
208
 
278
    const move = event => {
-
 
279
      // ensure swiping with one touch and not pinching
-
 
280
      this.touchDeltaX = event.originalEvent.touches && event.originalEvent.touches.length > 1 ?
-
 
281
        0 :
209
    if (this._config.pause === 'hover') {
-
 
210
      EventHandler.on(this._element, EVENT_MOUSEENTER, () => this.pause())
-
 
211
      EventHandler.on(this._element, EVENT_MOUSELEAVE, () => this._maybeEnableCycle())
282
        event.originalEvent.touches[0].clientX - this.touchStartX
212
    }
Línea 283... Línea 213...
283
    }
213
 
284
 
214
    if (this._config.touch && Swipe.isSupported()) {
285
    const end = event => {
215
      this._addTouchEventListeners()
286
      if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {
216
    }
Línea 287... Línea -...
287
        this.touchDeltaX = event.originalEvent.clientX - this.touchStartX
-
 
288
      }
217
  }
289
 
-
 
290
      this._handleSwipe()
218
 
291
      if (this._config.pause === 'hover') {
-
 
292
        // If it's a touch-enabled device, mouseenter/leave are fired as
-
 
293
        // part of the mouse compatibility events on first tap - the carousel
219
  _addTouchEventListeners() {
294
        // would stop cycling until user tapped out of it;
220
    for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {
295
        // here, we listen for touchend, explicitly pause the carousel
-
 
296
        // (as if it's the second time we tap on it, mouseenter compat event
-
 
297
        // is NOT fired) and after a timeout (to allow for mouse compatibility
221
      EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault())
298
        // events to fire) we explicitly restart cycling
222
    }
Línea 299... Línea 223...
299
 
223
 
300
        this.pause()
-
 
301
        if (this.touchTimeout) {
-
 
302
          clearTimeout(this.touchTimeout)
-
 
303
        }
224
    const endCallBack = () => {
304
 
-
 
305
        this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
-
 
306
      }
-
 
307
    }
-
 
308
 
-
 
309
    $(this._element.querySelectorAll(SELECTOR_ITEM_IMG))
-
 
310
      .on(EVENT_DRAG_START, e => e.preventDefault())
-
 
311
 
-
 
312
    if (this._pointerEvent) {
-
 
313
      $(this._element).on(EVENT_POINTERDOWN, event => start(event))
-
 
314
      $(this._element).on(EVENT_POINTERUP, event => end(event))
-
 
315
 
-
 
316
      this._element.classList.add(CLASS_NAME_POINTER_EVENT)
-
 
317
    } else {
-
 
318
      $(this._element).on(EVENT_TOUCHSTART, event => start(event))
-
 
319
      $(this._element).on(EVENT_TOUCHMOVE, event => move(event))
-
 
320
      $(this._element).on(EVENT_TOUCHEND, event => end(event))
-
 
321
    }
-
 
322
  }
-
 
323
 
225
      if (this._config.pause !== 'hover') {
324
  _keydown(event) {
-
 
325
    if (/input|textarea/i.test(event.target.tagName)) {
-
 
326
      return
-
 
327
    }
-
 
328
 
-
 
329
    switch (event.which) {
-
 
330
      case ARROW_LEFT_KEYCODE:
-
 
331
        event.preventDefault()
-
 
332
        this.prev()
-
 
333
        break
-
 
Línea -... Línea 226...
-
 
226
        return
334
      case ARROW_RIGHT_KEYCODE:
227
      }
-
 
228
 
-
 
229
      // If it's a touch-enabled device, mouseenter/leave are fired as
Línea 335... Línea 230...
335
        event.preventDefault()
230
      // part of the mouse compatibility events on first tap - the carousel
336
        this.next()
-
 
Línea 337... Línea 231...
337
        break
231
      // would stop cycling until user tapped out of it;
338
      default:
-
 
339
    }
-
 
340
  }
232
      // here, we listen for touchend, explicitly pause the carousel
Línea 341... Línea 233...
341
 
233
      // (as if it's the second time we tap on it, mouseenter compat event
342
  _getItemIndex(element) {
-
 
343
    this._items = element && element.parentNode ?
-
 
Línea 344... Línea 234...
344
      [].slice.call(element.parentNode.querySelectorAll(SELECTOR_ITEM)) :
234
      // is NOT fired) and after a timeout (to allow for mouse compatibility
345
      []
235
      // events to fire) we explicitly restart cycling
346
    return this._items.indexOf(element)
236
 
347
  }
237
      this.pause()
348
 
238
      if (this.touchTimeout) {
Línea 349... Línea 239...
349
  _getItemByDirection(direction, activeElement) {
239
        clearTimeout(this.touchTimeout)
350
    const isNextDirection = direction === DIRECTION_NEXT
240
      }
Línea 351... Línea 241...
351
    const isPrevDirection = direction === DIRECTION_PREV
241
 
352
    const activeIndex = this._getItemIndex(activeElement)
242
      this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval)
353
    const lastItemIndex = this._items.length - 1
243
    }
Línea 354... Línea 244...
354
    const isGoingToWrap = isPrevDirection && activeIndex === 0 ||
244
 
Línea 355... Línea -...
355
                            isNextDirection && activeIndex === lastItemIndex
-
 
356
 
-
 
357
    if (isGoingToWrap && !this._config.wrap) {
-
 
358
      return activeElement
-
 
359
    }
245
    const swipeConfig = {
360
 
-
 
361
    const delta = direction === DIRECTION_PREV ? -1 : 1
246
      leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),
Línea 362... Línea 247...
362
    const itemIndex = (activeIndex + delta) % this._items.length
247
      rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),
363
 
-
 
364
    return itemIndex === -1 ?
-
 
365
      this._items[this._items.length - 1] : this._items[itemIndex]
-
 
366
  }
-
 
367
 
-
 
368
  _triggerSlideEvent(relatedTarget, eventDirectionName) {
-
 
369
    const targetIndex = this._getItemIndex(relatedTarget)
-
 
370
    const fromIndex = this._getItemIndex(this._element.querySelector(SELECTOR_ACTIVE_ITEM))
-
 
371
    const slideEvent = $.Event(EVENT_SLIDE, {
-
 
372
      relatedTarget,
248
      endCallback: endCallBack
373
      direction: eventDirectionName,
-
 
374
      from: fromIndex,
-
 
375
      to: targetIndex
-
 
376
    })
-
 
377
 
-
 
378
    $(this._element).trigger(slideEvent)
249
    }
379
 
-
 
380
    return slideEvent
-
 
381
  }
-
 
382
 
250
 
Línea 383... Línea 251...
383
  _setActiveIndicatorElement(element) {
251
    this._swipeHelper = new Swipe(this._element, swipeConfig)
384
    if (this._indicatorsElement) {
252
  }
-
 
253
 
-
 
254
  _keydown(event) {
-
 
255
    if (/input|textarea/i.test(event.target.tagName)) {
385
      const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE))
256
      return
386
      $(indicators).removeClass(CLASS_NAME_ACTIVE)
257
    }
Línea -... Línea 258...
-
 
258
 
-
 
259
    const direction = KEY_TO_DIRECTION[event.key]
-
 
260
    if (direction) {
-
 
261
      event.preventDefault()
-
 
262
      this._slide(this._directionToOrder(direction))
-
 
263
    }
-
 
264
  }
-
 
265
 
-
 
266
  _getItemIndex(element) {
-
 
267
    return this._getItems().indexOf(element)
-
 
268
  }
387
 
269
 
-
 
270
  _setActiveIndicatorElement(index) {
388
      const nextIndicator = this._indicatorsElement.children[
271
    if (!this._indicatorsElement) {
389
        this._getItemIndex(element)
272
      return
390
      ]
273
    }
Línea 391... Línea 274...
391
 
274
 
392
      if (nextIndicator) {
275
    const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement)
-
 
276
 
393
        $(nextIndicator).addClass(CLASS_NAME_ACTIVE)
277
    activeIndicator.classList.remove(CLASS_NAME_ACTIVE)
394
      }
278
    activeIndicator.removeAttribute('aria-current')
Línea -... Línea 279...
-
 
279
 
395
    }
280
    const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement)
Línea 396... Línea 281...
396
  }
281
 
397
 
-
 
398
  _updateInterval() {
-
 
Línea 399... Línea 282...
399
    const element = this._activeElement || this._element.querySelector(SELECTOR_ACTIVE_ITEM)
282
    if (newActiveIndicator) {
400
 
283
      newActiveIndicator.classList.add(CLASS_NAME_ACTIVE)
Línea 401... Línea 284...
401
    if (!element) {
284
      newActiveIndicator.setAttribute('aria-current', 'true')
402
      return
-
 
403
    }
-
 
404
 
-
 
405
    const elementInterval = parseInt(element.getAttribute('data-interval'), 10)
-
 
406
 
-
 
407
    if (elementInterval) {
-
 
408
      this._config.defaultInterval = this._config.defaultInterval || this._config.interval
285
    }
409
      this._config.interval = elementInterval
-
 
410
    } else {
-
 
411
      this._config.interval = this._config.defaultInterval || this._config.interval
-
 
Línea 412... Línea -...
412
    }
-
 
413
  }
286
  }
Línea 414... Línea 287...
414
 
287
 
Línea 415... Línea -...
415
  _slide(direction, element) {
-
 
416
    const activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM)
-
 
417
    const activeElementIndex = this._getItemIndex(activeElement)
-
 
418
    const nextElement = element || activeElement &&
288
  _updateInterval() {
419
      this._getItemByDirection(direction, activeElement)
289
    const element = this._activeElement || this._getActive()
Línea -... Línea 290...
-
 
290
 
420
    const nextElementIndex = this._getItemIndex(nextElement)
291
    if (!element) {
-
 
292
      return
Línea 421... Línea -...
421
    const isCycling = Boolean(this._interval)
-
 
422
 
-
 
423
    let directionalClassName
-
 
424
    let orderClassName
-
 
425
    let eventDirectionName
-
 
426
 
-
 
427
    if (direction === DIRECTION_NEXT) {
293
    }
428
      directionalClassName = CLASS_NAME_LEFT
-
 
Línea 429... Línea 294...
429
      orderClassName = CLASS_NAME_NEXT
294
 
-
 
295
    const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10)
430
      eventDirectionName = DIRECTION_LEFT
296
 
431
    } else {
297
    this._config.interval = elementInterval || this._config.defaultInterval
Línea -... Línea 298...
-
 
298
  }
-
 
299
 
432
      directionalClassName = CLASS_NAME_RIGHT
300
  _slide(order, element = null) {
433
      orderClassName = CLASS_NAME_PREV
301
    if (this._isSliding) {
434
      eventDirectionName = DIRECTION_RIGHT
302
      return
435
    }
303
    }
Línea 436... Línea -...
436
 
-
 
437
    if (nextElement && $(nextElement).hasClass(CLASS_NAME_ACTIVE)) {
-
 
438
      this._isSliding = false
-
 
439
      return
-
 
440
    }
-
 
441
 
-
 
442
    const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)
-
 
443
    if (slideEvent.isDefaultPrevented()) {
-
 
444
      return
-
 
445
    }
-
 
446
 
-
 
447
    if (!activeElement || !nextElement) {
-
 
448
      // Some weirdness is happening, so we bail
-
 
449
      return
-
 
450
    }
-
 
451
 
-
 
452
    this._isSliding = true
-
 
453
 
-
 
454
    if (isCycling) {
304
 
455
      this.pause()
-
 
456
    }
305
    const activeElement = this._getActive()
457
 
306
    const isNext = order === ORDER_NEXT
Línea 458... Línea -...
458
    this._setActiveIndicatorElement(nextElement)
-
 
459
    this._activeElement = nextElement
307
    const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap)
460
 
-
 
461
    const slidEvent = $.Event(EVENT_SLID, {
-
 
462
      relatedTarget: nextElement,
308
 
463
      direction: eventDirectionName,
309
    if (nextElement === activeElement) {
Línea 464... Línea 310...
464
      from: activeElementIndex,
310
      return
465
      to: nextElementIndex
311
    }
466
    })
-
 
467
 
-
 
468
    if ($(this._element).hasClass(CLASS_NAME_SLIDE)) {
-
 
469
      $(nextElement).addClass(orderClassName)
-
 
470
 
312
 
Línea -... Línea 313...
-
 
313
    const nextElementIndex = this._getItemIndex(nextElement)
471
      Util.reflow(nextElement)
314
 
472
 
315
    const triggerEvent = eventName => {
-
 
316
      return EventHandler.trigger(this._element, eventName, {
-
 
317
        relatedTarget: nextElement,
-
 
318
        direction: this._orderToDirection(order),
Línea 473... Línea 319...
473
      $(activeElement).addClass(directionalClassName)
319
        from: this._getItemIndex(activeElement),
474
      $(nextElement).addClass(directionalClassName)
320
        to: nextElementIndex
-
 
321
      })
475
 
322
    }
Línea 476... Línea 323...
476
      const transitionDuration = Util.getTransitionDurationFromElement(activeElement)
323
 
-
 
324
    const slideEvent = triggerEvent(EVENT_SLIDE)
Línea 477... Línea 325...
477
 
325
 
478
      $(activeElement)
326
    if (slideEvent.defaultPrevented) {
-
 
327
      return
479
        .one(Util.TRANSITION_END, () => {
328
    }
Línea 480... Línea -...
480
          $(nextElement)
-
 
481
            .removeClass(`${directionalClassName} ${orderClassName}`)
329
 
482
            .addClass(CLASS_NAME_ACTIVE)
-
 
483
 
330
    if (!activeElement || !nextElement) {
484
          $(activeElement).removeClass(`${CLASS_NAME_ACTIVE} ${orderClassName} ${directionalClassName}`)
-
 
Línea 485... Línea 331...
485
 
331
      // Some weirdness is happening, so we bail
486
          this._isSliding = false
332
      // TODO: change tests that use empty divs to avoid this check
487
 
333
      return
-
 
334
    }
Línea 488... Línea 335...
488
          setTimeout(() => $(this._element).trigger(slidEvent), 0)
335
 
-
 
336
    const isCycling = Boolean(this._interval)
-
 
337
    this.pause()
-
 
338
 
Línea 489... Línea 339...
489
        })
339
    this._isSliding = true
-
 
340
 
490
        .emulateTransitionEnd(transitionDuration)
341
    this._setActiveIndicatorElement(nextElementIndex)
491
    } else {
342
    this._activeElement = nextElement
Línea 492... Línea 343...
492
      $(activeElement).removeClass(CLASS_NAME_ACTIVE)
343
 
-
 
344
    const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END
-
 
345
    const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV
493
      $(nextElement).addClass(CLASS_NAME_ACTIVE)
346
 
494
 
347
    nextElement.classList.add(orderClassName)
Línea 495... Línea 348...
495
      this._isSliding = false
348
 
496
      $(this._element).trigger(slidEvent)
349
    reflow(nextElement)
497
    }
350
 
Línea 498... Línea 351...
498
 
351
    activeElement.classList.add(directionalClassName)
-
 
352
    nextElement.classList.add(directionalClassName)
-
 
353
 
-
 
354
    const completeCallBack = () => {
-
 
355
      nextElement.classList.remove(directionalClassName, orderClassName)
-
 
356
      nextElement.classList.add(CLASS_NAME_ACTIVE)
-
 
357
 
-
 
358
      activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName)
Línea -... Línea 359...
-
 
359
 
-
 
360
      this._isSliding = false
-
 
361
 
-
 
362
      triggerEvent(EVENT_SLID)
-
 
363
    }
-
 
364
 
-
 
365
    this._queueCallback(completeCallBack, activeElement, this._isAnimated())
-
 
366
 
-
 
367
    if (isCycling) {
-
 
368
      this.cycle()
-
 
369
    }
-
 
370
  }
-
 
371
 
-
 
372
  _isAnimated() {
-
 
373
    return this._element.classList.contains(CLASS_NAME_SLIDE)
-
 
374
  }
-
 
375
 
-
 
376
  _getActive() {
-
 
377
    return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element)
499
    if (isCycling) {
378
  }
500
      this.cycle()
379
 
501
    }
-
 
-
 
380
  _getItems() {
502
  }
381
    return SelectorEngine.find(SELECTOR_ITEM, this._element)
503
 
382
  }
504
  // Static
383
 
505
  static _jQueryInterface(config) {
384
  _clearInterval() {
Línea 506... Línea 385...
506
    return this.each(function () {
385
    if (this._interval) {
507
      let data = $(this).data(DATA_KEY)
386
      clearInterval(this._interval)
508
      let _config = {
387
      this._interval = null
Línea 509... Línea -...
509
        ...Default,
-
 
510
        ...$(this).data()
388
    }
511
      }
-
 
512
 
-
 
513
      if (typeof config === 'object') {
-
 
514
        _config = {
-
 
Línea 515... Línea 389...
515
          ..._config,
389
  }