export default function loopFix({ slideRealIndex, slideTo = true, direction, setTranslate, activeSlideIndex, byController, byMousewheel } = {}) { const swiper = this; if (!swiper.params.loop) return; swiper.emit('beforeLoopFix'); const { slides, allowSlidePrev, allowSlideNext, slidesEl, params } = swiper; swiper.allowSlidePrev = true; swiper.allowSlideNext = true; if (swiper.virtual && params.virtual.enabled) { if (slideTo) { if (!params.centeredSlides && swiper.snapIndex === 0) { swiper.slideTo(swiper.virtual.slides.length, 0, false, true); } else if (params.centeredSlides && swiper.snapIndex < params.slidesPerView) { swiper.slideTo(swiper.virtual.slides.length + swiper.snapIndex, 0, false, true); } else if (swiper.snapIndex === swiper.snapGrid.length - 1) { swiper.slideTo(swiper.virtual.slidesBefore, 0, false, true); } } swiper.allowSlidePrev = allowSlidePrev; swiper.allowSlideNext = allowSlideNext; swiper.emit('loopFix'); return; } const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10)); let loopedSlides = params.loopedSlides || slidesPerView; if (loopedSlides % params.slidesPerGroup !== 0) { loopedSlides += params.slidesPerGroup - loopedSlides % params.slidesPerGroup; } swiper.loopedSlides = loopedSlides; const prependSlidesIndexes = []; const appendSlidesIndexes = []; let activeIndex = swiper.activeIndex; if (typeof activeSlideIndex === 'undefined') { activeSlideIndex = swiper.getSlideIndex(swiper.slides.filter(el => el.classList.contains(params.slideActiveClass))[0]); } else { activeIndex = activeSlideIndex; } const isNext = direction === 'next' || !direction; const isPrev = direction === 'prev' || !direction; let slidesPrepended = 0; let slidesAppended = 0; // prepend last slides before start if (activeSlideIndex < loopedSlides) { slidesPrepended = Math.max(loopedSlides - activeSlideIndex, params.slidesPerGroup); for (let i = 0; i < loopedSlides - activeSlideIndex; i += 1) { const index = i - Math.floor(i / slides.length) * slides.length; prependSlidesIndexes.push(slides.length - index - 1); } } else if (activeSlideIndex /* + slidesPerView */ > swiper.slides.length - loopedSlides * 2) { slidesAppended = Math.max(activeSlideIndex - (swiper.slides.length - loopedSlides * 2), params.slidesPerGroup); for (let i = 0; i < slidesAppended; i += 1) { const index = i - Math.floor(i / slides.length) * slides.length; appendSlidesIndexes.push(index); } } if (isPrev) { prependSlidesIndexes.forEach(index => { swiper.slides[index].swiperLoopMoveDOM = true; slidesEl.prepend(swiper.slides[index]); swiper.slides[index].swiperLoopMoveDOM = false; }); } if (isNext) { appendSlidesIndexes.forEach(index => { swiper.slides[index].swiperLoopMoveDOM = true; slidesEl.append(swiper.slides[index]); swiper.slides[index].swiperLoopMoveDOM = false; }); } swiper.recalcSlides(); if (params.slidesPerView === 'auto') { swiper.updateSlides(); } if (params.watchSlidesProgress) { swiper.updateSlidesOffset(); } if (slideTo) { if (prependSlidesIndexes.length > 0 && isPrev) { if (typeof slideRealIndex === 'undefined') { const currentSlideTranslate = swiper.slidesGrid[activeIndex]; const newSlideTranslate = swiper.slidesGrid[activeIndex + slidesPrepended]; const diff = newSlideTranslate - currentSlideTranslate; if (byMousewheel) { swiper.setTranslate(swiper.translate - diff); } else { swiper.slideTo(activeIndex + slidesPrepended, 0, false, true); if (setTranslate) { swiper.touches[swiper.isHorizontal() ? 'startX' : 'startY'] += diff; } } } else { if (setTranslate) { swiper.slideToLoop(slideRealIndex, 0, false, true); } } } else if (appendSlidesIndexes.length > 0 && isNext) { if (typeof slideRealIndex === 'undefined') { const currentSlideTranslate = swiper.slidesGrid[activeIndex]; const newSlideTranslate = swiper.slidesGrid[activeIndex - slidesAppended]; const diff = newSlideTranslate - currentSlideTranslate; if (byMousewheel) { swiper.setTranslate(swiper.translate - diff); } else { swiper.slideTo(activeIndex - slidesAppended, 0, false, true); if (setTranslate) { swiper.touches[swiper.isHorizontal() ? 'startX' : 'startY'] += diff; } } } else { swiper.slideToLoop(slideRealIndex, 0, false, true); } } } swiper.allowSlidePrev = allowSlidePrev; swiper.allowSlideNext = allowSlideNext; if (swiper.controller && swiper.controller.control && !byController) { const loopParams = { slideRealIndex, slideTo: false, direction, setTranslate, activeSlideIndex, byController: true }; if (Array.isArray(swiper.controller.control)) { swiper.controller.control.forEach(c => { if (!c.destroyed && c.params.loop) c.loopFix(loopParams); }); } else if (swiper.controller.control instanceof swiper.constructor && swiper.controller.control.params.loop) { swiper.controller.control.loopFix(loopParams); } } swiper.emit('loopFix'); }