jQuery / JavaScript pour remplacer les images brisées

j'ai une page web qui inclut un tas d'images. Parfois l'image n'est pas disponible, donc une image brisée est affichée dans le navigateur du client.

comment utiliser jQuery pour obtenir le jeu d'images, le filtrer aux images brisées puis remplacer le src?


--je pensais qu'il serait plus facile de le faire avec jQuery, mais il s'est avéré beaucoup plus facile d'utiliser une solution JavaScript pure, c'est-à-dire celle fournie par Prestaul.

490
demandé sur Peter Mortensen 2008-09-18 17:53:32

30 réponses

Gérer l'événement onError pour l'image de réassigner sa source en utilisant JavaScript:

function imgError(image) {
    image.onerror = "";
    image.src = "/images/noimage.gif";
    return true;
}
<img src="image.png" onerror="imgError(this);"/>

ou sans fonction JavaScript:

<img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" />

le tableau de compatibilité suivant énumère les navigateurs qui prennent en charge la fonction d'erreur:

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

674
répondu Prestaul 2013-04-28 14:58:58

j'utilise le construit dans error handler:

$("img").error(function () {
  $(this).unbind("error").attr("src", "broken.gif");
});

error() déprécié en 1.8 ou plus.

184
répondu travis 2016-07-04 13:08:03

dans le cas où quelqu'un comme moi, tente d'attacher l'événement error à une étiquette dynamique HTML img , je tiens à souligner que, Il ya un hic:

Apparemment img les événements d'erreur ne pas bulle dans la plupart des navigateurs, contrairement à ce que le standard dit.

donc, quelque chose comme ce qui suit will pas de travail :

$(document).on('error', 'img', function () { ... })

Espérons que ce sera utile à quelqu'un d'autre. Je souhaite que je n'avais pas vu cela ici dans ce fil. Mais je ne l'ai pas fait. Donc, je l'ajoute

111
répondu mouad 2016-06-14 13:19:55

Voici une solution autonome:

$(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';
    }
  });
});
53
répondu Devon 2008-09-18 14:38:01

je crois que c'est ce que vous cherchez: jQuery.Préchargez

voici le code d'exemple de la démo, vous spécifiez le chargement et les images non trouvées et vous êtes prêt:

$('#images img').preload({
    placeholder:'placeholder.jpg',
    notFound:'notfound.jpg'
});
32
répondu Nick Craver 2008-09-18 14:05:26
$(window).bind('load', function() {
$('img').each(function() {
    if((typeof this.naturalWidth != "undefined" &&
        this.naturalWidth == 0 ) 
        || this.readyState == 'uninitialized' ) {
        $(this).attr('src', 'missing.jpg');
    }
}); })

Source: http://www.developria.com/2009/03/jquery-quickie---broken-images.html

23
répondu Mohamad 2013-09-16 19:49:13

c'est une technique merdique, mais c'est assez garanti:

<img ...  onerror="this.parentNode.removeChild(this);">
9
répondu Phil LaNasa 2014-04-11 13:54:10

pendant que L'OP cherchait à remplacer le SRC, je suis sûr que beaucoup de gens qui se posent cette question ne souhaiteront peut-être que Cacher l'image brisée, auquel cas cette solution simple a bien fonctionné pour moi:

<img src="someimage.jpg" onerror="this.style.display='none';" />
9
répondu Nathan Arthur 2017-05-23 12:26:33

voici un moyen rapide et sale pour remplacer toutes les images brisées, et il n'est pas nécessaire de changer le code HTML;)

exemple de code

    $("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"),
            });
        }
  });
9
répondu Ashfaq Ahmed 2018-09-09 23:13:26

Je n'ai pas pu trouver de script pour répondre à mes besoins, donc j'ai fait une fonction récursive pour vérifier les images brisées et essayer de les recharger toutes les quatre secondes jusqu'à ce qu'elles soient réparées.

Je l'ai limité à 10 tentatives comme si elle n'était pas chargée d'ici là l'image pourrait ne pas être présente sur le serveur et la fonction entrerait dans une boucle infinie. Je suis encore en test. Se sentir libre de le modifier :)

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);
});
8
répondu Shade 2016-05-15 19:59:12

vous pouvez utiliser le propre fetch de GitHub pour ceci:

Frontend: https://github.com/github/fetch

ou pour le Backend, un Nœud.version js: https://github.com/bitinn/node-fetch

fetch(url)
  .then(function(res) {
    if (res.status == '200') {
      return image;
    } else {
      return placeholder;
    }
  }

Edit:cette méthode va remplacer XHR et aurait déjà été dans Chrome. Pour quiconque lisant ceci dans le futur, vous pouvez ne pas avoir besoin de la bibliothèque mentionnée ci-dessus.

5
répondu BarryMode 2016-09-22 18:18:20

il S'agit de JavaScript, devrait être compatible avec les navigateurs croisés, et livre sans le marqueur laid 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:

5
répondu Axel 2017-09-05 10:31:09

mieux appeler en utilisant

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

parce que l'utilisation de document.ready n'implique pas nécessairement que les images sont chargées, seulement le HTML. Il n'est donc pas nécessaire de retarder l'appel.

4
répondu Shade 2016-05-15 20:00:10

CoffeeScript variante:

je l'ai fait pour résoudre un problème avec Turbolinks qui provoque l' .erreur() méthode pour obtenir soulevées dans Firefox parfois, même si l'image est vraiment là.

$("img").error ->
  e = $(@).get 0
  $(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)
4
répondu Kevin 2016-05-15 20:01:30

en utilisant réponse de Prestaul , j'ai ajouté quelques vérifications et je préfère utiliser la méthode 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;
}
4
répondu trante 2017-05-23 11:55:10

si vous avez inséré votre img avec innerHTML , comme: $("div").innerHTML = <img src="wrong-uri"> , vous pouvez charger une autre image si elle ne fonctionne pas, E. g, ceci:

<script>
    function imgError(img) {
        img.error="";
        img.src="valid-uri";
    }
</script>

<img src="wrong-uri" onerror="javascript:imgError(this)">

pourquoi javascript: _ est-il nécessaire? Parce que les scripts injectés dans le DOM via les balises de script dans innerHTML ne sont pas exécutés au moment où ils sont injectés, vous devez donc être explicite.

4
répondu horro 2016-05-15 20:10:41

j'ai trouvé ce post tout en regardant cet autre so post . Voici une copie de la réponse que j'y ai donnée.

je sais que c'est un vieux fil, mais React est devenu populaire et, peut-être, quelqu'un utilisant React viendra ici à la recherche d'une réponse au même problème.

donc, si vous utilisez React, vous pouvez faire quelque chose comme ce qui suit, qui était une réponse originale fournie par Ben Alpert de L'équipe React ici

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} />;
    );
}
4
répondu Jordan Bonitatis 2017-05-23 11:55:10

j'ai créé un violon pour remplacer l'image brisée en utilisant l'événement" onerror". Cela peut vous aider.

    //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))
    })
4
répondu Ninjaneer 2016-09-01 13:23:34

voici un exemple utilisant L'objet Image HTML5 Enveloppé par JQuery. Appelez la fonction load pour L'URL de l'image primaire et si cette charge provoque une erreur, remplacez l'attribut src de l'image par une URL de sauvegarde.

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>
4
répondu Kurt Hartmann 2016-11-04 16:00:23

Pure js. Ma tâche était: si l'image ' BL-once.png' est vide -> insérer le premier (qui n'a pas de statut 404) de l'image à partir de la liste du réseau (dans le répertoire courant):

<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">

peut-être qu'il faut l'améliorer, mais:

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

                }
            }
        }

    };

ainsi, il insérera correct 'nécessaire.png' à ma src ou " non-image.png " du dir actuel.

4
répondu Дмитрий Дорогонов 2017-04-10 13:59:14

Je ne suis pas sûr s'il y a une meilleure façon, mais je peux penser à un hack pour l'obtenir - vous pouvez Ajax post à L'URL img, et parse la réponse pour voir si l'image est réellement revenue. S'il est revenu comme un 404 ou quelque chose, puis échanger l'img. Si j'attends d'être assez lent.

3
répondu Chii 2016-05-15 19:55:36

j'ai résolu mon problème avec ces deux fonctions simples:

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');
        }
    });
}
3
répondu Luis Gustavo Beligante 2016-05-15 20:03:37

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" );

référence

3
répondu Nabi K.A.Z. 2017-09-02 03:16:04
;(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] || ''; });
    });
};

vous pouvez passer un chemin d'accès et y accéder Toutes les propriétés de l'objet image échoué via $* :

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

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

2
répondu yckart 2013-07-01 11:02:48

cela m'a frustré pendant des années. Mon correctif CSS définit une image de fond sur le img . Lorsqu'une image dynamique src ne se charge pas au premier plan, un paramètre est visible sur le bg img . Cela fonctionne si vos images ont une taille par défaut (par exemple height , min-height , width et / ou min-width ).

, Vous verrez l'icône d'image brisée, mais c'est une amélioration. Testé jusqu'à IE9 avec succès. iOS Safari et Chrome ne montrez même pas une icône cassée.

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
}

Ajouter un peu d'animation pour donner src temps de charger sans flicker d'arrière-plan. Le Chrome s'estompe à l'arrière-plan en douceur, mais le Safari bureau ne le fait pas.

.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; }
}
2
répondu Dylan Valade 2014-04-25 15:20:46

si l'image ne peut pas être chargée (par exemple, parce qu'elle n'est pas présente à L'URL fournie), l'URL de l'image sera changée par défaut,

pour en savoir plus sur .erreur ()

$('img').on('error', function (e) {
  $(this).attr('src', 'broken.png');
});
2
répondu CasperSL 2018-02-20 04:41:52

je pense que j'ai une façon plus élégante avec la délégation d'événement et l'événement capturant sur window 's error même lorsque l'image de sauvegarde ne se charge pas.

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">

Le point est :

  1. mettez le code dans le head et exécuté comme le premier script en ligne. Donc, il écoutera les erreurs qui se produisent après le script.

  2. utilisez la capture d'événements pour détecter les erreurs, en particulier pour les événements qui ne font pas de bulles.

  3. utiliser une délégation d'événement qui évite de lier des événements sur chaque image.

  4. donner l'erreur img élément un attribut après leur donner un backup.png pour éviter la disparition de la backup.png et boucle infinie subséquente comme ci-dessous:

erreur img - > sauvegarde.png->erreur->sauvegarde.png - > erreur->,,,,,

2
répondu xianshenglu 2018-05-24 01:30:41

j'ai eu le même problème. Ce code fonctionne bien sur mon cas.

// Replace broken images by a default img
$('img').each(function(){
    if($(this).attr('src') === ''){
      this.src = '/default_feature_image.png';
    }
});
1
répondu Dale Nguyen 2017-11-16 20:43:54

utiliser parfois l'événement error n'est pas possible, par exemple parce que vous essayez de faire quelque chose sur une page déjà chargée, comme quand vous lancez du code via la console, un bookmarklet, ou un script chargé asynchrone. Dans ce cas, vérifier que img.naturalWidth et img.naturalHeight sont 0 semble faire l'affaire.

par exemple, voici un extrait pour recharger toutes les images cassées de la console:

$$("img").forEach(img => {
  if (!img.naturalWidth && !img.naturalHeight) {
    img.src = img.src;
  }
}
1
répondu Lea Verou 2018-01-14 15:56:36

j'utilise le code ci-dessous qui tente d'abord de trouver l'avatar de l'utilisateur actuel basé sur son userid qui dans ce cas est" 123", et s'il ne trouve pas d'image avatar le code onerror change l'IMG src en une image de remplacement.

<img src="avatars/users/123.png" onerror="this.src='/ngTribeBase/src/assets/img/avatars/male.png'" />
-4
répondu Charles Naccio 2015-02-17 17:59:26