Vanilla javascript Lazy-load
Последние записи
Отличное решение lazy-load скрипта предложил автор сайта web3r.ru
Javascript
/**
* Анонимная самовызывающаяся функция-обертка
* @param {document} d - получает документ
*/
!function(d) {
"use strict";
/**
* Полифилл для 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);
};
/**
* Функция загрузки элемента
* @param {Event|Object} e - событие получаемое при click/hover или элемент, если используется "view"
* @param {Function|false} [callback] - функция, выполняемая после загрузки элемента
*/
lazy.get = function(e, callback) {
var item = e.target || e;
var event = e.type || false;
if (event) item.removeEventListener(event, lazy.get); // удаление обработчика события
if (!item.src) { // проверка элемента на наличие атрибута src
console.error("lazy-load не поддерживается для этого элемента (" + item.tagName + ")");
return;
}
if (!item.hasAttribute("data-js-loaded")) {
var src = item.getAttribute("data-js-source");
if (src) { // если атрибут data-js-source присутствует
item.src = src;
item.setAttribute("data-js-loaded", "");
item.removeAttribute("data-js-source");
item.onerror = function() { // обработка ошибок загрузки
console.error("загрузка источника не удалась (элемент: " + item.tagName + ", путь: " + item.src + ")");
};
setTimeout(function() { // удаление обработчика ошибок
item.onerror = null;
}, 3000);
} else console.error("отсутствует оригинальный источник (элемент: " + item.tagName + ", путь: " + item.src + ")");
if (callback) callback(item); // вызов callback, если необходимо
}
};
/**
* Функция инициализации lazy-load
* @param {Object} settings - объект с предварительными настройками
*/
lazy.init = function(settings) {
// настройки по умолчанию
settings = Object.assign({}, {
items: "[data-js-source]",
on: "click",
callback: false,
}, settings);
// поиск всех lazy-элементов
var els = d.querySelectorAll(settings.items);
// обработчики событий
if (settings.on === "view") { // для события с условным наимнованием "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() принимает элемент
});
};
// обработка событий для "view"
window.addEventListener("scroll", onviewLoad);
window.addEventListener("resize", onviewLoad);
if (screen.msOrientation || (screen.orientation || screen.mozOrientation || { type: false }).type) window.addEventListener("orientationchange", onviewLoad);
} else { // обработка событий "hover" и "click"
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() принимает событие
});
}
};
window.lazy = lazy;
}(document);
CSS оформление
/* все загрузившиеся элементы */
[data-js-loaded] { }
/* все не загрузившиеся фреймы */
iframe[data-js-source] { }
/* все не загрузившиеся картинки */
img[data-js-source] { }
/* все загрузившиеся фреймы */
iframe[data-js-loaded] { }
/* все загрузившиеся картинки */
img[data-js-loaded] { }
Использование
// вызов функции
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;
}
}
});
// отключение кеширования оригинальных картинок
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" />
Комментарии