I have a web page that includes a bunch of images. Sometimes the image isn\'t available, so a broken image is displayed in the client\'s browser.
How do I use jQuery
CoffeeScript variant:
I made it to fix an issue with Turbolinks that causes the .error() method to get raised in Firefox sometimes even though the image is really there.
$("img").error ->
e = $(@).get 0
$(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)
Pure JS. My task was: if image 'bl-once.png' is empty -> insert the first one (that hasn't 404 status) image from array list (in current dir):
<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">
Maybe it needs to be improved, but:
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();
}
}
}
}
};
So, it will insert correct 'needed.png' to my src or 'no-image.png' from current dir.
If you have inserted your img
with innerHTML
, like: $("div").innerHTML = <img src="wrong-uri">
, you can load another image if it fails doing, e.g, this:
<script>
function imgError(img) {
img.error="";
img.src="valid-uri";
}
</script>
<img src="wrong-uri" onerror="javascript:imgError(this)">
Why is javascript: _
needed? Because scripts injected into the DOM via script tags in innerHTML
are not run at the time they are injected, so you have to be explicit.
(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] || ''; }
);
});
};
You can pass a placeholder path and acces in it all properties from the failed image object via $*
:
$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');
http://jsfiddle.net/ARTsinn/Cu4Zn/
I use the built in error
handler:
$("img").error(function () {
$(this).unbind("error").attr("src", "broken.gif");
});
Edit: The error()
method is deprecated in jquery 1.8 and higher. Instead, you should use .on("error")
instead:
$("img").on("error", function () {
$(this).attr("src", "broken.gif");
});
I believe this is what you're after: jQuery.Preload
Here's the example code from the demo, you specify the loading and not found images and you're all set:
jQuery('#images img').preload({
placeholder:'placeholder.jpg',
notFound:'notfound.jpg'
});