Vanilla javascript Lazy-load
The last notes
All English-language materials have been translated fully automatically using the Google service
An excellent solution to the lazy-load script was suggested by the author of the site web3r.ru
Javascript
/ **
* Anonymous self-calling wrapper function
* @param {document} d - gets the document
* /
!function(d) {
"use strict";
/**
* Polyfill for Object.assign ()
*/
Object.assign||Object.defineProperty(Object,"assign",{enumerable:!1,configurable:!0,writable:!0,value:function(e,r){"use strict";if(null==e)throw new TypeError("Cannot convert first argument to object");for(var t=Object(e),n=1;n= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || d.documentElement.clientHeight);
};
/**
* Element loading function
* @param {Event | Object} e - an event received on click / hover or an element if "view" is used
* @param {Function | false} [callback] - the function to be executed after the element is loaded
*/
lazy.get = function(e, callback) {
var item = e.target || e;
var event = e.type || false;
if (event) item.removeEventListener(event, lazy.get); // remove event handler
if (!item.src) { // check the element for the src attribute
console.error ("lazy-load is not supported for this item (" + item.tagName + ")");
return;
}
if (!item.hasAttribute("data-js-loaded")) {
var src = item.getAttribute("data-js-source");
if (src) { // if the data-js-source attribute is present
item.src = src;
item.setAttribute("data-js-loaded", "");
item.removeAttribute("data-js-source");
item.onerror = function() { // handle loading errors
console.error("loading source failed (item: "+ item.tagName +", path: "+ item.src +")");
};
setTimeout(function() { //remove error handler
item.onerror = null;
}, 3000);
} else console.error("the original source is missing (element: "+ item.tagName +", path: "+ item.src +")");
if (callback) callback(item); // call callback if necessary
}
};
/**
* Lazy-load initialization function
* @param {Object} settings - object with presets
*/
lazy.init = function(settings) {
// default settings
settings = Object.assign({}, {
items: "[data-js-source]",
on: "click",
callback: false,
}, settings);
// find all lazy elements
var els = d.querySelectorAll(settings.items);
// event handlers
if (settings.on === "view") { // for an event with the conditional name "view"
var onviewLoad = function() {
Array.prototype.slice.call(els, 0).forEach(function(el) {
if (lazy.isVisible(el)) lazy.get(el, settings.callback); // проверка на видимость во viewport, lazy.get() takes event
});
};
// handle events for "view"
window.addEventListener("scroll", onviewLoad);
window.addEventListener("resize", onviewLoad);
if (screen.msOrientation || (screen.orientation || screen.mozOrientation || { type: false }).type) window.addEventListener("orientationchange", onviewLoad);
} else { // handle the "hover" and "click" events
var eventName = (settings.on === "hover") ? "mouseover" : settings.on;
Array.prototype.slice.call(els, 0).forEach(function(el) {
el.addEventListener(eventName, function(e) {
lazy.get(e, settings.callback);
}); // lazy.get() takes event
});
}
};
window.lazy = lazy;
}(document);
CSS styling
/ * all loaded items * /
[data-js-loaded] { }
/ * all unloaded frames * /
iframe[data-js-source] { }
/ * all images not loaded * /
img[data-js-source] { }
/ * all loaded frames * /
iframe[data-js-loaded] { }
/ * all uploaded images * /
img[data-js-loaded] { }
Usage
// function call
document.addEventListener("DOMContentLoaded", function() {
// lazy-load
lazy.init({
on: "view", // при попадании во viewport
callback: function(el) { // функция при загрузке
el.classList.add("loading");
el.onload = function() {
el.classList.remove("loading");
el.onload = null;
}
}
});
// disable caching of original images
var images = document.querySelectorAll("[data-source]");
images.forEach(function(el) {
var source = el.getAttribute("data-source");
el.setAttribute("data-source", source + "?" + Math.random());
})
});
html
<img src="placeholder.gif" alt="" data-js-source="path_to_img" />
Comments