I would like to make a simple carousel without libraries.
I defined a class but I can't access my variable outside of my constructor.
I use a script defer with my DOMContentLoaded event.
class Carousel {
/**
* @param {HTMLElement} element
* @param {Object} options.slidesToScroll Number of elements to slide
* @param {Object} options.slidesVisible Number of elements to display
*/
constructor (element, options = {}) {
this.element = element
this.options = Object.assign({}, {
slidesToScroll: 1,
slidesVisible: 1
}, options)
let children = [].slice.call(element.children)
let currentItem = 0
this.root = this.createDivWithClass('carousel')
this.container = this.createDivWithClass('carousel-container')
this.root.appendChild(this.container)
this.element.appendChild(this.root)
this.items = children.map((child) => {
let item = this.createDivWithClass('carousel-item')
item.appendChild(child)
this.container.appendChild(item)
return item
});
this.setStyle()
this.createNavigation()
}
/**
* Applies the correct dimensions to the items in the carousel
*/
setStyle () {
let ratio = this.items.length / this.options.slidesVisible
this.container.style.width = (ratio * 100) + "%"
this.items.forEach(item => item.style.width = ((100 / this.options.slidesVisible) / ratio) + "%")
}
createNavigation () {
let nextButton = this.createDivWithClass('carousel-next')
let prevButton = this.createDivWithClass('carousel-prev')
this.root.appendChild(nextButton)
this.root.appendChild(prevButton)
nextButton.addEventListener('click', this.next.bind(this))
prevButton.addEventListener('click', this.prev.bind(this))
}
next () {
this.goToItem(this.currentItem + this.options.slidesToScroll)
}
prev () {
this.goToItem(this.currentItem - this.options.slidesToScroll)
}
/**
* Moves the carousel to the targeted element
* @param {number} index
*/
goToItem (index) {
this.currentItem = index
let translateX = index * (-100 / this.items.length)
this.container.style.transform = 'translate3d(' + translateX + '%, 0, 0)'
console.log("translateX", translateX);
console.log("currentItem", this.currentItem);
console.log("typeof(currentItem)", typeof(this.currentItem));
console.log("typeof(index)", typeof(index));
console.log("index", index);
}
/**
*
* @param {string} className
* @returns {HTMLElement}
*/
createDivWithClass (className) {
let div = document.createElement('div')
div.setAttribute('class', className)
return div
}
}
document.addEventListener('DOMContentLoaded', function () {
new Carousel(document.querySelector('#carousel1'), {
slidesVisible: 3,
slidesToScroll: 1
})
})
Results of my logs :
translateX NaN
currentItem NaN
typeof(currentItem) number
typeof(index) number
index NaN
In the DOM, I get this :
<div id="carousel1">
<div class="carousel">
<div class="carousel-container" style="width: 166.667%">
<div class="carousel-item" style="width: 20%"></div>
<div class="carousel-item" style="width: 20%"></div>
<div class="carousel-item" style="width: 20%"></div>
<div class="carousel-item" style="width: 20%"></div>
<div class="carousel-item" style="width: 20%"></div>
</div>
<div class="carousel-next"></div>
<div class="carousel-prev"></div>
</div>
</div>
When I give a value to my currentItem, I can see my function works :
goToItem () {
let index = 1
let translateX = index * (-100 / this.items.length)
this.container.style.transform = 'translate3d(' + translateX + '%, 0, 0)'
console.log("translateX", translateX);
}
Results of my logs :
translateX -20
I should have the index incremented with each click.
Do you know why my variable is NaN ?
Maybe try declaring the function at the start instead of the end.