Skip to content

Commit

Permalink
feat(lazy): simplify Lazy module in favor of native loading="lazy"
Browse files Browse the repository at this point in the history
  • Loading branch information
nolimits4web committed Nov 10, 2022
1 parent 4d02653 commit d46d5d0
Show file tree
Hide file tree
Showing 7 changed files with 20 additions and 384 deletions.
3 changes: 0 additions & 3 deletions src/components-shared/update-on-virtual-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ export const updateOnVirtualData = (swiper) => {
swiper.updateSlides();
swiper.updateProgress();
swiper.updateSlidesClasses();
if (swiper.lazy && swiper.params.lazy.enabled) {
swiper.lazy.load();
}
if (swiper.parallax && swiper.params.parallax && swiper.params.parallax.enabled) {
swiper.parallax.setTranslate();
}
Expand Down
2 changes: 0 additions & 2 deletions src/components-shared/update-swiper.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@ function updateSwiper({
if (changedParams.includes('children') && slides && virtual && currentParams.virtual.enabled) {
virtual.slides = slides;
virtual.update(true);
} else if (changedParams.includes('children') && swiper.lazy && swiper.params.lazy.enabled) {
swiper.lazy.load();
}

if (needThumbsInit) {
Expand Down
8 changes: 8 additions & 0 deletions src/element/swiper-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,20 @@ class SwiperSlide extends HTMLElement {
}

initialize() {
const lazy =
this.lazy || this.getAttribute('lazy') === '' || this.getAttribute('lazy') === 'true';

this.tempDiv.innerHTML = `
<slot />
`;
[...this.tempDiv.children].forEach((el) => {
this.shadowEl.appendChild(el);
});
if (lazy) {
const lazyDiv = document.createElement('div');
lazyDiv.classList.add('swiper-lazy-preloader');
this.appendChild(lazyDiv);
}
}

connectedCallback() {
Expand Down
303 changes: 10 additions & 293 deletions src/modules/lazy/lazy.js
Original file line number Diff line number Diff line change
@@ -1,311 +1,28 @@
import { getWindow } from 'ssr-window';
import $ from '../../shared/dom.js';

export default function Lazy({ swiper, extendParams, on, emit }) {
export default function Lazy({ swiper, extendParams, on }) {
extendParams({
lazy: {
checkInView: false,
enabled: false,
loadPrevNext: false,
loadPrevNextAmount: 1,
loadOnTransitionStart: false,
scrollingElement: '',

elementClass: 'swiper-lazy',
loadingClass: 'swiper-lazy-loading',
loadedClass: 'swiper-lazy-loaded',
preloaderClass: 'swiper-lazy-preloader',
},
});

swiper.lazy = {};

let scrollHandlerAttached = false;
let initialImageLoaded = false;
const slideSelector = () => (swiper.isElement ? `swiper-slide` : `.${swiper.params.slideClass}`);

function loadInSlide(index, loadInDuplicate = true) {
const params = swiper.params.lazy;
if (typeof index === 'undefined') return;
if (swiper.slides.length === 0) return;
const isVirtual = swiper.virtual && swiper.params.virtual.enabled;

const $slideEl = isVirtual
? swiper.$wrapperEl.children(`${slideSelector()}[data-swiper-slide-index="${index}"]`)
: swiper.slides.eq(index);

const $images = $slideEl.find(
`.${params.elementClass}:not(.${params.loadedClass}):not(.${params.loadingClass})`,
);
if (
$slideEl.hasClass(params.elementClass) &&
!$slideEl.hasClass(params.loadedClass) &&
!$slideEl.hasClass(params.loadingClass)
) {
$images.push($slideEl[0]);
}
if ($images.length === 0) return;

$images.each((imageEl) => {
const $imageEl = $(imageEl);
$imageEl.addClass(params.loadingClass);

const background = $imageEl.attr('data-background');
const src = $imageEl.attr('data-src');
const srcset = $imageEl.attr('data-srcset');
const sizes = $imageEl.attr('data-sizes');
const $pictureEl = $imageEl.parent('picture');

swiper.loadImage($imageEl[0], src || background, srcset, sizes, false, () => {
if (
typeof swiper === 'undefined' ||
swiper === null ||
!swiper ||
(swiper && !swiper.params) ||
swiper.destroyed
)
return;
if (background) {
$imageEl.css('background-image', `url("${background}")`);
$imageEl.removeAttr('data-background');
} else {
if (srcset) {
$imageEl.attr('srcset', srcset);
$imageEl.removeAttr('data-srcset');
}
if (sizes) {
$imageEl.attr('sizes', sizes);
$imageEl.removeAttr('data-sizes');
}
if ($pictureEl.length) {
$pictureEl.children('source').each((sourceEl) => {
const $source = $(sourceEl);

if ($source.attr('data-srcset')) {
$source.attr('srcset', $source.attr('data-srcset'));
$source.removeAttr('data-srcset');
}
});
}
if (src) {
$imageEl.attr('src', src);
$imageEl.removeAttr('data-src');
}
}

$imageEl.addClass(params.loadedClass).removeClass(params.loadingClass);
$slideEl.find(`.${params.preloaderClass}`).remove();
if (swiper.params.loop && loadInDuplicate) {
const slideOriginalIndex = $slideEl.attr('data-swiper-slide-index');
if ($slideEl.hasClass(swiper.params.slideDuplicateClass)) {
const originalSlide = swiper.$wrapperEl.children(
`[data-swiper-slide-index="${slideOriginalIndex}"]:not(.${swiper.params.slideDuplicateClass})`,
);
loadInSlide(originalSlide.index(), false);
} else {
const duplicatedSlide = swiper.$wrapperEl.children(
`.${swiper.params.slideDuplicateClass}[data-swiper-slide-index="${slideOriginalIndex}"]`,
);
loadInSlide(duplicatedSlide.index(), false);
}
}
emit('lazyImageReady', $slideEl[0], $imageEl[0]);
if (swiper.params.autoHeight) {
swiper.updateAutoHeight();
}
});

emit('lazyImageLoad', $slideEl[0], $imageEl[0]);
});
}

function load() {
const { $wrapperEl, params: swiperParams, slides, activeIndex } = swiper;
const isVirtual = swiper.virtual && swiperParams.virtual.enabled;
const params = swiperParams.lazy;

let slidesPerView = swiperParams.slidesPerView;
if (slidesPerView === 'auto') {
slidesPerView = 0;
}

function slideExist(index) {
if (isVirtual) {
if ($wrapperEl.children(`${slideSelector()}[data-swiper-slide-index="${index}"]`).length) {
return true;
}
} else if (slides[index]) return true;
return false;
}

function slideIndex(slideEl) {
if (isVirtual) {
return $(slideEl).attr('data-swiper-slide-index');
}
return $(slideEl).index();
}

if (!initialImageLoaded) initialImageLoaded = true;
if (swiper.params.watchSlidesProgress) {
$wrapperEl.children(`.${swiperParams.slideVisibleClass}`).each((slideEl) => {
const index = isVirtual ? $(slideEl).attr('data-swiper-slide-index') : $(slideEl).index();
loadInSlide(index);
});
} else if (slidesPerView > 1) {
for (let i = activeIndex; i < activeIndex + slidesPerView; i += 1) {
if (slideExist(i)) loadInSlide(i);
}
} else {
loadInSlide(activeIndex);
}
if (params.loadPrevNext) {
if (slidesPerView > 1 || (params.loadPrevNextAmount && params.loadPrevNextAmount > 1)) {
const amount = params.loadPrevNextAmount;
const spv = Math.ceil(slidesPerView);
const maxIndex = Math.min(activeIndex + spv + Math.max(amount, spv), slides.length);
const minIndex = Math.max(activeIndex - Math.max(spv, amount), 0);
// Next Slides
for (let i = activeIndex + spv; i < maxIndex; i += 1) {
if (slideExist(i)) loadInSlide(i);
}
// Prev Slides
for (let i = minIndex; i < activeIndex; i += 1) {
if (slideExist(i)) loadInSlide(i);
}
} else {
const nextSlide = $wrapperEl.children(`.${swiperParams.slideNextClass}`);
if (nextSlide.length > 0) loadInSlide(slideIndex(nextSlide));

const prevSlide = $wrapperEl.children(`.${swiperParams.slidePrevClass}`);
if (prevSlide.length > 0) loadInSlide(slideIndex(prevSlide));
}
}
}
function checkInViewOnLoad() {
const window = getWindow();
if (!swiper || swiper.destroyed) return;
const $scrollElement = swiper.params.lazy.scrollingElement
? $(swiper.params.lazy.scrollingElement)
: $(window);
const isWindow = $scrollElement[0] === window;
const scrollElementWidth = isWindow ? window.innerWidth : $scrollElement[0].offsetWidth;
const scrollElementHeight = isWindow ? window.innerHeight : $scrollElement[0].offsetHeight;
const swiperOffset = swiper.$el.offset();
const { rtlTranslate: rtl } = swiper;

let inView = false;

if (rtl) swiperOffset.left -= swiper.$el[0].scrollLeft;
const swiperCoord = [
[swiperOffset.left, swiperOffset.top],
[swiperOffset.left + swiper.width, swiperOffset.top],
[swiperOffset.left, swiperOffset.top + swiper.height],
[swiperOffset.left + swiper.width, swiperOffset.top + swiper.height],
];
for (let i = 0; i < swiperCoord.length; i += 1) {
const point = swiperCoord[i];
if (
point[0] >= 0 &&
point[0] <= scrollElementWidth &&
point[1] >= 0 &&
point[1] <= scrollElementHeight
) {
if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line
inView = true;
}
}

const passiveListener =
swiper.touchEvents.start === 'touchstart' &&
swiper.support.passiveListener &&
swiper.params.passiveListeners
? { passive: true, capture: false }
: false;

if (inView) {
load();
$scrollElement.off('scroll', checkInViewOnLoad, passiveListener);
} else if (!scrollHandlerAttached) {
scrollHandlerAttached = true;
$scrollElement.on('scroll', checkInViewOnLoad, passiveListener);
}
}
const onLoad = (e) => {
const slideEl = e.target.closest(slideSelector());
if (!slideEl) return;
$(slideEl).find(`.${swiper.params.lazy.preloaderClass}`).remove();
};

on('beforeInit', () => {
if (swiper.params.lazy.enabled && swiper.params.preloadImages) {
swiper.params.preloadImages = false;
}
});
on('init', () => {
if (swiper.params.lazy.enabled) {
if (swiper.params.lazy.checkInView) {
checkInViewOnLoad();
} else {
load();
}
}
});
on('scroll', () => {
if (
swiper.params.freeMode &&
swiper.params.freeMode.enabled &&
!swiper.params.freeMode.sticky
) {
load();
}
});
on('scrollbarDragMove resize _freeModeNoMomentumRelease', () => {
if (swiper.params.lazy.enabled) {
if (swiper.params.lazy.checkInView) {
checkInViewOnLoad();
} else {
load();
}
}
});
on('transitionStart', () => {
if (swiper.params.lazy.enabled) {
if (
swiper.params.lazy.loadOnTransitionStart ||
(!swiper.params.lazy.loadOnTransitionStart && !initialImageLoaded)
) {
if (swiper.params.lazy.checkInView) {
checkInViewOnLoad();
} else {
load();
}
}
}
});
on('transitionEnd', () => {
if (swiper.params.lazy.enabled && !swiper.params.lazy.loadOnTransitionStart) {
if (swiper.params.lazy.checkInView) {
checkInViewOnLoad();
} else {
load();
}
}
});
on('slideChange', () => {
const { lazy, cssMode, watchSlidesProgress, touchReleaseOnEdges, resistanceRatio } =
swiper.params;
if (
lazy.enabled &&
(cssMode || (watchSlidesProgress && (touchReleaseOnEdges || resistanceRatio === 0)))
) {
load();
if (swiper.el && swiper.$el) {
swiper.$el.on('load', onLoad, { capture: true });
}
});

on('destroy', () => {
if (!swiper.$el) return;
swiper.$el
.find(`.${swiper.params.lazy.loadingClass}`)
.removeClass(swiper.params.lazy.loadingClass);
});

Object.assign(swiper.lazy, {
load,
loadInSlide,
if (!swiper.$el || !swiper.el) return;
swiper.$el.off('load', onLoad, { capture: true });
});
}
3 changes: 0 additions & 3 deletions src/modules/virtual/virtual.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ export default function Virtual({ swiper, extendParams, on, emit }) {
swiper.updateSlides();
swiper.updateProgress();
swiper.updateSlidesClasses();
if (swiper.lazy && swiper.params.lazy.enabled) {
swiper.lazy.load();
}
emit('virtualUpdate');
}

Expand Down
Loading

0 comments on commit d46d5d0

Please sign in to comment.