debian-mirror-gitlab/app/assets/javascripts/lazy_loader.js

96 lines
2.9 KiB
JavaScript
Raw Normal View History

2017-09-10 17:25:29 +05:30
import _ from 'underscore';
2018-11-18 11:00:15 +05:30
export const placeholderImage =
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
2017-09-10 17:25:29 +05:30
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() {
2018-11-18 11:00:15 +05:30
const that = this;
requestIdleCallback(
() => {
that.lazyImages = [].slice.call(document.querySelectorAll('.lazy'));
2018-03-17 18:26:18 +05:30
2018-11-18 11:00:15 +05:30
if (that.lazyImages.length) {
that.checkElementsInView();
}
},
{ timeout: 500 },
);
2017-09-10 17:25:29 +05:30
}
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-11-08 19:23:39 +05:30
const scrollTop = window.pageYOffset;
const visHeight = scrollTop + window.innerHeight + SCROLL_THRESHOLD;
2017-09-10 17:25:29 +05:30
// Loading Images which are in the current viewport or close to them
2018-11-18 11:00:15 +05:30
this.lazyImages = this.lazyImages.filter(selectedImage => {
2017-09-10 17:25:29 +05:30
if (selectedImage.getAttribute('data-src')) {
2018-03-17 18:26:18 +05:30
const imgBoundRect = selectedImage.getBoundingClientRect();
const imgTop = scrollTop + imgBoundRect.top;
const imgBound = imgTop + imgBoundRect.height;
2017-09-10 17:25:29 +05:30
if (scrollTop < imgBound && visHeight > imgTop) {
2018-11-18 11:00:15 +05:30
requestAnimationFrame(() => {
LazyLoader.loadImage(selectedImage);
});
2017-09-10 17:25:29 +05:30
return false;
}
return true;
}
return false;
});
}
static loadImage(img) {
if (img.getAttribute('data-src')) {
2018-11-18 11:00:15 +05:30
let imgUrl = img.getAttribute('data-src');
// Only adding width + height for avatars for now
if (imgUrl.indexOf('/avatar/') > -1 && imgUrl.indexOf('?') === -1) {
let targetWidth = null;
if (img.getAttribute('width')) {
targetWidth = img.getAttribute('width');
} else {
targetWidth = img.width;
}
if (targetWidth) imgUrl += `?width=${targetWidth}`;
}
img.setAttribute('src', imgUrl);
2017-09-10 17:25:29 +05:30
img.removeAttribute('data-src');
img.classList.remove('lazy');
img.classList.add('js-lazy-loaded');
}
}
}