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; } }