import { elementChildren, elementOuterSize, elementStyle, setCSSProperty } from '../../shared/utils.js'; export default function updateSlides() { const swiper = this; function getDirectionLabel(property) { if (swiper.isHorizontal()) { return property; } // prettier-ignore return { 'width': 'height', 'margin-top': 'margin-left', 'margin-bottom ': 'margin-right', 'margin-left': 'margin-top', 'margin-right': 'margin-bottom', 'padding-left': 'padding-top', 'padding-right': 'padding-bottom', 'marginRight': 'marginBottom' }[property]; } function getDirectionPropertyValue(node, label) { return parseFloat(node.getPropertyValue(getDirectionLabel(label)) || 0); } const params = swiper.params; const { wrapperEl, slidesEl, size: swiperSize, rtlTranslate: rtl, wrongRTL } = swiper; const isVirtual = swiper.virtual && params.virtual.enabled; const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length; const slides = elementChildren(slidesEl, `.${swiper.params.slideClass}, swiper-slide`); const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length; let snapGrid = []; const slidesGrid = []; const slidesSizesGrid = []; let offsetBefore = params.slidesOffsetBefore; if (typeof offsetBefore === 'function') { offsetBefore = params.slidesOffsetBefore.call(swiper); } let offsetAfter = params.slidesOffsetAfter; if (typeof offsetAfter === 'function') { offsetAfter = params.slidesOffsetAfter.call(swiper); } const previousSnapGridLength = swiper.snapGrid.length; const previousSlidesGridLength = swiper.slidesGrid.length; let spaceBetween = params.spaceBetween; let slidePosition = -offsetBefore; let prevSlideSize = 0; let index = 0; if (typeof swiperSize === 'undefined') { return; } if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize; } else if (typeof spaceBetween === 'string') { spaceBetween = parseFloat(spaceBetween); } swiper.virtualSize = -spaceBetween; // reset margins slides.forEach(slideEl => { if (rtl) { slideEl.style.marginLeft = ''; } else { slideEl.style.marginRight = ''; } slideEl.style.marginBottom = ''; slideEl.style.marginTop = ''; }); // reset cssMode offsets if (params.centeredSlides && params.cssMode) { setCSSProperty(wrapperEl, '--swiper-centered-offset-before', ''); setCSSProperty(wrapperEl, '--swiper-centered-offset-after', ''); } const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid; if (gridEnabled) { swiper.grid.initSlides(slidesLength); } // Calc slides let slideSize; const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => { return typeof params.breakpoints[key].slidesPerView !== 'undefined'; }).length > 0; for (let i = 0; i < slidesLength; i += 1) { slideSize = 0; let slide; if (slides[i]) slide = slides[i]; if (gridEnabled) { swiper.grid.updateSlide(i, slide, slidesLength, getDirectionLabel); } if (slides[i] && elementStyle(slide, 'display') === 'none') continue; // eslint-disable-line if (params.slidesPerView === 'auto') { if (shouldResetSlideSize) { slides[i].style[getDirectionLabel('width')] = ``; } const slideStyles = getComputedStyle(slide); const currentTransform = slide.style.transform; const currentWebKitTransform = slide.style.webkitTransform; if (currentTransform) { slide.style.transform = 'none'; } if (currentWebKitTransform) { slide.style.webkitTransform = 'none'; } if (params.roundLengths) { slideSize = swiper.isHorizontal() ? elementOuterSize(slide, 'width', true) : elementOuterSize(slide, 'height', true); } else { // eslint-disable-next-line const width = getDirectionPropertyValue(slideStyles, 'width'); const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left'); const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right'); const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left'); const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right'); const boxSizing = slideStyles.getPropertyValue('box-sizing'); if (boxSizing && boxSizing === 'border-box') { slideSize = width + marginLeft + marginRight; } else { const { clientWidth, offsetWidth } = slide; slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth); } } if (currentTransform) { slide.style.transform = currentTransform; } if (currentWebKitTransform) { slide.style.webkitTransform = currentWebKitTransform; } if (params.roundLengths) slideSize = Math.floor(slideSize); } else { slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView; if (params.roundLengths) slideSize = Math.floor(slideSize); if (slides[i]) { slides[i].style[getDirectionLabel('width')] = `${slideSize}px`; } } if (slides[i]) { slides[i].swiperSlideSize = slideSize; } slidesSizesGrid.push(slideSize); if (params.centeredSlides) { slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween; if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween; if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween; if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0; if (params.roundLengths) slidePosition = Math.floor(slidePosition); if (index % params.slidesPerGroup === 0) snapGrid.push(slidePosition); slidesGrid.push(slidePosition); } else { if (params.roundLengths) slidePosition = Math.floor(slidePosition); if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition); slidesGrid.push(slidePosition); slidePosition = slidePosition + slideSize + spaceBetween; } swiper.virtualSize += slideSize + spaceBetween; prevSlideSize = slideSize; index += 1; } swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter; if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) { wrapperEl.style.width = `${swiper.virtualSize + spaceBetween}px`; } if (params.setWrapperSize) { wrapperEl.style[getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`; } if (gridEnabled) { swiper.grid.updateWrapperSize(slideSize, snapGrid, getDirectionLabel); } // Remove last grid elements depending on width if (!params.centeredSlides) { const newSlidesGrid = []; for (let i = 0; i < snapGrid.length; i += 1) { let slidesGridItem = snapGrid[i]; if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem); if (snapGrid[i] <= swiper.virtualSize - swiperSize) { newSlidesGrid.push(slidesGridItem); } } snapGrid = newSlidesGrid; if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) { snapGrid.push(swiper.virtualSize - swiperSize); } } if (isVirtual && params.loop) { const size = slidesSizesGrid[0] + spaceBetween; if (params.slidesPerGroup > 1) { const groups = Math.ceil((swiper.virtual.slidesBefore + swiper.virtual.slidesAfter) / params.slidesPerGroup); const groupSize = size * params.slidesPerGroup; for (let i = 0; i < groups; i += 1) { snapGrid.push(snapGrid[snapGrid.length - 1] + groupSize); } } for (let i = 0; i < swiper.virtual.slidesBefore + swiper.virtual.slidesAfter; i += 1) { if (params.slidesPerGroup === 1) { snapGrid.push(snapGrid[snapGrid.length - 1] + size); } slidesGrid.push(slidesGrid[slidesGrid.length - 1] + size); swiper.virtualSize += size; } } if (snapGrid.length === 0) snapGrid = [0]; if (spaceBetween !== 0) { const key = swiper.isHorizontal() && rtl ? 'marginLeft' : getDirectionLabel('marginRight'); slides.filter((_, slideIndex) => { if (!params.cssMode || params.loop) return true; if (slideIndex === slides.length - 1) { return false; } return true; }).forEach(slideEl => { slideEl.style[key] = `${spaceBetween}px`; }); } if (params.centeredSlides && params.centeredSlidesBounds) { let allSlidesSize = 0; slidesSizesGrid.forEach(slideSizeValue => { allSlidesSize += slideSizeValue + (spaceBetween || 0); }); allSlidesSize -= spaceBetween; const maxSnap = allSlidesSize - swiperSize; snapGrid = snapGrid.map(snap => { if (snap <= 0) return -offsetBefore; if (snap > maxSnap) return maxSnap + offsetAfter; return snap; }); } if (params.centerInsufficientSlides) { let allSlidesSize = 0; slidesSizesGrid.forEach(slideSizeValue => { allSlidesSize += slideSizeValue + (spaceBetween || 0); }); allSlidesSize -= spaceBetween; if (allSlidesSize < swiperSize) { const allSlidesOffset = (swiperSize - allSlidesSize) / 2; snapGrid.forEach((snap, snapIndex) => { snapGrid[snapIndex] = snap - allSlidesOffset; }); slidesGrid.forEach((snap, snapIndex) => { slidesGrid[snapIndex] = snap + allSlidesOffset; }); } } Object.assign(swiper, { slides, snapGrid, slidesGrid, slidesSizesGrid }); if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) { setCSSProperty(wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`); setCSSProperty(wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`); const addToSnapGrid = -swiper.snapGrid[0]; const addToSlidesGrid = -swiper.slidesGrid[0]; swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid); swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid); } if (slidesLength !== previousSlidesLength) { swiper.emit('slidesLengthChange'); } if (snapGrid.length !== previousSnapGridLength) { if (swiper.params.watchOverflow) swiper.checkOverflow(); swiper.emit('snapGridLengthChange'); } if (slidesGrid.length !== previousSlidesGridLength) { swiper.emit('slidesGridLengthChange'); } if (params.watchSlidesProgress) { swiper.updateSlidesOffset(); } if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) { const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`; const hasClassBackfaceClassAdded = swiper.el.classList.contains(backFaceHiddenClass); if (slidesLength <= params.maxBackfaceHiddenSlides) { if (!hasClassBackfaceClassAdded) swiper.el.classList.add(backFaceHiddenClass); } else if (hasClassBackfaceClassAdded) { swiper.el.classList.remove(backFaceHiddenClass); } } }