import classesToSelector from '../../shared/classes-to-selector.js';
export default function Pagination({
swiper,
extendParams,
on,
emit
}) {
const pfx = 'swiper-pagination';
extendParams({
pagination: {
el: null,
bulletElement: 'span',
clickable: false,
hideOnClick: false,
renderBullet: null,
renderProgressbar: null,
renderFraction: null,
renderCustom: null,
progressbarOpposite: false,
type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
dynamicBullets: false,
dynamicMainBullets: 1,
formatFractionCurrent: (number) => number,
formatFractionTotal: (number) => number,
bulletClass: `${pfx}-bullet`,
bulletActiveClass: `${pfx}-bullet-active`,
modifierClass: `${pfx}-`,
currentClass: `${pfx}-current`,
totalClass: `${pfx}-total`,
hiddenClass: `${pfx}-hidden`,
progressbarFillClass: `${pfx}-progressbar-fill`,
progressbarOppositeClass: `${pfx}-progressbar-opposite`,
clickableClass: `${pfx}-clickable`,
lockClass: `${pfx}-lock`,
horizontalClass: `${pfx}-horizontal`,
verticalClass: `${pfx}-vertical`,
},
});
swiper.pagination = {
el: null,
$el: null,
bullets: [],
};
let bulletSize;
let dynamicBulletIndex = 0;
function isPaginationDisabled() {
return (
!swiper.params.pagination.el ||
!swiper.pagination.el ||
!swiper.pagination.$el
);
}
function setSideBullets($bulletEl, position) {
const {
bulletActiveClass
} = swiper.params.pagination;
const bullets = swiper.pagination.bullets;
if (bullets[$bulletEl.index + position]) {
bullets[$bulletEl.index + position].addPaginationItemClass(
`${bulletActiveClass}-${position>0?'next':'prev'}`);
}
if (bullets[$bulletEl.index + (position > 0 ? position + 1 : position -
1)]) {
bullets[$bulletEl.index + (position > 0 ? position + 1 : position - 1)].addPaginationItemClass(
`${bulletActiveClass}-${position>0?'next':'prev'}-${position>0?'next':'prev'}`);
}
}
function update() {
// Render || Update Pagination bullets/items
const rtl = swiper.rtl;
const params = swiper.params.pagination;
if (isPaginationDisabled()) return;
const slidesLength =
swiper.virtual && swiper.params.virtual.enabled ?
swiper.virtual.slides.length :
swiper.slides.length;
const $el = swiper.pagination.$el;
// Current/Total
let current;
const total = swiper.params.loop ?
Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) :
swiper.snapGrid.length;
if (swiper.params.loop) {
current = Math.ceil(
(swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup,
);
if (current > slidesLength - 1 - swiper.loopedSlides * 2) {
current -= slidesLength - swiper.loopedSlides * 2;
}
if (current > total - 1) current -= total;
if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
} else if (typeof swiper.snapIndex !== 'undefined') {
current = swiper.snapIndex;
} else {
current = swiper.activeIndex || 0;
}
// Types
if (
params.type === 'bullets' &&
swiper.pagination.bullets &&
swiper.pagination.bullets.length > 0
) {
const bullets = swiper.pagination.bullets;
let firstIndex;
let lastIndex;
let midIndex;
if (params.dynamicBullets) {
bulletSize = bullets[0][swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'];
swiper.$wrapperEl.paginationCss({
[swiper.isHorizontal() ? 'width' :
'height'
]: `${bulletSize * (params.dynamicMainBullets + 4)}px`
});
if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
dynamicBulletIndex += current - (swiper.previousIndex - swiper.loopedSlides || 0);
if (dynamicBulletIndex > params.dynamicMainBullets - 1) {
dynamicBulletIndex = params.dynamicMainBullets - 1;
} else if (dynamicBulletIndex < 0) {
dynamicBulletIndex = 0;
}
}
firstIndex = Math.max(current - dynamicBulletIndex, 0);
lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
midIndex = (lastIndex + firstIndex) / 2;
}
bullets.forEach((item) => {
item.removePaginationItemClass(
['', '-next', '-next-next', '-prev', '-prev-prev', '-main']
.map((suffix) => `${params.bulletActiveClass}${suffix}`)
.join(' '),
);
})
if ($el.length > 1) {
bullets.each((bullet) => {
const $bullet = $(bullet);
const bulletIndex = $bullet.index();
if (bulletIndex === current) {
$bullet.addClass(params.bulletActiveClass);
}
if (params.dynamicBullets) {
if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
$bullet.addClass(`${params.bulletActiveClass}-main`);
}
if (bulletIndex === firstIndex) {
setSideBullets($bullet, 'prev');
}
if (bulletIndex === lastIndex) {
setSideBullets($bullet, 'next');
}
}
});
} else {
const $bullet = bullets[current];
const bulletIndex = $bullet.index;
$bullet.addPaginationItemClass(params.bulletActiveClass);
if (params.dynamicBullets) {
const $firstDisplayedBullet = bullets[firstIndex];
const $lastDisplayedBullet = bullets[lastIndex];
for (let i = firstIndex; i <= lastIndex; i += 1) {
bullets[i].addPaginationItemClass(`${params.bulletActiveClass}-main`);
}
if (swiper.params.loop) {
if (bulletIndex >= bullets.length) {
for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {
bullets[bullets.length - i].addPaginationItemClass(`${params.bulletActiveClass}-main`);
}
bullets
[bullets.length - params.dynamicMainBullets - 1]
.addPaginationItemClass(`${params.bulletActiveClass}-prev`);
} else {
setSideBullets($firstDisplayedBullet, -1);
setSideBullets($lastDisplayedBullet, 1);
}
} else {
setSideBullets($firstDisplayedBullet, -1);
setSideBullets($lastDisplayedBullet, 1);
}
}
}
if (params.dynamicBullets) {
const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
const bulletsOffset =
(bulletSize * dynamicBulletsLength - bulletSize) / 2 - midIndex * bulletSize;
const offsetProp = rtl ? 'right' : 'left';
bullets.forEach((item) => {
item.setCss({
[swiper.isHorizontal() ? offsetProp : 'top']: `${bulletsOffset}px`
})
})
// bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
}
}
if (params.type === 'fraction') {
// $el
// .find(classesToSelector(params.currentClass))
// .text(params.formatFractionCurrent(current + 1));
swiper.native.paginationContent.text = params.formatFractionCurrent(current + 1);
swiper.native.paginationContent.total = params.formatFractionTotal(total);
swiper.native.updateData({
paginationContent: swiper.native.paginationContent,
})
// $el.find(classesToSelector(params.totalClass)).text(params.formatFractionTotal(total));
}
if (params.type === 'progressbar') {
let progressbarDirection;
if (params.progressbarOpposite) {
progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
} else {
progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
}
const scale = (current + 1) / total;
let scaleX = 1;
let scaleY = 1;
if (progressbarDirection === 'horizontal') {
scaleX = scale;
} else {
scaleY = scale;
}
// $el
// .find(classesToSelector(params.progressbarFillClass))
swiper.native.paginationContent.transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`);
swiper.native.paginationContent.transition(swiper.params.speed);
swiper.native.updateData({
paginationContent: swiper.native.paginationContent,
})
}
if (params.type === 'custom' && params.renderCustom) {
$el.html(params.renderCustom(swiper, current + 1, total));
emit('paginationRender', $el[0]);
} else {
emit('paginationUpdate', $el[0]);
}
if (swiper.params.watchOverflow && swiper.enabled) {
swiper.$wrapperEl[swiper.isLocked ? 'addPaginationClass' : 'removePaginationClass'](params.lockClass);
}
}
function render() {
// Render Container
const params = swiper.params.pagination;
if (isPaginationDisabled()) return;
const slidesLength =
swiper.virtual && swiper.params.virtual.enabled ?
swiper.virtual.slides.length :
swiper.slides.length;
const $el = swiper.pagination.$el;
let paginationHTML = 0;
if (params.type === 'bullets') {
let numberOfBullets = swiper.params.loop ?
Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) :
swiper.snapGrid.length;
if (
swiper.params.freeMode &&
swiper.params.freeMode.enabled &&
!swiper.params.loop &&
numberOfBullets > slidesLength
) {
numberOfBullets = slidesLength;
}
for (let i = 0; i < numberOfBullets; i += 1) {
if (params.renderBullet) {
paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
}
// else {
// paginationHTML +=
// `<${params.bulletElement} class="${params.bulletClass}">${params.bulletElement}>`;
// }
// paginationHTML += 1;
else {
swiper.native.paginationType = "bullets";
swiper.native.paginationContent.push({
index: i,
outerWidth: 16,
outerHeight: 16,
classContent: [params.bulletClass],
styleContent: {},
addPaginationItemClass: function(value) {
this.classContent = Array.from(new Set([...this.classContent,
...value.split(" ")
]));
},
removePaginationItemClass: function(value) {
this.classContent = this.classContent.filter(item => !value.split(
" ").includes(item));
},
setCss: function(value) {
// vueNative['itemStyle'] = {
// ...vueNative['itemStyle'],
// ...value
// };Object.keys(value).forEach((item) => {
Object.keys(value).forEach((item) => {
// this.$set(this.itemStyle, item, value[item])
this.styleContent[item] = value[item];
})
// this.$set(this.itemStyle, item, value[item])
}
});
swiper.native.updateData({
paginationType: swiper.native.paginationType,
paginationContent: swiper.native.paginationContent,
})
}
}
// $el.html(paginationHTML);
// swiper.$wrapperEl.addPaginationItemClass(params.bulletClass)
// swiper.pagination.bullets = $el.find(classesToSelector(params.bulletClass));
swiper.pagination.bullets = swiper.native.paginationContent;
}
if (params.type === 'fraction') {
if (params.renderFraction) {
paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
} else {
swiper.native.paginationType = "fraction";
// paginationHTML =
// `` +
// ' / ' +
// ``;
swiper.native.paginationContent = {
currentClass: params.currentClass,
totalClass: params.totalClass
}
swiper.native.updateData({
paginationType: swiper.native.paginationType,
paginationContent: swiper.native.paginationContent,
})
}
}
if (params.type === 'progressbar') {
if (params.renderProgressbar) {
paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
} else {
swiper.native.paginationType = "progressbar";
// paginationHTML = ``;
swiper.native.paginationContent = {
progressbarFillClass: params.progressbarFillClass,
styleContent: {
transform: '',
transitionDuration: ''
},
transition: function(value) {
this.styleContent.transitionDuration = `${value}ms`;
},
transform: function(value) {
this.styleContent.transform = value;
},
}
swiper.native.updateData({
paginationType: swiper.native.paginationType,
paginationContent: swiper.native.paginationContent,
})
}
// $el.html(paginationHTML);
}
if (params.type !== 'custom') {
emit('paginationRender', swiper.pagination.$el[0]);
}
}
function init() {
const params = swiper.params.pagination;
if (!params.el) return;
// swiper.native.showIndicators = true;
swiper.native.updateData({
showIndicators: true
})
let $el = params.el;
if (params.type === 'bullets' && params.clickable) {
swiper.$wrapperEl.addPaginationClass(params.clickableClass);
}
swiper.$wrapperEl.addPaginationClass(params.modifierClass + params.type);
swiper.$wrapperEl.addPaginationClass(params.modifierClass + swiper.params.direction);
if (params.type === 'bullets' && params.dynamicBullets) {
swiper.$wrapperEl.addPaginationClass(`${params.modifierClass}${params.type}-dynamic`);
dynamicBulletIndex = 0;
if (params.dynamicMainBullets < 1) {
params.dynamicMainBullets = 1;
}
}
if (params.type === 'progressbar' && params.progressbarOpposite) {
swiper.$wrapperEl.addPaginationClass(params.progressbarOppositeClass);
}
if (params.clickable) {
swiper.on('paginationItemClick', function onClick(_s, itemIndex) {
let index = itemIndex * swiper.params.slidesPerGroup;
if (swiper.params.loop) index += swiper.loopedSlides;
swiper.slideTo(index);
});
}
Object.assign(swiper.pagination, {
$el,
el: $el,
});
if (!swiper.enabled) {
swiper.$wrapperEl.addPaginationClass(params.lockClass);
}
}
function destroy() {
const params = swiper.params.pagination;
if (isPaginationDisabled()) return;
const $el = swiper.pagination.$el;
if (params.clickable) {
swiper.off('paginationItemClick', classesToSelector(params.bulletClass));
}
}
on('init update', () => {
if (swiper.native.paginationContent) {
swiper.native.updateData({
paginationContent: []
})
}
// swiper.native.paginationContent = [];
init();
render();
update();
});
on('activeIndexChange', () => {
if (swiper.params.loop) {
update();
} else if (typeof swiper.snapIndex === 'undefined') {
update();
}
});
on('snapIndexChange', () => {
if (!swiper.params.loop) {
update();
}
});
on('slidesLengthChange', () => {
if (swiper.params.loop) {
render();
update();
}
});
on('snapGridLengthChange', () => {
if (!swiper.params.loop) {
render();
update();
}
});
on('destroy', () => {
destroy();
});
on('enable disable', () => {
const {
$el
} = swiper.pagination;
if ($el) {
swiper.$wrapperEl[swiper.enabled ? 'removePaginationClass' : 'addPaginationClass'](swiper.params
.pagination.lockClass);
}
});
on('lock unlock', () => {
update();
});
on('click', (_s, e) => {
const targetEl = e.target;
const {
$el
} = swiper.pagination;
if (
swiper.params.pagination.el &&
swiper.params.pagination.hideOnClick &&
$el.length > 0 &&
!$(targetEl).hasClass(swiper.params.pagination.bulletClass)
) {
if (
swiper.navigation &&
((swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) ||
(swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl))
)
return;
const isHidden = $el.hasClass(swiper.params.pagination.hiddenClass);
if (isHidden === true) {
emit('paginationShow');
} else {
emit('paginationHide');
}
$el.toggleClass(swiper.params.pagination.hiddenClass);
}
});
Object.assign(swiper.pagination, {
render,
update,
init,
destroy,
});
}