jQuery / JavaScript для замены сломанных изображений
У меня есть веб-страницу, которая включает в себя кучу образов. Иногда изображение недоступно, поэтому в браузере клиента отображается сломанное изображение.
Как использовать jQuery для получения набора изображений, фильтровать его на сломанные изображения, а затем заменить src?
--Я думал, что будет проще сделать это с помощью jQuery, но оказалось намного проще просто использовать чистое решение JavaScript, то есть то, которое предоставлено Prestaul.
30 ответов
обработки 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';" />
в следующей таблице совместимости перечислены браузеры, которые поддерживают средство ошибки:
программа error обработчик:
$("img").error(function () {
  $(this).unbind("error").attr("src", "broken.gif");
});
error() осуждается в 1.8 или выше.
в случае, если кто-то, как я, пытается прикрепить error событие для динамического HTML img тег, я хотел бы отметить, что есть одна загвоздка: 
видимо img событий ошибки не пузырь в большинстве браузеров, вопреки тому, что стандартный говорит.
так, что-то вроде следующего будет не работает:
$(document).on('error', 'img', function () { ... })
надеюсь это будет полезно кому-то еще. Жаль, что я не видел этого здесь, в эта тема. Но я этого не сделал. Итак, я добавляю его
вот вам самостоятельное решение:
$(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';
    }
  });
});
Я считаю, что это то, что вы после: С помощью jQuery.Поджатие
вот пример кода из демо, вы указываете загрузку и не нашли изображения, и все готово:
$('#images img').preload({
    placeholder:'placeholder.jpg',
    notFound:'notfound.jpg'
});
$(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
это дерьмовый метод, но это в значительной степени гарантировано:
<img ...  onerror="this.parentNode.removeChild(this);">
в то время как OP искал замену SRC, я уверен, что многие люди, задающие этот вопрос, могут только хотеть скрыть сломанное изображение, и в этом случае Это простое решение отлично сработало для меня:
<img src="someimage.jpg" onerror="this.style.display='none';" />
вот быстрый и грязный способ, чтобы заменить все сломанные изображения, и нет необходимости менять 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"),
            });
        }
  });
Я не смог найти сценарий, соответствующий моим потребностям, поэтому я сделал рекурсивную функцию, чтобы проверить сломанные изображения и попытаться перезагрузить их каждые четыре секунды, пока они не будут исправлены.
Я ограничил его 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);
});
вы можете использовать собственную выборку GitHub для этого:
интерфейс:https://github.com/github/fetch
или для бэкэнда, узла.версия js:https://github.com/bitinn/node-fetch
fetch(url)
  .then(function(res) {
    if (res.status == '200') {
      return image;
    } else {
      return placeholder;
    }
  }
Edit: этот метод собирается заменить XHR и, предположительно, уже был в Chrome. Для тех, кто читает это в будущем, вам может не понадобиться вышеупомянутая библиотека.
это 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] );
}
лучше позвонить с помощью
jQuery(window).load(function(){
    $.imgReload();
});
потому что с помощью document.ready Не обязательно означает, что изображения загружаются, только HTML. Таким образом, нет необходимости в отложенном звонке.
CoffeeScript вариант:
Я сделал это, чтобы исправить проблему с Turbolinks, которая вызывает .метод error (), чтобы подняться в Firefox иногда, даже если изображение действительно есть.
$("img").error ->
  e = $(@).get 0
  $(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)
С помощью 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;
}
если вы вставили свой img С innerHTML, например: $("div").innerHTML = <img src="wrong-uri">, вы можете загрузить другое изображение, если это не удается сделать, e.g, это:
<script>
    function imgError(img) {
        img.error="";
        img.src="valid-uri";
    }
</script>
<img src="wrong-uri" onerror="javascript:imgError(this)">
почему javascript: _нужен? Потому что скрипты, введенные в DOM через теги скриптов в innerHTML не запускаются в то время, когда они вводятся, поэтому вы должны быть явными.
Я нашел этот пост, глядя на этот другой так пост. Ниже приводится копия ответа, который я там дал.
Я знаю, что это старый поток, но 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} />;
    );
}
Я создал скрипка для замены сломанного изображения с помощью события" 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\(['"](.+)['"]\)/, '');
      $('<img>', {
        src: currentUrl
      }).on("error", function(e) {
        $this = $(this);
        $this.css({
          "background-image": defaultUrl
        })
        e.target.remove()
      }.bind(this))
    })
вот пример использования объекта изображения HTML5, обернутого JQuery. Вызовите функцию load для основного 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>
чистый JS. Моя задача была: если изображение ' BL-один раз.png " пуст - > вставить первое (не имеющее статуса 404) изображение из списка массивов (в текущем каталоге):
<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">возможно, его нужно улучшить, но:
var srcToInsertArr = ['empty1.png', 'empty2.png', 'needed.png', 'notActual.png']; // try to insert one by one img from this array
    var path;
    var imgNotFounded = true; // to mark when success
    var replaceEmptyImage = {
        insertImg: function (elem) {
            if (srcToInsertArr.length == 0) { // if there are no more src to try return
                return "no-image.png";
            }
            if(!/undefined/.test(elem.src)) { // remember path
                path = elem.src.split("/").slice(0, -1).join("/"); // "http://localhost:63342/GetImage"
            }
            var url = path + "/" + srcToInsertArr[0];
            srcToInsertArr.splice(0, 1); // tried 1 src
            
                if(imgNotFounded){ // while not success
                    replaceEmptyImage.getImg(url, path, elem); // CALL GET IMAGE
                }
            
        },
        getImg: function (src, path, elem) { // GET IMAGE
            if (src && path && elem) { // src = "http://localhost:63342/GetImage/needed.png"
                
                var pathArr = src.split("/"); // ["http:", "", "localhost:63342", "GetImage", "needed.png"]
                var name = pathArr[pathArr.length - 1]; // "needed.png"
                xhr = new XMLHttpRequest();
                xhr.open('GET', src, true);
                xhr.send();
                xhr.onreadystatechange = function () {
                    if (xhr.status == 200) {
                        elem.src = src; // insert correct src
                        imgNotFounded = false; // mark success
                    }
                    else {
                        console.log(name + " doesn't exist!");
                        elem.onerror();
                    }
                }
            }
        }
    };Так, это вставить правильно необходимо.png "для моего src или" no-image.ПНГ с текущего каталога.
Я не уверен, что есть лучший способ, но я могу придумать хак, чтобы получить его - вы могли бы AJAX опубликовать URL-адрес img и проанализировать ответ, чтобы увидеть, действительно ли изображение вернулось. Если он вернулся как 404 или что-то еще, то замените img. Хотя я ожидаю, что это будет довольно медленно.
Я решил свою проблему с помощью этих двух простых функций:
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');
        }
    });
}
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" );
;(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');
это расстраивало меня в течение многих лет.  Мое исправление CSS устанавливает фоновое изображение на img. Когда динамическое изображение src не загружается на передний план, заполнитель виден на img ' s bg.  Это работает, если ваши изображения имеют размер по умолчанию (например,height, min-height, width и/или min-width).
вы увидите значок сломанного изображения, но это улучшение. Протестировано до IE9 успешно. iOS Safari и Chrome даже не показывают сломанный икона.
.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
}
добавить немного анимации, чтобы дать src время загрузки без фонового мерцания.  Chrome плавно исчезает в фоновом режиме, но desktop 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; }
}
Если изображение не может быть загружено (например, потому что его нет в предоставленном URL-адресе), URL-адрес изображения будет изменен на default,
подробнее о .error ()
$('img').on('error', function (e) {
  $(this).attr('src', 'broken.png');
});Я думаю, что у меня есть более элегантный способ с делегированием событий и захватом событий на window ' s 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">суть :
- вставить код в тег - headи выполняется как первый встроенный скрипт. Таким образом, он будет слушать ошибки, возникающие после сценария.
- используйте захват событий, чтобы поймать ошибки, особенно для тех событий, которые не кипятись. 
- используйте делегирование событий, которое позволяет избежать привязки событий к каждому изображению. 
- дает ошибку - imgэлемент атрибут после предоставления им- backup.pngчтобы избежать исчезновения- backup.pngи последующий бесконечный цикл, как показано ниже:
ошибка img - >резервное копирование.png - >ошибка - >резервное копирование.ПНГ->ошибка->,,,,,
У меня такая же проблема. Этот код хорошо работает в моем случае.
// Replace broken images by a default img
$('img').each(function(){
    if($(this).attr('src') === ''){
      this.src = '/default_feature_image.png';
    }
});
иногда с помощью error событие невозможно, например, потому, что вы пытаетесь сделать что-то на странице, которая уже загружена, например, когда вы запускаете код через консоль, букмарклет или скрипт, загруженный асинхронно. В таком случае, проверьте, что img.naturalWidth и img.naturalHeight 0, кажется, делает трюк.
например, вот фрагмент для перезагрузки всех сломанных изображений с консоли:
$$("img").forEach(img => {
  if (!img.naturalWidth && !img.naturalHeight) {
    img.src = img.src;
  }
}
Я использую код ниже, который сначала пытается найти аватар текущего пользователя на основе их идентификатора пользователя, который в этом случае является "123", и если он не находит изображение Аватара, код onerror изменяет img src на изображение-заполнитель.
<img src="avatars/users/123.png" onerror="this.src='/ngTribeBase/src/assets/img/avatars/male.png'" />
