0
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-02-19 16:54:24 +01:00

fix(carousel): arrow keys break animation if carousel sliding (#34307)

This commit is contained in:
alpadev 2021-06-22 12:11:03 +02:00 committed by GitHub
parent 8be957b32b
commit 290b9ee2cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 15 deletions

View File

@ -59,6 +59,11 @@ 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}`
@ -134,9 +139,7 @@ class Carousel extends BaseComponent {
// Public
next() {
if (!this._isSliding) {
this._slide(ORDER_NEXT)
}
this._slide(ORDER_NEXT)
}
nextWhenVisible() {
@ -148,9 +151,7 @@ class Carousel extends BaseComponent {
}
prev() {
if (!this._isSliding) {
this._slide(ORDER_PREV)
}
this._slide(ORDER_PREV)
}
pause(event) {
@ -319,12 +320,10 @@ class Carousel extends BaseComponent {
return
}
if (event.key === ARROW_LEFT_KEY) {
const direction = KEY_TO_DIRECTION[event.key]
if (direction) {
event.preventDefault()
this._slide(DIRECTION_RIGHT)
} else if (event.key === ARROW_RIGHT_KEY) {
event.preventDefault()
this._slide(DIRECTION_LEFT)
this._slide(direction)
}
}
@ -408,6 +407,10 @@ class Carousel extends BaseComponent {
return
}
if (this._isSliding) {
return
}
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)
if (slideEvent.defaultPrevented) {
return

View File

@ -203,6 +203,26 @@ describe('Carousel', () => {
expect(spySlide).not.toHaveBeenCalled()
})
it('should not slide if arrow key is pressed and carousel is sliding', () => {
fixtureEl.innerHTML = '<div></div>'
const carouselEl = fixtureEl.querySelector('div')
const carousel = new Carousel(carouselEl, {})
spyOn(carousel, '_triggerSlideEvent')
carousel._isSliding = true;
['ArrowLeft', 'ArrowRight'].forEach(key => {
const keydown = createEvent('keydown')
keydown.key = key
carouselEl.dispatchEvent(keydown)
})
expect(carousel._triggerSlideEvent).not.toHaveBeenCalled()
})
it('should wrap around from end to start when wrap option is true', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
@ -487,6 +507,49 @@ describe('Carousel', () => {
})
})
it('should not slide when swiping and carousel is sliding', done => {
Simulator.setType('touch')
clearPointerEvents()
document.documentElement.ontouchstart = () => {}
fixtureEl.innerHTML = [
'<div class="carousel" data-bs-interval="false">',
' <div class="carousel-inner">',
' <div id="item" class="carousel-item active">',
' <img alt="">',
' </div>',
' <div class="carousel-item">',
' <img alt="">',
' </div>',
' </div>',
'</div>'
].join('')
const carouselEl = fixtureEl.querySelector('.carousel')
const carousel = new Carousel(carouselEl)
carousel._isSliding = true
spyOn(carousel, '_triggerSlideEvent')
Simulator.gestures.swipe(carouselEl, {
deltaX: 300,
deltaY: 0
})
Simulator.gestures.swipe(carouselEl, {
pos: [300, 10],
deltaX: -300,
deltaY: 0
})
setTimeout(() => {
expect(carousel._triggerSlideEvent).not.toHaveBeenCalled()
delete document.documentElement.ontouchstart
restorePointerEvents()
done()
}, 300)
})
it('should not allow pinch with touch events', done => {
Simulator.setType('touch')
clearPointerEvents()
@ -552,12 +615,12 @@ describe('Carousel', () => {
const carouselEl = fixtureEl.querySelector('div')
const carousel = new Carousel(carouselEl, {})
spyOn(carousel, '_slide')
spyOn(carousel, '_triggerSlideEvent')
carousel._isSliding = true
carousel.next()
expect(carousel._slide).not.toHaveBeenCalled()
expect(carousel._triggerSlideEvent).not.toHaveBeenCalled()
})
it('should not fire slid when slide is prevented', done => {
@ -763,12 +826,12 @@ describe('Carousel', () => {
const carouselEl = fixtureEl.querySelector('div')
const carousel = new Carousel(carouselEl, {})
spyOn(carousel, '_slide')
spyOn(carousel, '_triggerSlideEvent')
carousel._isSliding = true
carousel.prev()
expect(carousel._slide).not.toHaveBeenCalled()
expect(carousel._triggerSlideEvent).not.toHaveBeenCalled()
})
})