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'
});

Ответ 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: