Skip to content

Commit ea4f409

Browse files
Fix bug with clicking slide to navigate in infinite mode
1 parent d66d43b commit ea4f409

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

.eslintrc

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"template-curly-spacing": "off",
66
"indent": "off",
77
"accessor-pairs": "off",
8-
"react/jsx-pascal-case": "off"
8+
"react/jsx-pascal-case": "off",
9+
"no-nested-ternary": "off"
910
}
1011
}

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 2.0.2 - May 2021
2+
3+
***(Bug Fix)*** Fixes a bug when clicking to navigate to a particular slide and crossing the end or beginning of the list
4+
15
# 2.0.1 - May 2021
26

37
***(Bug Fix)*** Fixes a bug in Safari 14.1 and Mobile Safari where carousel content is not visible in some scenarios

src/index.js

+14-11
Original file line numberDiff line numberDiff line change
@@ -300,18 +300,24 @@ export default class Carousel extends Component {
300300
* @param {Boolean} autoSlide - The source of slide transition, should be true for autoPlay and false for user click.
301301
*/
302302
goToSlide = (index, direction, autoSlide = false) => {
303-
const { beforeChange, transitionDuration, transition, onSlideTransitioned } = this.props;
303+
const { beforeChange, transitionDuration, transition, onSlideTransitioned, children } = this.props;
304+
const { currentSlide } = this.state;
305+
const lastIndex = Children.count(children) - 1;
306+
307+
const newIndex = index < 0 ? lastIndex + index + 1 :
308+
index <= lastIndex ? index : index - lastIndex - 1;
309+
310+
direction = direction || (index > currentSlide ? 'right' : 'left');
304311

305312
if (onSlideTransitioned) {
306313
onSlideTransitioned({
307314
autoPlay: autoSlide,
308-
index,
315+
index: newIndex,
309316
direction
310317
});
311318
}
312319

313-
const { currentSlide } = this.state;
314-
if (currentSlide === index) {
320+
if (currentSlide === newIndex) {
315321
return;
316322
}
317323

@@ -326,7 +332,7 @@ export default class Carousel extends Component {
326332
transitionDuration
327333
}, () => {
328334
this.setState({
329-
currentSlide: index,
335+
currentSlide: newIndex,
330336
direction,
331337
transitioningFrom: currentSlide
332338
}, () => {
@@ -343,20 +349,16 @@ export default class Carousel extends Component {
343349
* @param {Object} e - The event that calls nextSlide, will be undefined for autoPlay.
344350
*/
345351
nextSlide = (e) => {
346-
const { children } = this.props;
347352
const { currentSlide } = this.state;
348-
const newIndex = currentSlide < Children.count(children) - 1 ? currentSlide + 1 : 0;
349-
this.goToSlide(newIndex, 'right', typeof e !== 'object');
353+
this.goToSlide(currentSlide + 1, 'right', typeof e !== 'object');
350354
}
351355

352356
/**
353357
* Transitions to the previous slide moving from right to left.
354358
*/
355359
prevSlide = () => {
356-
const { children } = this.props;
357360
const { currentSlide } = this.state;
358-
const newIndex = currentSlide > 0 ? currentSlide - 1 : Children.count(children) - 1;
359-
this.goToSlide(newIndex, 'left');
361+
this.goToSlide(currentSlide - 1, 'left');
360362
}
361363

362364
/**
@@ -585,6 +587,7 @@ export default class Carousel extends Component {
585587
style={ loadingSlideStyle }
586588
data-index={ index }
587589
className={ classnames(slideClasses, LOADING_CLASS) }
590+
onClick={ this.handleSlideClick }
588591
></li>
589592
);
590593
});

test/unit/carousel.tests.js

+38
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,44 @@ describe('Carousel', () => {
189189
});
190190
});
191191

192+
it('should jump directly to a slide when the slide is clicked', done => {
193+
const onSlideTransitionedStub = sinon.stub();
194+
195+
renderToJsdom(
196+
<Carousel slideWidth='300px'
197+
viewportWidth='300px'
198+
infinite={ true }
199+
onSlideTransitioned={ onSlideTransitionedStub }>
200+
<div id='slide1'/>
201+
<div id='slide2'/>
202+
<div id='slide3'/>
203+
<div id='slide4'/>
204+
<div id='slide5'/>
205+
<div id='slide6'/>
206+
</Carousel>
207+
);
208+
209+
setImmediate(() => {
210+
let slides = tree.find('.carousel-slide');
211+
const track = tree.find('.carousel-track');
212+
expect(slides.length).to.equal(10);
213+
expect(slides.at(2).prop('className')).to.contain('carousel-slide-selected');
214+
expect(slides.at(2).prop('data-index')).to.eql(0);
215+
slides.at(0).simulate('mousedown', { clientX: 0, clientY: 0 });
216+
slides.at(0).simulate('click', { clientX: 0, clientY: 0 });
217+
slides = tree.find('.carousel-slide');
218+
expect(slides.at(6).prop('className')).to.contain('carousel-slide-selected');
219+
expect(slides.at(6).prop('data-index')).to.eql(4);
220+
track.simulate('transitionend', { propertyName: 'transform' });
221+
slides.at(9).simulate('mousedown', { clientX: 0, clientY: 0 });
222+
slides.at(9).simulate('click', { clientX: 0, clientY: 0 });
223+
slides = tree.find('.carousel-slide');
224+
expect(slides.at(3).prop('className')).to.contain('carousel-slide-selected');
225+
expect(slides.at(3).prop('data-index')).to.eql(1);
226+
done();
227+
});
228+
});
229+
192230
it('should not freeze when a selected dot is clicked', done => {
193231
renderToJsdom(
194232
<Carousel slideWidth='300px' viewportWidth='300px' infinite={ false }>

0 commit comments

Comments
 (0)