JQuery/JavaScript для замены сломанных изображений
У меня есть веб-страница, которая содержит кучу изображений. Иногда изображение недоступно, поэтому в браузере клиента отображается разбитое изображение.
Как я могу использовать jQuery для получения набора изображений, отфильтровать его на разбитые изображения, а затем заменить src?
- Я думал, что было бы проще сделать это с помощью jQuery, но оказалось, что гораздо проще просто использовать чистое решение JavaScript, то есть то, что предоставляется Prestaul.
Ответы
Ответ 1
Обработайте событие onError
, чтобы изображение переназначало исходный код с помощью JavaScript:
function imgError(image) {
image.onerror = "";
image.src = "/images/noimage.gif";
return true;
}
<img src="image.png" onerror="imgError(this);"/>
Или без функции JavaScript:
<img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" />
В следующей таблице совместимости перечислены браузеры, поддерживающие функцию ошибки:
http://www.quirksmode.org/dom/events/error.html
Ответ 2
Я использую встроенный обработчик error
:
$("img").error(function () {
$(this).unbind("error").attr("src", "broken.gif");
});
Редактировать: метод error()
устарел в jquery 1.8 и выше. Вместо этого вы должны использовать .on("error")
:
$("img").on("error", function () {
$(this).attr("src", "broken.gif");
});
Ответ 3
В случае, если кто-то вроде меня, пытается привязать событие error
к динамическому тегу HTML img
, я хотел бы указать, что есть catch:
По-видимому, img
события ошибок не пузырь в большинстве браузеров, вопреки тому, что стандарт.
Итак, что-то вроде следующего будет не работать:
$(document).on('error', 'img', function () { ... })
Надеюсь, это будет полезно кому-то другому. Хотелось бы, чтобы я видел это здесь в этой теме. Но я этого не сделал. Итак, я добавляю его
Ответ 4
Вот отдельное решение:
$(window).load(function() {
$('img').each(function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
// image was broken, replace with your new image
this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
}
});
});
Ответ 5
Я считаю, что это то, что вам нужно: jQuery.Preload
Вот пример кода из демонстрации, вы указываете загрузочные и не найденные изображения, и все вы настроены:
$('#images img').preload({
placeholder:'placeholder.jpg',
notFound:'notfound.jpg'
});
Ответ 6
$(window).bind('load', function() {
$('img').each(function() {
if((typeof this.naturalWidth != "undefined" &&
this.naturalWidth == 0 )
|| this.readyState == 'uninitialized' ) {
$(this).attr('src', 'missing.jpg');
}
}); })
Источник: http://www.developria.com/2009/03/jquery-quickie---broken-images.html
Ответ 7
Вот быстрый и грязный способ заменить все испорченные изображения, и нет необходимости менять HTML-код;)
пример кода
$("img").each(function(){
var img = $(this);
var image = new Image();
image.src = $(img).attr("src");
var no_image = "https://dummyimage.com/100x100/7080b5/000000&text=No+image";
if (image.naturalWidth == 0 || image.readyState == 'uninitialized'){
$(img).unbind("error").attr("src", no_image).css({
height: $(img).css("height"),
width: $(img).css("width"),
});
}
});
Ответ 8
В то время как OP надеялся заменить SRC, я уверен, что многие люди, сталкивающиеся с этим вопросом, могут только скрыть сбитое изображение, и в этом случае это простое решение отлично поработал у меня:
<img src="someimage.jpg" onerror="this.style.display='none';" />
Ответ 9
Я не смог найти script в соответствии с моими потребностями, поэтому я сделал рекурсивную функцию для проверки неработающих изображений и попыток перезагрузить их каждые четыре секунды, пока они не будут исправлены.
Я ограничил его до 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()); //slightly change url to prevent loading from cache
loaded =0;
}
});
retries +=1;
if (retries < 10) { // If after 10 retries error images are not fixed maybe because they
// are not present on server, the recursion will break the loop
if (loaded == 0) {
setTimeout('$.imgReload()',4000); // I think 4 seconds is enough to load a small image (<50k) from a slow server
}
// All images have been loaded
else {
// alert("images loaded");
}
}
// If error images cannot be loaded after 10 retries
else {
// alert("recursion exceeded");
}
}
jQuery(document).ready(function() {
setTimeout('$.imgReload()',5000);
});
Ответ 10
Это дерьмовая техника, но она в значительной степени гарантирована:
<img ... onerror="this.parentNode.removeChild(this);">
Ответ 11
Это JavaScript, должен быть совместим с браузером, и обеспечивает без уродливой разметки onerror=""
:
var sPathToDefaultImg = 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
validateImage = function( domImg ) {
oImg = new Image();
oImg.onerror = function() {
domImg.src = sPathToDefaultImg;
};
oImg.src = domImg.src;
},
aImg = document.getElementsByTagName( 'IMG' ),
i = aImg.length;
while ( i-- ) {
validateImage( aImg[i] );
}
CODEPEN:
Ответ 12
Вы можете использовать собственную выборку GitHub для этого:
Внешний вид: https://github.com/github/fetch
или для Backend, Node.js версия: https://github.com/bitinn/node-fetch
fetch(url)
.then(function(res) {
if (res.status == '200') {
return image;
} else {
return placeholder;
}
}
Изменить: этот метод заменит XHR и предположительно уже был в Chrome. Для тех, кто читает это в будущем, вам может не понадобиться упомянутая выше библиотека.
Ответ 13
Лучший вызов с использованием
jQuery(window).load(function(){
$.imgReload();
});
Поскольку использование document.ready
не требует, чтобы изображения загружались, только HTML. Таким образом, нет необходимости в отсроченном вызове.
Ответ 14
CoffeeScript вариант:
Я решил исправить проблему с Turbolinks, которая заставляет метод .error() подниматься в Firefox иногда даже несмотря на то, что изображение действительно там.
$("img").error ->
e = $(@).get 0
$(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)
Ответ 15
Используя ответ Prestaul, я добавил несколько проверок, и я предпочитаю использовать способ jQuery.
<img src="image1.png" onerror="imgError(this,1);"/>
<img src="image2.png" onerror="imgError(this,2);"/>
function imgError(image, type) {
if (typeof jQuery !== 'undefined') {
var imgWidth=$(image).attr("width");
var imgHeight=$(image).attr("height");
// Type 1 puts a placeholder image
// Type 2 hides img tag
if (type == 1) {
if (typeof imgWidth !== 'undefined' && typeof imgHeight !== 'undefined') {
$(image).attr("src", "http://lorempixel.com/" + imgWidth + "/" + imgHeight + "/");
} else {
$(image).attr("src", "http://lorempixel.com/200/200/");
}
} else if (type == 2) {
$(image).hide();
}
}
return true;
}
Ответ 16
Если вы вставили img
с помощью innerHTML
, например: $("div").innerHTML = <img src="wrong-uri">
, вы можете загрузить другое изображение, если оно не выполняется, например:
<script>
function imgError(img) {
img.error="";
img.src="valid-uri";
}
</script>
<img src="wrong-uri" onerror="javascript:imgError(this)">
Почему требуется javascript: _
? Поскольку скрипты, введенные в DOM через теги script в innerHTML
, не запускаются во время их ввода, поэтому вы должны быть явным.
Ответ 17
Я нашел этот пост, смотря на эту другую публикацию SO. Ниже приведена копия ответа, который я дал там.
Я знаю, что это старый поток, но React стал популярным, и, возможно, кто-то, кто использует React, придет сюда искать ответ на ту же проблему.
Итак, если вы используете React, вы можете сделать что-то вроде ниже, что было ответом, предоставленным Бен Алпертом команды React здесь
getInitialState: function(event) {
return {image: "http://example.com/primary_image.jpg"};
},
handleError: function(event) {
this.setState({image: "http://example.com/failover_image.jpg"});
},
render: function() {
return (
<img onError={this.handleError} src={src} />;
);
}
Ответ 18
Я создал fiddle, чтобы заменить сломанное изображение с помощью события "onerror".
Это может вам помочь.
//the placeholder image url
var defaultUrl = "url('https://sadasd/image02.png')";
$('div').each(function(index, item) {
var currentUrl = $(item).css("background-image").replace(/^url\(['"](.+)['"]\)/, '$1');
$('<img>', {
src: currentUrl
}).on("error", function(e) {
$this = $(this);
$this.css({
"background-image": defaultUrl
})
e.target.remove()
}.bind(this))
})
Ответ 19
Вот пример использования объекта HTML5 Image, обернутого JQuery. Вызовите функцию загрузки для URL первичного изображения, и если эта загрузка вызывает ошибку, замените атрибут src изображения URL-адресом резервной копии.
function loadImageUseBackupUrlOnError(imgId, primaryUrl, backupUrl) {
var $img = $('#' + imgId);
$(new Image()).load().error(function() {
$img.attr('src', backupUrl);
}).attr('src', primaryUrl)
}
<img id="myImage" src="primary-image-url"/>
<script>
loadImageUseBackupUrlOnError('myImage','primary-image-url','backup-image-url');
</script>
Ответ 20
Чистый JS.
Моя задача состояла в том, что если образ "bl-once.png" пуст → вставьте первый из них (который не имеет статуса 404) из списка массивов (в текущем каталоге):
<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">
Ответ 21
Я не уверен, есть ли лучший способ, но я могу подумать о взломе, чтобы получить его - вы могли бы отправить Ajax на URL-адрес img и проанализировать ответ, чтобы увидеть, действительно ли изображение вернулось. Если он вернется как 404 или что-то еще, замените img. Хотя я ожидаю, что это будет довольно медленно.
Ответ 22
Я решил проблему с этими двумя простыми функциями:
function imgExists(imgPath) {
var http = jQuery.ajax({
type:"HEAD",
url: imgPath,
async: false
});
return http.status != 404;
}
function handleImageError() {
var imgPath;
$('img').each(function() {
imgPath = $(this).attr('src');
if (!imgExists(imgPath)) {
$(this).attr('src', 'images/noimage.jpg');
}
});
}
Ответ 23
jQuery 1.8
// If missing.png is missing, it is replaced by replacement.png
$( "img" )
.error(function() {
$( this ).attr( "src", "replacement.png" );
})
.attr( "src", "missing.png" );
jQuery 3
// If missing.png is missing, it is replaced by replacement.png
$( "img" )
.on("error", function() {
$( this ).attr( "src", "replacement.png" );
})
.attr( "src", "missing.png" );
ссылка
Ответ 24
;(window.jQuery || window.Zepto).fn.fallback = function (fallback) {
return this.one('error', function () {
var self = this;
this.src = (fallback || 'http://lorempixel.com/$width/$height')
.replace(/\$(\w+)/g, function (m, t) { return self[t] || ''; });
});
};
Вы можете передать путь к заполнителю и получить в нем все свойства из объекта неудавшегося изображения через $*
:
$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');
http://jsfiddle.net/ARTsinn/Cu4Zn/
Ответ 25
Это меня расстраивало годами. Мое исправление CSS устанавливает фоновое изображение на img
. Когда динамическое изображение src
не загружается на передний план, на img
bg видна заполнитель. Это работает, если ваши изображения имеют размер по умолчанию (например, height
, min-height
, width
и/или min-width
).
Вы увидите значок сломанного изображения, но это улучшение. Протестировано до IE9 успешно. iOS Safari и Chrome даже не показывают сломанную иконку.
.dynamicContainer img {
background: url('/images/placeholder.png');
background-size: contain;
}
Добавьте немного анимации, чтобы дать время src
для загрузки без фонового мерцания. Chrome постепенно исчезает в фоновом режиме, но на рабочем столе Safari нет.
.dynamicContainer img {
background: url('/images/placeholder.png');
background-size: contain;
-webkit-animation: fadein 1s;
animation: fadein 1s;
}
@-webkit-keyframes fadein {
0% { opacity: 0.0; }
50% { opacity: 0.5; }
100% { opacity: 1.0; }
}
@keyframes fadein {
0% { opacity: 0.0; }
50% { opacity: 0.5; }
100% { opacity: 1.0; }
}
Ответ 26
Если изображение не может быть загружено (например, поскольку оно отсутствует в указанном URL-адресе), URL-адрес изображения будет изменен по умолчанию,
Подробнее о .error()
$('img'). on ('error', function (e) {
$(this).attr('src', 'broken.png');
});Код>
Ответ 27
Я думаю, что у меня более элегантный способ делегирования событий и захвата событий на window
error
, даже если резервное изображение не загружается.
img {
width: 100px;
height: 100px;
}
<script>
window.addEventListener('error', windowErrorCb, {
capture: true
}, true)
function windowErrorCb(event) {
let target = event.target
let isImg = target.tagName.toLowerCase() === 'img'
if (isImg) {
imgErrorCb()
return
}
function imgErrorCb() {
let isImgErrorHandled = target.hasAttribute('data-src-error')
if (!isImgErrorHandled) {
target.setAttribute('data-src-error', 'handled')
target.src = 'backup.png'
} else {
//anything you want to do
console.log(target.alt, 'both origin and backup image fail to load!');
}
}
}
</script>
<img id="img" src="error1.png" alt="error1">
<img id="img" src="error2.png" alt="error2">
<img id="img" src="https://i.stack.imgur.com/ZXCE2.jpg" alt="avatar">
Ответ 28
У меня такая же проблема. Этот код хорошо работает в моем случае.
// Replace broken images by a default img
$('img').each(function(){
if($(this).attr('src') === ''){
this.src = '/default_feature_image.png';
}
});
Ответ 29
Иногда использование события error
не представляется возможным, например. потому что вы пытаетесь сделать что-то на уже загруженной странице, например, когда вы запускаете код через консоль, букмарклет или script загружается асинхронно. В этом случае проверка того, что img.naturalWidth
и img.naturalHeight
равна 0, кажется, делает трюк.
Например, здесь приведен фрагмент для перезагрузки всех сломанных изображений с консоли:
$$ ( "img" ). forEach (img = > { if (! img.naturalWidth &! img.naturalHeight) { img.src= img.src; }
}
Код>
Ответ 30
Это решение является простым JavaScript, и оно должно быть совместимым с crossbrowser и поставляет без уродливой разметки onerror=""
:
var sPathToDefaultImg = 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
validateImage = function( domImg ) {
oImg = new Image();
oImg.onerror = function() {
domImg.src = sPathToDefaultImg;
};
oImg.src = domImg.src;
},
aImg = document.getElementsByTagName( 'IMG' ),
i = aImg.length;
while ( i-- ) {
validateImage( aImg[i] );
}
CODEPEN: