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}">`; // } // 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, }); }