111 lines
3.4 KiB
JavaScript
111 lines
3.4 KiB
JavaScript
export default class Carousel {
|
|
constructor (element) {
|
|
this.element = element;
|
|
this.itemClassName = 'carousel__photo';
|
|
this.items = this.element.querySelectorAll(`.${this.itemClassName}`);
|
|
this.totalItems = this.items.length;
|
|
this.slide = 0;
|
|
this.moving = true;
|
|
|
|
this.start();
|
|
}
|
|
|
|
setInitialClasses () {
|
|
this.items[0].classList.add('active');
|
|
this.items[1].classList.add('next');
|
|
}
|
|
|
|
attachEventListeners () {
|
|
const next = this.element.querySelector('.carousel__button--next');
|
|
const prev = this.element.querySelector('.carousel__button--prev');
|
|
|
|
next.addEventListener('click', this.moveNext.bind(this));
|
|
prev.addEventListener('click', this.movePrev.bind(this));
|
|
}
|
|
|
|
moveCarouselTo (slide) {
|
|
// Check if carousel is moving, if not, allow interaction
|
|
if (!this.moving) {
|
|
// temporarily disable interactivity
|
|
this.disableInteraction();
|
|
// Update the 'old' adjacent slides with 'new' ones
|
|
let newPrevious = slide - 1,
|
|
newNext = slide + 1,
|
|
oldPrevious = slide - 2,
|
|
oldNext = slide + 2;
|
|
// Test if carousel has more than three items
|
|
if ((this.totalItems - 1) > 2) {
|
|
// Checks and updates if the new slides are out of bounds
|
|
if (newPrevious <= 0) {
|
|
oldPrevious = (this.totalItems - 1);
|
|
} else if (newNext >= (this.totalItems - 1)) {
|
|
oldNext = 0;
|
|
}
|
|
// Checks and updates if slide is at the beginning/end
|
|
if (slide === 0) {
|
|
newPrevious = (this.totalItems - 1);
|
|
oldPrevious = (this.totalItems - 2);
|
|
oldNext = (slide + 1);
|
|
} else if (slide === (this.totalItems - 1)) {
|
|
newPrevious = (slide - 1);
|
|
newNext = 0;
|
|
oldNext = 1;
|
|
}
|
|
// Now we've worked out where we are and where we're going,
|
|
// by adding/removing classes we'll trigger the transitions.
|
|
// Reset old next/prev elements to default classes
|
|
this.items[oldPrevious].className = this.itemClassName;
|
|
this.items[oldNext].className = this.itemClassName; // Add new classes
|
|
this.items[newPrevious].className = this.itemClassName + ' prev';
|
|
this.items[slide].className = this.itemClassName + ' active';
|
|
this.items[newNext].className = this.itemClassName + ' next';
|
|
}
|
|
}
|
|
}
|
|
|
|
moveNext () {
|
|
// Check if moving
|
|
if (!this.moving) {
|
|
// If it's the last slide, reset to 0, else +1
|
|
if (this.slide === (this.totalItems - 1)) {
|
|
this.slide = 0;
|
|
} else {
|
|
this.slide++;
|
|
}
|
|
// Move carousel to updated slide
|
|
this.moveCarouselTo(this.slide);
|
|
}
|
|
}
|
|
|
|
movePrev () {
|
|
// Check if moving
|
|
if (!this.moving) {
|
|
// If it's the first slide, set as the last slide, else -1
|
|
if (this.slide === 0) {
|
|
this.slide = (this.totalItems - 1);
|
|
} else {
|
|
this.slide--;
|
|
}
|
|
// Move carousel to updated slide
|
|
this.moveCarouselTo(this.slide);
|
|
}
|
|
}
|
|
|
|
disableInteraction () {
|
|
// Set 'moving' to true for the same duration as our transition.
|
|
// (0.5s = 500ms)
|
|
this.moving = true;
|
|
// setTimeout runs its function once after the given time
|
|
setTimeout(() => {
|
|
this.moving = false
|
|
}, 500);
|
|
}
|
|
|
|
start () {
|
|
this.setInitialClasses();
|
|
this.attachEventListeners();
|
|
// Set moving to false so that the carousel becomes interactive
|
|
this.moving = false;
|
|
}
|
|
}
|