xbase-2.x-dev/js/carousel-init.js
js/carousel-init.js
(function () {
/**
* Return element preset.
*/
function getElementPresetName(element) {
var presetName;
// Get preset name
element.classList.forEach(className => {
const presetMatches = className.match(/^carousel-preset-(.+)$/);
if (presetMatches) {
presetName = Drupal.camelize(presetMatches[1]);
return false;
}
});
return presetName;
}
/**
* Wrap all children to new element.
*
* Example before:
* <div class="parent">
* <div class="child"></div>
* <div class="child"></div>
* </div>
* After:
* <div class="parent">
* <div class="inner">
* <div class="child"></div>
* <div class="child"></div>
* </div>
* </div>
*/
function wrapChildren(element, wrapperEl) {
if (!wrapperEl) {
wrapperEl = document.createElement('div');
}
while (element.children.length) {
wrapperEl.append(element.children[0]);
}
element.append(wrapperEl);
return wrapperEl;
}
/**
* Create element and append to owner.
*/
function createElementAndAppendTo(tagName, className, ownerEl) {
const element = document.createElement(tagName);
if (className) {
if (Array.isArray(className)) {
element.classList.add(...className);
}
else {
element.classList.add(className);
}
}
if (ownerEl) {
ownerEl.append(element);
}
return element;
}
/**
* Create required elements and add classes.
*/
function preprocessCarouselElement(carouselEl, options) {
carouselEl.classList.add('carousel', 'swiper-container');
// Create swiper element
const swiperEl = wrapChildren(carouselEl);
swiperEl.classList.add('swiper');
// Add "swiper-slide" class to slides
for (const slideEl of swiperEl.children) {
slideEl.classList.add('swiper-slide');
}
// Create navigation elements outside swiper element
if (options.navigation) {
if (typeof options.navigation == 'boolean') {
options.navigation = {};
}
if (!options.navigation.el) {
// options.navigation.el it's custom option
options.navigation.el = createElementAndAppendTo('div', 'swiper-navigation', carouselEl);
}
if (!options.navigation.prevEl) {
options.navigation.prevEl = createElementAndAppendTo('div', ['swiper-navigation-button', 'swiper-button-prev'], options.navigation.el);
}
if (!options.navigation.nextEl) {
options.navigation.nextEl = createElementAndAppendTo('div', ['swiper-navigation-button', 'swiper-button-next'], options.navigation.el);
}
}
// Create pagination element outside swiper element
if (options.pagination) {
if (typeof options.pagination == 'boolean') {
options.pagination = {};
}
if (!options.pagination.el) {
options.pagination.el = createElementAndAppendTo('div', 'swiper-pagination', carouselEl);
}
}
}
/**
* Create carousel.
*/
Drupal.carousel = function (carouselEl, presetName = '', options = {}) {
// Error handlers
if (!presetName) {
console.error('Carousel preset name not found.');
return false;
}
if (!Drupal.carouselPresets) {
console.error('Carousel presets not exist.');
return false;
}
if (!Drupal.carouselPresets[presetName]) {
console.error('Carousel preset "' + presetName + '" not exist.');
return false;
}
if (!carouselEl) {
console.error('Carousel element not exist.');
return false;
}
// Merge options
options = {createElements: true, ...Drupal.carouselPresets[presetName], ...options};
// Create required elements and add classes
if (options.createElements) {
preprocessCarouselElement(carouselEl, options);
}
// Fix bug when not work slidesPerGroupAuto:true
// Set slidesPerGroup option from css variable
if (options.slidesPerGroupAuto) {
options.slidesPerGroup = Drupal.getCssVariable('--carousel-slides-count', carouselEl, 1, 'int');
}
const swiperEl = carouselEl.querySelector('.swiper');
const swiper = new Swiper(swiperEl, options);
// Fix bug when not work slidesPerGroupAuto:true
if (options.slidesPerGroupAuto) {
/** @param {Swiper} swiper */
swiper.on('beforeResize', (swiper) => {
swiper.params.slidesPerGroup = Drupal.getCssVariable('--carousel-slides-count', swiper.el, 1, 'int');
});
}
}
/**
* Drupal behaviors.
*/
Drupal.behaviors.carousel = {
attach: function (context, settings) {
if (context.tagName == 'SCRIPT' || !window.Swiper) {
return;
}
once('carousel', '.carousel', context).forEach(carouselEl => {
Drupal.carousel(carouselEl, getElementPresetName(carouselEl));
});
}
};
})();
