библиотека jQuery/JavaScript, чтобы заменить сломанные изображения



У меня есть веб-страницу, которая включает в себя кучу образов. Иногда изображение недоступно, поэтому сломанное изображение отображается в браузере клиента.



Как я могу использовать jQuery, чтобы получить набор изображений, фильтровать его на сломанные изображения, а затем заменить src?





--Я думал, что было бы проще сделать это с помощью jQuery, но оказалось намного проще просто использовать чистое решение JavaScript, то есть то, которое предоставлено Prestaul.

557   30  

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';" />

в следующей таблице совместимости перечислены браузеры, которые поддерживают средство ошибок:

http://www.quirksmode.org/dom/events/error.html

программа 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 код ;)

пример codepen

    $("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] );
}

CODEPEN:

лучше позвонить с помощью

jQuery(window).load(function(){
    $.imgReload();
});

потому что с помощью document.ready Не обязательно означает, что изображения загружаются, только HTML. Таким образом, нет необходимости в отложенном вызове.

CoffeeScript вариант:

Я сделал это, чтобы исправить проблему с Turbolinks, которая вызывает .ошибка () метод, чтобы получить поднятый в Firefox иногда, даже если изображение действительно есть.

$("img").error ->
  e = $(@).get 0
  $(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)

С помощью ответ престола, я добавил некоторые проверки, и я предпочитаю использовать способ 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">, вы можете загрузить другое изображение, если это не удается сделать, например, это:

<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 или' нет-изображения.ПНГ с текущего каталога.

Я не уверен, что есть лучший способ, но я могу придумать хак, чтобы получить его - вы можете отправить 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] || ''; });
    });
};

вы можете передать путь заполнителя и получить доступ ко всем свойствам из объекта failed image через $*:

$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');

http://jsfiddle.net/ARTsinn/Cu4Zn/

это расстраивало меня в течение многих лет. Мое исправление CSS устанавливает фоновое изображение на img. Когда динамическое изображение src не загружается на передний план, заполнитель виден на imgС БГ. Это работает, если ваши изображения имеют размер по умолчанию (например,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,

подробнее о .ошибка()

$('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">

суть :

  1. вставить код в тег head и выполняется как первый встроенный скрипт. Таким образом, он будет слушать ошибки происходят после сценария.

  2. используйте захват событий, чтобы поймать ошибки, особенно для тех событий, которые не пузыриться.

  3. используйте делегирование событий, которое позволяет избежать привязки событий к каждому изображению.

  4. дает ошибку 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'" />

Comments

    Ничего не найдено.