jQuery/JavaScript: Замена битых изображений
У меня есть веб-страница, на которой размещено множество изображений. Иногда изображение недоступно, и в браузере клиента отображается значок сломанного изображения.
Как использовать jQuery, чтобы получить набор изображений, отфильтровать его по сломанным изображениям и затем заменить атрибут src?
Я думал, что сделать это с помощью jQuery будет проще, но на самом деле решать эту задачу оказалось гораздо легче с помощью чистого JavaScript, то есть решения, предоставленного Prestaul.
5 ответ(ов)
Вот самостоятельное решение вашей проблемы:
$(window).load(function() {
$('img').each(function() {
if ( !this.complete
|| typeof this.naturalWidth == "undefined"
|| this.naturalWidth == 0 ) {
// изображение повреждено, замените его на ваше новое изображение
this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
}
});
});
В этом коде мы используем событие load
для окна, чтобы убедиться, что все изображения загружены. Затем, перебираем каждое изображение на странице с помощью $('img').each()
. Для каждого изображения проверяем, завершена ли загрузка, определено ли его натуральное ширина и не равно ли оно нулю. Если одно из условий истинно, мы заменяем его на изображение, указывая новый URL.
Этот код использует jQuery для проверки наличия изображений на странице. Когда окно полностью загружено (load
), он проходит по каждому элементу <img>
и проверяет, корректно ли загружены изображения. Если ширина изображения (naturalWidth
) равна 0 или состояние загрузки (readyState
) равно 'uninitialized', то устанавливается атрибут src
на 'missing.jpg', что позволяет заменить отсутствующие изображения на заданное изображение-заглушку.
Вот краткое объяснение каждой части кода:
$(window).bind('load', function() {...});
- эта функция выполняется, когда все элементы окна (включая изображения и другие ресурсы) загружены.$('img').each(function() {...});
- перебираем каждый элемент<img>
на странице.if ((typeof this.naturalWidth != "undefined" && this.naturalWidth == 0) || this.readyState == 'uninitialized') {...}
- проверяем, если:naturalWidth
не определён (то есть браузер не поддерживает эту функцию) и равен 0 (значит изображение не загружено),- или состояние загрузки изображения не инициализировано.
$(this).attr('src', 'missing.jpg');
- если условие выполняется, заменяем источник изображения на 'missing.jpg'.
Таким образом, данный код позволяет избежать отображения сломанных изображений на веб-странице.
Источник: приведённая ссылка.
Похоже, что у вас возникла необходимость проверить изображения на наличие ошибок и попытаться их перезагрузить. Вот пример рекурсивной функции, которую я разработал на основе ваших требований. Она проверяет изображения на наличие ошибок и пытается перезагрузить их каждые четыре секунды до тех пор, пока не будет достигнуто максимальное количество попыток в 10.
Я ограничил количество попыток до 10, так как если изображение не загрузилось за это время, возможно, оно отсутствует на сервере, и функция могла бы зациклиться. Пока что я продолжаю тестировать её, так что не стесняйтесь вносить изменения 😃
var retries = 0;
$.imgReload = function() {
var loaded = 1;
$("img").each(function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
var src = $(this).attr("src");
var date = new Date();
$(this).attr("src", src + "?v=" + date.getTime()); // небольшое изменение URL, чтобы избежать загрузки из кэша
loaded = 0;
}
});
retries += 1;
if (retries < 10) { // Если после 10 попыток изображения так и не загрузились, возможно, их нет на сервере,
// что завершит рекурсию
if (loaded == 0) {
setTimeout('$.imgReload()', 4000); // Я думаю, что 4 секунды — это достаточно для загрузки небольшого изображения (<50k) с медленного сервера
}
// Все изображения загрузились
else {
// alert("изображения загружены");
}
}
// Если изображения не загрузились после 10 попыток
else {
// alert("превышено количество попыток");
}
}
jQuery(document).ready(function() {
setTimeout('$.imgReload()', 5000);
});
Не забудьте протестировать скрипт в вашем проекте!
Вы можете использовать встроенную функцию fetch от GitHub для этого:
Для фронтенда: https://github.com/github/fetch
или для бэкенда, версия для Node.js: https://github.com/bitinn/node-fetch
fetch(url)
.then(function(res) {
if (res.status == '200') {
return image;
} else {
return placeholder;
}
});
Правка: Этот метод заменяет XHR и, как предполагается, уже был внедрен в Chrome. Для всех, кто читает это в будущем, возможно, вам не потребуется упоминать вышеуказанную библиотеку.
Вы правы, что использование $(document).ready()
не гарантирует, что все изображения загружены, так как этот обработчик срабатывает, как только DOM полностью загружен, но не дожидается загрузки всех медиафайлов. Поэтому предпочтительно использовать $(window).load()
, что позволяет выполнить ваш код только после полной загрузки всех ресурсов страницы, включая изображения.
Вот как это можно сделать:
jQuery(window).load(function(){
$.imgReload();
});
Таким образом, в этом случае действительно нет необходимости в задержке, так как вы уверены, что все изображения будут загружены перед выполнением вашего кода.
Как узнать, какая радиокнопка выбрана с помощью jQuery?
Как проверить, отмечен ли чекбокс в jQuery?
Эквивалент jQuery $.ready() на чистом JavaScript - как вызвать функцию, когда страница/DOM готовы (дубликат)
Потеряно HTML-кодирование при чтении атрибута из поля ввода
Высота, равная динамической ширине (флюидная верстка на CSS)