mirror of
https://github.com/twbs/bootstrap.git
synced 2025-02-21 18:54:30 +01:00
fix(carousel): arrow keys break animation if carousel sliding (#34307)
This commit is contained in:
parent
8be957b32b
commit
290b9ee2cd
@ -59,6 +59,11 @@ const ORDER_PREV = 'prev'
|
|||||||
const DIRECTION_LEFT = 'left'
|
const DIRECTION_LEFT = 'left'
|
||||||
const DIRECTION_RIGHT = 'right'
|
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_SLIDE = `slide${EVENT_KEY}`
|
||||||
const EVENT_SLID = `slid${EVENT_KEY}`
|
const EVENT_SLID = `slid${EVENT_KEY}`
|
||||||
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
|
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
|
||||||
@ -134,9 +139,7 @@ class Carousel extends BaseComponent {
|
|||||||
// Public
|
// Public
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
if (!this._isSliding) {
|
this._slide(ORDER_NEXT)
|
||||||
this._slide(ORDER_NEXT)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nextWhenVisible() {
|
nextWhenVisible() {
|
||||||
@ -148,9 +151,7 @@ class Carousel extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prev() {
|
prev() {
|
||||||
if (!this._isSliding) {
|
this._slide(ORDER_PREV)
|
||||||
this._slide(ORDER_PREV)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pause(event) {
|
pause(event) {
|
||||||
@ -319,12 +320,10 @@ class Carousel extends BaseComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === ARROW_LEFT_KEY) {
|
const direction = KEY_TO_DIRECTION[event.key]
|
||||||
|
if (direction) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
this._slide(DIRECTION_RIGHT)
|
this._slide(direction)
|
||||||
} else if (event.key === ARROW_RIGHT_KEY) {
|
|
||||||
event.preventDefault()
|
|
||||||
this._slide(DIRECTION_LEFT)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,6 +407,10 @@ class Carousel extends BaseComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._isSliding) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)
|
const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)
|
||||||
if (slideEvent.defaultPrevented) {
|
if (slideEvent.defaultPrevented) {
|
||||||
return
|
return
|
||||||
|
@ -203,6 +203,26 @@ describe('Carousel', () => {
|
|||||||
expect(spySlide).not.toHaveBeenCalled()
|
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 => {
|
it('should wrap around from end to start when wrap option is true', done => {
|
||||||
fixtureEl.innerHTML = [
|
fixtureEl.innerHTML = [
|
||||||
'<div id="myCarousel" class="carousel slide">',
|
'<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 => {
|
it('should not allow pinch with touch events', done => {
|
||||||
Simulator.setType('touch')
|
Simulator.setType('touch')
|
||||||
clearPointerEvents()
|
clearPointerEvents()
|
||||||
@ -552,12 +615,12 @@ describe('Carousel', () => {
|
|||||||
const carouselEl = fixtureEl.querySelector('div')
|
const carouselEl = fixtureEl.querySelector('div')
|
||||||
const carousel = new Carousel(carouselEl, {})
|
const carousel = new Carousel(carouselEl, {})
|
||||||
|
|
||||||
spyOn(carousel, '_slide')
|
spyOn(carousel, '_triggerSlideEvent')
|
||||||
|
|
||||||
carousel._isSliding = true
|
carousel._isSliding = true
|
||||||
carousel.next()
|
carousel.next()
|
||||||
|
|
||||||
expect(carousel._slide).not.toHaveBeenCalled()
|
expect(carousel._triggerSlideEvent).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not fire slid when slide is prevented', done => {
|
it('should not fire slid when slide is prevented', done => {
|
||||||
@ -763,12 +826,12 @@ describe('Carousel', () => {
|
|||||||
const carouselEl = fixtureEl.querySelector('div')
|
const carouselEl = fixtureEl.querySelector('div')
|
||||||
const carousel = new Carousel(carouselEl, {})
|
const carousel = new Carousel(carouselEl, {})
|
||||||
|
|
||||||
spyOn(carousel, '_slide')
|
spyOn(carousel, '_triggerSlideEvent')
|
||||||
|
|
||||||
carousel._isSliding = true
|
carousel._isSliding = true
|
||||||
carousel.prev()
|
carousel.prev()
|
||||||
|
|
||||||
expect(carousel._slide).not.toHaveBeenCalled()
|
expect(carousel._triggerSlideEvent).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user