webpack-bootstrap-ui-kit/src/js/ui/carousel.js

212 lines
6.7 KiB
JavaScript
Raw Permalink Normal View History

2022-05-03 20:50:57 +02:00
import Events from '../_events'
2022-09-21 19:43:28 +02:00
import Consts from '../_consts'
2022-05-03 20:50:57 +02:00
import Carousel from 'bootstrap/js/src/carousel'
2021-08-09 18:04:09 +02:00
const CarouselUI = ((window) => {
2022-05-03 20:50:57 +02:00
const NAME = 'js-carousel'
2021-08-09 18:04:09 +02:00
const init = () => {
2022-05-03 20:50:57 +02:00
console.log(`${NAME}: init`)
2021-08-09 18:04:09 +02:00
document.querySelectorAll(`.${NAME}`).forEach((el, i) => {
2022-07-12 16:45:34 +02:00
const interval = el.dataset.bsInterval ? parseInt(el.dataset.bsInterval) : false;
2021-09-05 21:05:55 +02:00
const carousel = new Carousel(el, {
2022-07-12 16:45:34 +02:00
interval,
2022-05-03 20:50:57 +02:00
})
el.ui = carousel
2022-08-14 22:29:09 +02:00
let items = el.querySelectorAll('.carousel-item')
let numberOfItems = parseInt(items.length)
2021-09-05 21:05:55 +02:00
2021-08-09 18:04:09 +02:00
// create next/prev arrows
if (el.dataset.bsArrows) {
2022-05-03 20:50:57 +02:00
const next = document.createElement('button')
next.classList.add('carousel-control-next')
next.setAttribute('type', 'button')
next.setAttribute('aria-label', 'Next Slide')
next.setAttribute('data-bs-target', el.getAttribute('id'))
next.setAttribute('data-bs-slide', 'next')
next.addEventListener('click', (e) => {
carousel.next()
})
2021-08-18 20:51:15 +02:00
next.innerHTML =
2022-05-03 20:50:57 +02:00
'<span class="carousel-control-next-icon" aria-hidden="true"></span><span class="visually-hidden">Next</span>'
el.appendChild(next)
const prev = document.createElement('button')
prev.setAttribute('type', 'button')
prev.setAttribute('aria-label', 'Previous Slide')
prev.classList.add('carousel-control-prev')
prev.setAttribute('data-bs-target', el.getAttribute('id'))
prev.setAttribute('data-bs-slide', 'prev')
prev.addEventListener('click', (e) => {
carousel.prev()
})
2021-08-18 20:51:15 +02:00
prev.innerHTML =
2022-05-03 20:50:57 +02:00
'<span class="carousel-control-prev-icon" aria-hidden="true"></span><span class="visually-hidden">Previous</span>'
el.appendChild(prev)
2021-08-09 18:04:09 +02:00
}
if (el.dataset.bsIndicators) {
2022-05-03 20:50:57 +02:00
const indicators = document.createElement('div')
indicators.classList.add('carousel-indicators')
let i = 0
2022-05-02 21:26:17 +02:00
while (i < numberOfItems) {
2022-05-03 20:50:57 +02:00
const ind = document.createElement('button')
ind.setAttribute('type', 'button')
ind.setAttribute('aria-label', `Slide to #${i + 1}`)
2022-05-03 21:44:33 +02:00
if (i === 0) {
2022-05-03 20:50:57 +02:00
ind.classList.add('active')
2021-08-09 18:04:09 +02:00
}
2022-05-03 20:50:57 +02:00
ind.setAttribute('data-bs-target', el.getAttribute('id'))
ind.setAttribute('data-bs-slide-to', i)
ind.addEventListener('click', (e) => {
const target = e.target
carousel.to(target.getAttribute('data-bs-slide-to'))
indicators.querySelectorAll('.active').forEach((ind2) => {
ind2.classList.remove('active')
})
target.classList.add('active')
})
indicators.appendChild(ind)
i++
2021-08-09 18:04:09 +02:00
}
2022-05-03 20:50:57 +02:00
el.appendChild(indicators)
el.addEventListener('slide.bs.carousel', (e) => {
el.querySelectorAll('.carousel-indicators .active').forEach(
2021-08-18 20:51:15 +02:00
(ind2) => {
2022-05-03 20:50:57 +02:00
ind2.classList.remove('active')
2021-08-18 20:51:15 +02:00
}
2022-05-03 20:50:57 +02:00
)
2021-08-18 20:51:15 +02:00
el.querySelectorAll(
`.carousel-indicators [data-bs-slide-to="${e.to}"]`
).forEach((ind2) => {
2022-05-03 20:50:57 +02:00
ind2.classList.add('active')
})
})
2021-08-09 18:04:09 +02:00
}
2021-09-05 21:05:55 +02:00
2022-05-03 20:50:57 +02:00
if (el.classList.contains('carousel-multislide')) {
2022-07-12 16:45:34 +02:00
const inner = el.querySelector('.carousel-inner')
2022-08-14 22:29:09 +02:00
2023-08-04 00:56:00 +02:00
// add next elements by cloning originals
items.forEach((el, i) => {
const newItem = el.cloneNode(true);
newItem.classList.remove('active');
inner.appendChild(newItem);
});
2022-08-14 22:29:09 +02:00
items = el.querySelectorAll('.carousel-item')
numberOfItems = parseInt(items.length)
2022-07-12 16:45:34 +02:00
// fix animation glitch
inner.style.left = '0px'
2022-09-21 19:43:28 +02:00
const getNumToDisplay = (el) => {
const screenSize = window.detectCSSScreenSize()
2022-09-21 23:13:29 +02:00
let curNum = parseInt(el.dataset[`length${window.globalF.ucwords(screenSize)}`]);
2022-09-21 19:43:28 +02:00
if(!curNum){
curNum = parseInt(el.dataset.length);
}
return Math.min(curNum, numberOfItems)
}
2022-08-14 22:29:09 +02:00
const calculate = (entries) => {
2022-05-03 20:50:57 +02:00
const entry = entries[0]
const el = entry.target
const rect = entry.contentRect
2022-09-21 19:43:28 +02:00
//const width = rect.width
const width = el.querySelector('.carousel-inner-container').clientWidth
2022-05-03 21:44:33 +02:00
// const height = rect.height
2022-09-21 19:43:28 +02:00
const numToDisplay = getNumToDisplay(el)
2022-05-03 20:50:57 +02:00
const itemWidth = width / numToDisplay
el.dataset.itemWidth = itemWidth
el.dataset.numToDisplay = numToDisplay
2023-08-04 00:56:00 +02:00
inner.style.width = `${numberOfItems * itemWidth}px`
items.forEach((el, i) => {
el.style.width = `${itemWidth}px`
})
if (numberOfItems === numToDisplay) {
2022-09-21 19:43:28 +02:00
el.classList.add(`${NAME}-no-slide`)
2022-05-03 20:50:57 +02:00
carousel.pause()
2022-04-19 17:07:22 +02:00
}
2022-08-14 22:29:09 +02:00
};
const calcResize = new window.ResizeObserver(calculate)
calcResize.observe(el)
const resetPosition = () => {
2022-08-14 22:40:48 +02:00
// disable transition
inner.style.transition = 'none'
inner.classList.add('no-transition')
inner.style.left = '0px'
// enable transition
setTimeout(() => {
inner.style.transition = ''
inner.classList.remove('no-transition')
inner.querySelectorAll('.carousel-item').forEach((el) => {
el.classList.remove('active')
})
inner.querySelector('.carousel-item:first-child').classList.add('active')
}, 1000);
2022-08-14 22:29:09 +02:00
};
2021-09-05 21:05:55 +02:00
el.addEventListener('slide.bs.carousel', (e) => {
2022-07-12 16:45:34 +02:00
// infinite scroll
2022-09-21 19:43:28 +02:00
const numToDisplay = getNumToDisplay(el)
2022-08-14 22:29:09 +02:00
console.log(`.${NAME}: ${e.to} ${numberOfItems / 2}`);
2022-07-12 16:45:34 +02:00
2022-08-14 22:29:09 +02:00
if(numberOfItems - numToDisplay < e.to){
2022-07-12 16:45:34 +02:00
e.preventDefault();
2022-08-14 22:29:09 +02:00
resetPosition();
2022-07-12 16:45:34 +02:00
return;
}
//
2021-09-05 21:05:55 +02:00
switch (e.direction) {
case 'left':
2022-05-03 20:50:57 +02:00
inner.style.left = `${-(e.to * el.dataset.itemWidth)}px`
break
2021-09-05 21:05:55 +02:00
case 'right':
2022-05-03 20:50:57 +02:00
inner.style.left = `${-(e.to * el.dataset.itemWidth)}px`
break
2021-09-05 21:05:55 +02:00
}
2022-08-14 22:29:09 +02:00
if(numberOfItems / 2 === e.to){
resetPosition();
}
2022-05-03 20:50:57 +02:00
})
2021-09-05 21:05:55 +02:00
2022-05-03 20:50:57 +02:00
el.classList.add(`${NAME}-multislide-active`)
} else {
if (items.length === 1) {
2022-09-21 19:43:28 +02:00
el.classList.add(`${NAME}-no-slide`)
2022-04-19 18:06:28 +02:00
}
2021-09-05 21:05:55 +02:00
}
2022-07-12 16:45:34 +02:00
if(interval){
el.ui.cycle();
}
el.dataset.ui = el.ui
2022-05-03 20:50:57 +02:00
el.classList.add(`${NAME}-active`)
2022-09-12 22:07:08 +02:00
el.dispatchEvent(new Event(`${NAME}-ready`))
2022-05-03 20:50:57 +02:00
})
}
2021-08-09 18:04:09 +02:00
2022-05-03 20:50:57 +02:00
window.addEventListener(`${Events.LODEDANDREADY}`, init)
window.addEventListener(`${Events.AJAX}`, init)
})(window)
2021-08-09 18:04:09 +02:00
2022-05-03 20:50:57 +02:00
export default CarouselUI