wp_back/wp-content/plugins/visual-portfolio/assets/js/plugin-swiper.js

432 lines
11 KiB
JavaScript
Raw Normal View History

2024-05-20 15:37:46 +03:00
import isNumber from 'is-number';
import $ from 'jquery';
const $doc = $(document);
const { screenSizes } = window.VPData;
function getSwiperVersion(Swiper) {
let ver = 8;
// in version 8 added new parameter `maxBackfaceHiddenSlides`.
if (typeof Swiper.defaults.maxBackfaceHiddenSlides === 'undefined') {
ver = 7;
}
// in version 7 added new parameter `rewind`.
if (typeof Swiper.defaults.rewind === 'undefined') {
ver = 6;
}
// in version 6 added new parameter `loopPreventsSlide`.
if (typeof Swiper.defaults.loopPreventsSlide === 'undefined') {
ver = 5;
}
return ver;
}
// Extend VP class.
$doc.on('extendClass.vpf', (event, VP) => {
if (event.namespace !== 'vpf') {
return;
}
/**
* Init Swiper plugin
*
* @param {mixed} options - slider options.
*/
VP.prototype.initSwiper = function (options = false) {
const self = this;
if (
self.options.layout === 'slider' &&
typeof window.Swiper !== 'undefined'
) {
const $parent = self.$items_wrap.parent();
$parent.addClass('swiper');
self.$items_wrap.addClass('swiper-wrapper');
self.$items_wrap.children().addClass('swiper-slide');
// calculate responsive.
let slidesPerView = self.options.sliderSlidesPerView || 3;
const breakPoints = {};
if (self.options.sliderEffect === 'fade') {
slidesPerView = 1;
}
if (isNumber(slidesPerView)) {
let count = slidesPerView;
let currentPoint = Math.min(screenSizes.length - 1, count - 1);
for (; currentPoint >= 0; currentPoint -= 1) {
if (
count > 0 &&
typeof screenSizes[currentPoint] !== 'undefined'
) {
breakPoints[screenSizes[currentPoint] + 1] = {
slidesPerView: count,
};
}
count -= 1;
}
slidesPerView = count || 1;
}
let optionsThumbs = false;
let $thumbsParent = false;
options = options || {
speed: (parseFloat(self.options.sliderSpeed) || 0) * 1000,
autoHeight: self.options.sliderItemsHeight === 'auto',
effect: self.options.sliderEffect || 'slide',
// fix fade items collapse (mostly in Default items style).
fadeEffect: {
crossFade: true,
},
spaceBetween: parseFloat(self.options.itemsGap) || 0,
centeredSlides: self.options.sliderCenteredSlides === 'true',
freeMode: {
enabled: self.options.sliderFreeMode === 'true',
sticky: self.options.sliderFreeModeSticky === 'true',
},
loop: self.options.sliderLoop === 'true',
// This feature is cool, but not working properly when loop enabled
// and fast clicking on previous button is not working properly
// https://github.com/nolimits4web/swiper/issues/5945
// loopPreventsSlide: false,
autoplay: parseFloat(self.options.sliderAutoplay) > 0 && {
delay: parseFloat(self.options.sliderAutoplay) * 1000,
disableOnInteraction: false,
},
navigation: self.options.sliderArrows === 'true' && {
nextEl: '.vp-portfolio__items-arrow-next',
prevEl: '.vp-portfolio__items-arrow-prev',
},
pagination: self.options.sliderBullets === 'true' && {
el: '.vp-portfolio__items-bullets',
clickable: true,
dynamicBullets:
self.options.sliderBulletsDynamic === 'true',
renderBullet(index, className) {
return `<span class="${className}" data-bullet-index="${index}" data-bullet-number="${
index + 1
}"></span>`;
},
},
mousewheel: self.options.sliderMousewheel === 'true',
slidesPerView,
breakpoints: breakPoints,
keyboard: true,
grabCursor: true,
preloadImages: false,
// fixes text selection when swipe in the items gap.
touchEventsTarget: 'container',
};
// fix first load slide position (seems like a conflict with lazySizes)
// issue: https://github.com/nk-crew/visual-portfolio/issues/54
if (options.speed === 0) {
options.speed = 1;
}
let positionFix = 0;
options.on = {
transitionEnd() {
if (positionFix === 0) {
positionFix = 1;
this.setTransition(1);
this.setTranslate(this.translate + 0.1);
} else if (positionFix === 1) {
positionFix = 2;
this.slideReset();
}
},
// These events used to add fixes for
// conflict with custom cursor movement.
touchStart(swiper, e) {
self.emitEvent('swiperTouchStart', [swiper, e]);
},
touchMove(swiper, e) {
self.emitEvent('swiperTouchMove', [swiper, e]);
},
touchEnd(swiper, e) {
self.emitEvent('swiperTouchEnd', [swiper, e]);
},
};
self.emitEvent('beforeInitSwiper', [options]);
// thumbnails.
if (self.$slider_thumbnails_wrap.length) {
$thumbsParent = self.$slider_thumbnails_wrap.parent();
$thumbsParent.addClass('swiper');
self.$slider_thumbnails_wrap.addClass('swiper-wrapper');
self.$slider_thumbnails_wrap
.children()
.addClass('swiper-slide');
// calculate responsive.
let thumbnailsPerView =
self.options.sliderThumbnailsPerView || 8;
const thumbnailsBreakPoints = {};
if (isNumber(thumbnailsPerView)) {
let count = thumbnailsPerView;
let currentPoint = Math.min(
screenSizes.length - 1,
count - 1
);
for (; currentPoint >= 0; currentPoint -= 1) {
if (
count > 0 &&
typeof screenSizes[currentPoint] !== 'undefined'
) {
thumbnailsBreakPoints[
screenSizes[currentPoint] + 1
] = {
slidesPerView: count,
};
}
count -= 1;
}
thumbnailsPerView = count || 1;
}
optionsThumbs = {
autoHeight: self.options.sliderThumbnailsHeight === 'auto',
effect: 'slide',
spaceBetween:
parseFloat(self.options.sliderThumbnailsGap) || 0,
loop: false,
// This feature is cool, but not working properly when loop enabled
// and fast clicking on previous button is not working properly
// https://github.com/nolimits4web/swiper/issues/5945
// loopPreventsSlide: false,
freeMode: {
enabled: true,
sticky: true,
},
loopedSlides: 5,
slidesPerView: thumbnailsPerView,
breakpoints: thumbnailsBreakPoints,
keyboard: true,
grabCursor: true,
watchSlidesVisibility: true,
watchSlidesProgress: true,
preloadImages: false,
// fixed text selection when swipe in the items gap.
touchEventsTarget: 'container',
on: {
// These events used to add fixes for
// conflict with custom cursor movement.
touchStart(swiper, e) {
self.emitEvent('swiperTouchStart', [swiper, e]);
},
touchMove(swiper, e) {
self.emitEvent('swiperTouchMove', [swiper, e]);
},
touchEnd(swiper, e) {
self.emitEvent('swiperTouchEnd', [swiper, e]);
},
},
};
}
// Fallbacks for old Swiper versions.
(() => {
const swiperVersion = getSwiperVersion(window.Swiper);
const isThumbsEnabled =
optionsThumbs && $thumbsParent && $thumbsParent[0];
// Since v7 used container class `swiper`, we should also add old `swiper-container` class.
if (swiperVersion < 7) {
$parent.addClass('swiper-container');
if (isThumbsEnabled) {
$thumbsParent.addClass('swiper-container');
}
}
// Since v7 freeMode options moved under `freeMode` object.
if (swiperVersion < 7) {
options.freeModeSticky = options.freeMode.sticky;
options.freeMode = options.freeMode.enabled;
if (isThumbsEnabled) {
optionsThumbs.freeModeSticky =
optionsThumbs.freeMode.sticky;
optionsThumbs.freeMode = optionsThumbs.freeMode.enabled;
}
}
// Since v5 `breakpointsInverse` option is removed and it is now `true` by default, but in older versions it was `false`.
if (swiperVersion >= 5) {
options.breakpointsInverse = true;
if (isThumbsEnabled) {
optionsThumbs.breakpointsInverse = true;
}
}
})();
// Init Swiper.
if (optionsThumbs && $thumbsParent && $thumbsParent[0]) {
const swiperThumbs = new window.Swiper(
$thumbsParent[0],
optionsThumbs
);
options.thumbs = {
swiper: swiperThumbs,
};
}
const instance = new window.Swiper($parent[0], options);
// Autoplay Hover Pause.
if (
self.options.sliderAutoplayHoverPause === 'true' &&
parseFloat(self.options.sliderAutoplay) > 0
) {
self.$item.on(
`mouseenter.vpf-uid-${self.uid}`,
'.swiper',
() => {
$parent[0].swiper.autoplay.stop();
}
);
self.$item.on(
`mouseleave.vpf-uid-${self.uid}`,
'.swiper',
() => {
$parent[0].swiper.autoplay.start();
}
);
}
self.emitEvent('initSwiper', [options, instance]);
}
};
/**
* Destroy Swiper plugin
*/
VP.prototype.destroySwiper = function () {
const self = this;
const $parent = self.$items_wrap.parent();
const $thumbsParent = self.$slider_thumbnails_wrap.length
? self.$slider_thumbnails_wrap.parent()
: false;
const SliderSwiper = $parent[0].swiper;
const ThumbsSwiper = $thumbsParent ? $thumbsParent[0].swiper : false;
let isDestroyed = false;
// Thumbnails.
if (ThumbsSwiper) {
ThumbsSwiper.destroy();
$thumbsParent.removeClass('swiper');
self.$slider_thumbnails_wrap.removeClass('swiper-wrapper');
self.$slider_thumbnails_wrap.children().removeClass('swiper-slide');
isDestroyed = true;
}
// Slider.
if (SliderSwiper) {
SliderSwiper.destroy();
$parent.removeClass('swiper');
self.$items_wrap.removeClass('swiper-wrapper');
self.$items_wrap.children().removeClass('swiper-slide');
$parent
.find('.vp-portfolio__items-bullets')
.removeClass(
'swiper-pagination-clickable swiper-pagination-bullets-dynamic'
)
.removeAttr('style')
.html('');
isDestroyed = true;
}
if (isDestroyed) {
self.emitEvent('destroySwiper');
}
};
});
// Add Items.
$doc.on('addItems.vpf', (event, self, $items, removeExisting, $newVP) => {
if (event.namespace !== 'vpf') {
return;
}
const Swiper = self.$items_wrap.parent()[0].swiper;
if (!Swiper) {
return;
}
// Slider.
{
if (removeExisting) {
Swiper.removeAllSlides();
}
const appendArr = [];
$items.addClass('swiper-slide').each(function () {
appendArr.push(this);
});
Swiper.appendSlide(appendArr);
}
// Thumbnails.
const ThumbsSwiper = self.$slider_thumbnails_wrap.length
? self.$slider_thumbnails_wrap.parent()[0].swiper
: false;
if (ThumbsSwiper) {
if (removeExisting) {
ThumbsSwiper.removeAllSlides();
}
const appendArr = [];
$newVP
.find('.vp-portfolio__thumbnails > .vp-portfolio__thumbnail-wrap')
.clone()
.addClass('swiper-slide')
.each(function () {
appendArr.push(this);
});
ThumbsSwiper.appendSlide(appendArr);
}
});
// Init.
$doc.on('init.vpf', (event, self) => {
if (event.namespace !== 'vpf') {
return;
}
self.initSwiper();
});
// Destroy.
$doc.on('destroy.vpf', (event, self) => {
if (event.namespace !== 'vpf') {
return;
}
self.destroySwiper();
});