Reponsive images are now loaded on demand
Signed-off-by: Jim Martens <github@2martens.de>
This commit is contained in:
135
_assets/js/echo.js
Normal file
135
_assets/js/echo.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*! echo.js v1.7.0 | (c) 2015 @toddmotto | https://github.com/toddmotto/echo */
|
||||||
|
(function (root, factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(function() {
|
||||||
|
return factory(root);
|
||||||
|
});
|
||||||
|
} else if (typeof exports === 'object') {
|
||||||
|
module.exports = factory;
|
||||||
|
} else {
|
||||||
|
root.echo = factory(root);
|
||||||
|
}
|
||||||
|
})(this, function (root) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let echo = {};
|
||||||
|
|
||||||
|
let callback = function () {};
|
||||||
|
|
||||||
|
let offset, poll, delay, useDebounce, unload;
|
||||||
|
|
||||||
|
const isHidden = function (element) {
|
||||||
|
return (element.offsetParent === null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const inView = function (element, view) {
|
||||||
|
if (isHidden(element)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let box = element.getBoundingClientRect();
|
||||||
|
return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b);
|
||||||
|
};
|
||||||
|
|
||||||
|
const debounceOrThrottle = function () {
|
||||||
|
if(!useDebounce && !!poll) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearTimeout(poll);
|
||||||
|
poll = setTimeout(function(){
|
||||||
|
echo.render();
|
||||||
|
poll = null;
|
||||||
|
}, delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
echo.init = function (opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
let offsetAll = opts.offset || 0;
|
||||||
|
let offsetVertical = opts.offsetVertical || offsetAll;
|
||||||
|
let offsetHorizontal = opts.offsetHorizontal || offsetAll;
|
||||||
|
const optionToInt = function (opt, fallback) {
|
||||||
|
return parseInt(opt || fallback, 10);
|
||||||
|
};
|
||||||
|
offset = {
|
||||||
|
t: optionToInt(opts.offsetTop, offsetVertical),
|
||||||
|
b: optionToInt(opts.offsetBottom, offsetVertical),
|
||||||
|
l: optionToInt(opts.offsetLeft, offsetHorizontal),
|
||||||
|
r: optionToInt(opts.offsetRight, offsetHorizontal)
|
||||||
|
};
|
||||||
|
delay = optionToInt(opts.throttle, 250);
|
||||||
|
useDebounce = opts.debounce !== false;
|
||||||
|
unload = !!opts.unload;
|
||||||
|
callback = opts.callback || callback;
|
||||||
|
echo.render();
|
||||||
|
if (document.addEventListener) {
|
||||||
|
root.addEventListener('scroll', debounceOrThrottle, false);
|
||||||
|
root.addEventListener('load', debounceOrThrottle, false);
|
||||||
|
} else {
|
||||||
|
root.attachEvent('onscroll', debounceOrThrottle);
|
||||||
|
root.attachEvent('onload', debounceOrThrottle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
echo.render = function () {
|
||||||
|
let nodes = document.querySelectorAll('img[data-echo], [data-echo-background]');
|
||||||
|
let length = nodes.length;
|
||||||
|
let src, elem;
|
||||||
|
let view = {
|
||||||
|
l: 0 - offset.l,
|
||||||
|
t: 0 - offset.t,
|
||||||
|
b: (root.innerHeight || document.documentElement.clientHeight) + offset.b,
|
||||||
|
r: (root.innerWidth || document.documentElement.clientWidth) + offset.r
|
||||||
|
};
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
elem = nodes[i];
|
||||||
|
if (inView(elem, view)) {
|
||||||
|
|
||||||
|
if (unload) {
|
||||||
|
elem.setAttribute('data-echo-placeholder', elem.src);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem.getAttribute('data-echo-background') !== null) {
|
||||||
|
elem.style.backgroundImage = "url(" + elem.getAttribute('data-echo-background') + ")";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elem.src = elem.getAttribute('data-echo');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!unload) {
|
||||||
|
elem.removeAttribute('data-echo');
|
||||||
|
elem.removeAttribute('data-echo-background');
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(elem, 'load');
|
||||||
|
}
|
||||||
|
else if (unload && !!(src = elem.getAttribute('data-echo-placeholder'))) {
|
||||||
|
|
||||||
|
if (elem.getAttribute('data-echo-background') !== null) {
|
||||||
|
elem.style.backgroundImage = "url(" + src + ")";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elem.src = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
elem.removeAttribute('data-echo-placeholder');
|
||||||
|
callback(elem, 'unload');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
echo.detach();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
echo.detach = function () {
|
||||||
|
if (document.removeEventListener) {
|
||||||
|
root.removeEventListener('scroll', debounceOrThrottle);
|
||||||
|
} else {
|
||||||
|
root.detachEvent('onscroll', debounceOrThrottle);
|
||||||
|
}
|
||||||
|
clearTimeout(poll);
|
||||||
|
};
|
||||||
|
|
||||||
|
return echo;
|
||||||
|
|
||||||
|
});
|
||||||
@ -19,5 +19,13 @@
|
|||||||
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
|
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
{% asset main.js %}
|
{% asset main.js %}
|
||||||
|
{% asset echo.js %}
|
||||||
|
<script defer>
|
||||||
|
echo.init({
|
||||||
|
offset: 500,
|
||||||
|
throttle: 250,
|
||||||
|
unload: false
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% asset fontawesome-all.js defer %}
|
{% asset fontawesome-all.js defer %}
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
<img alt="{{ include.alt }}"
|
<img alt="{{ include.alt }}"
|
||||||
src="{% if site.data.cdn.use %}{{ site.data.cdn.url }}{% else %}{{ site.baseurl }}{% endif %}{{ include.link }}"
|
src=""
|
||||||
|
data-echo="{% if site.data.cdn.use %}{{ site.data.cdn.url }}{% else %}{{ site.baseurl }}{% endif %}{{ include.link }}"
|
||||||
class="img-fluid" />
|
class="img-fluid" />
|
||||||
Reference in New Issue
Block a user