2017-07-24 13:36:52 -04:00
|
|
|
import _ from 'underscore';
|
|
|
|
|
|
|
|
export const placeholderImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
|
|
|
|
const SCROLL_THRESHOLD = 300;
|
|
|
|
|
|
|
|
export default class LazyLoader {
|
|
|
|
constructor(options = {}) {
|
|
|
|
this.lazyImages = [];
|
|
|
|
this.observerNode = options.observerNode || '#content-body';
|
|
|
|
|
|
|
|
const throttledScrollCheck = _.throttle(() => this.scrollCheck(), 300);
|
|
|
|
const debouncedElementsInView = _.debounce(() => this.checkElementsInView(), 300);
|
|
|
|
|
|
|
|
window.addEventListener('scroll', throttledScrollCheck);
|
|
|
|
window.addEventListener('resize', debouncedElementsInView);
|
|
|
|
|
|
|
|
const scrollContainer = options.scrollContainer || window;
|
|
|
|
scrollContainer.addEventListener('load', () => this.loadCheck());
|
|
|
|
}
|
|
|
|
searchLazyImages() {
|
|
|
|
this.lazyImages = [].slice.call(document.querySelectorAll('.lazy'));
|
2017-10-31 13:18:09 -04:00
|
|
|
|
|
|
|
if (this.lazyImages.length) {
|
|
|
|
this.checkElementsInView();
|
|
|
|
}
|
2017-07-24 13:36:52 -04:00
|
|
|
}
|
|
|
|
startContentObserver() {
|
|
|
|
const contentNode = document.querySelector(this.observerNode) || document.querySelector('body');
|
|
|
|
|
|
|
|
if (contentNode) {
|
|
|
|
const observer = new MutationObserver(() => this.searchLazyImages());
|
|
|
|
|
|
|
|
observer.observe(contentNode, {
|
|
|
|
childList: true,
|
|
|
|
subtree: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loadCheck() {
|
|
|
|
this.searchLazyImages();
|
|
|
|
this.startContentObserver();
|
|
|
|
}
|
|
|
|
scrollCheck() {
|
|
|
|
requestAnimationFrame(() => this.checkElementsInView());
|
|
|
|
}
|
|
|
|
checkElementsInView() {
|
2018-06-15 11:58:27 -04:00
|
|
|
const scrollTop = window.pageYOffset;
|
|
|
|
const visHeight = scrollTop + window.innerHeight + SCROLL_THRESHOLD;
|
2017-07-24 13:36:52 -04:00
|
|
|
|
|
|
|
// Loading Images which are in the current viewport or close to them
|
|
|
|
this.lazyImages = this.lazyImages.filter((selectedImage) => {
|
|
|
|
if (selectedImage.getAttribute('data-src')) {
|
2017-10-31 13:18:09 -04:00
|
|
|
const imgBoundRect = selectedImage.getBoundingClientRect();
|
|
|
|
const imgTop = scrollTop + imgBoundRect.top;
|
|
|
|
const imgBound = imgTop + imgBoundRect.height;
|
2017-07-24 13:36:52 -04:00
|
|
|
|
|
|
|
if (scrollTop < imgBound && visHeight > imgTop) {
|
|
|
|
LazyLoader.loadImage(selectedImage);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
static loadImage(img) {
|
|
|
|
if (img.getAttribute('data-src')) {
|
|
|
|
img.setAttribute('src', img.getAttribute('data-src'));
|
|
|
|
img.removeAttribute('data-src');
|
|
|
|
img.classList.remove('lazy');
|
|
|
|
img.classList.add('js-lazy-loaded');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|