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.
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:
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
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';
}
});
});
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'
});
$(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
c'est une technique merdique, mais c'est assez garanti:
<img ... onerror="this.parentNode.removeChild(this);">
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';" />
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;)
$("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"),
});
}
});
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);
});
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.
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] );
}
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.
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)
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;
}
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.
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} />;
);
}
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))
})
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>
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.
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.
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');
}
});
}
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] || ''; });
});
};
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');
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; }
}
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');
});
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 :
-
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. -
utilisez la capture d'événements pour détecter les erreurs, en particulier pour les événements qui ne font pas de bulles.
-
utiliser une délégation d'événement qui évite de lier des événements sur chaque image.
-
donner l'erreur
img
élément un attribut après leur donner unbackup.png
pour éviter la disparition de labackup.png
et boucle infinie subséquente comme ci-dessous:
erreur img - > sauvegarde.png->erreur->sauvegarde.png - > erreur->,,,,,
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';
}
});
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;
}
}
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'" />