Replacing broken images dynamically with JQuery
Thursday, June 2nd, 2011
As any affiliate worth their salt knows, your website is only as good as your content. And when relying on third party data feeds to populate parts of your site there is always the risk that some content may not reach the high standards you desire.
A prime example of this is product images.
When dealing with a large number of products I often find that, for one reason or another, links to some images will be broken.
That’s just the way it is. Maybe the feed is slightly out of date, maybe the image has been moved or renamed since the feed was generated? Either way it happens and it doesn’t look great.
It can also (if your users are still stuck in 2008 and using IE) result in that dreaded no image ‘red cross’; and as we know, any kind of ‘error’ [or should I say anything that can be perceived as an error] is not going to inspire much confidence in your users.
Not ideal.
We could of course simply check all the images in the data feed prior to using it – but what if the feed import is automated? And / or your feed contains thousands of products? Checking every image prior to use is simply not feasible.
Time for JQuery
Thanks to JQuerys ability to easily loop over any element it is extremely simple to use the client side library to check all of your product images after the page load, and replace any that appear to be broken.
So let’s do it.
If your website does not already use JQuery you will need to add it – and the easiest way of doing that is simply by pulling the library directly from Google.
Add this line just above the closing </head> tag on the page you would like to check for broken images (in my case it is the product search results page).
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> </script>
Now we have loaded the JQuery library we simply need to add the code to perform some magic on our images.
Paste the below code just above the closing </body> tag of your page:
<script type="text/javascript">
$(window).load(function() {
$("img").each(function(){
var image = $(this);
if(image.context.naturalWidth == 0 ||
image.readyState == 'uninitialized'){
$(image).unbind("error").attr(
"src", "path/to/image/no-image.gif"
);
}
});
});
</script>
The code above may look complicated so let’s break it down.
- Firstly we create a function to be executed when our webpage has been loaded. It needs to be when the page has loaded as we need to give all our images an opportunity to load before we attempt to replace any.
$(window).load(function() { }); - Next inside this function we need to loop over all our images. We can do this using the ‘img’ selector and calling the each method. This will then iterate over each image on the page. Perfect.
$(window).load(function() {
$("img").each(function(){
});
});
- Next we get an instance of the ‘current’ image in the loop using a special keyword called this.
$(window).load(function() { $("img").each(function(){ var image = $(this); }); }); - And finally we use the current image object to check a couple of things. We check if the width of the image is zero or if its readyState is ‘uninitialized’ – yup that is a load of gibberish to most people but in plain English it simply means that if those two parameters are true then the image has NOT loaded. So again using the current image object we can ‘unbind’ it – and assign it a NEW image path (path/to/image/no-image.gif). This can be to any image of your choosing (personally I use a nice coming soon image)
$(window).load(function() {
$("img").each(function(){
var image = $(this);
if(image.context.naturalWidth == 0 ||
image.readyState == 'uninitialized'){
$(image).unbind("error").attr(
"src", "path/to/image/no-image.gif"
);
}
});
});
And it is as simple as that. Any image that now fails to load correctly will be replaced with the image you specified.
Great huh?
Well – no, not exactly.
What if (for some reason) your site logo failed to load? Would you really want your site logo replaced with a ‘coming soon’ image?
No. So what we need to do it make sure JQuery only replaces the images we want it to replace.
And we can do that easily enough by applying a specific ‘class’ to those images.
Let’s say for example we had the following product images:
<img src="http://path/to/image1.jpg" alt="product one" /> <img src="http://path/to/image2.jpg" alt="product two" /> <img src="http://path/to/image3.jpg" alt="product three" /> <img src="http://path/to/image4.jpg" alt="product four" />
We could easily apply a class of ‘product’ to those images like this:
<img class="product" src="http://path/to/image1.jpg" alt="product one" /> <img class="product" src="http://path/to/image2.jpg" alt="product two" /> <img class="product" src="http://path/to/image3.jpg" alt="product three" /> <img class="product" src="http://path/to/image4.jpg" alt="product four" />
And then we could modify our JQuery to only loop over images that had the ‘product’ class like this:
$(window).load(function() {
$("img.product").each(function(){
var image = $(this);
if(image.context.naturalWidth == 0 ||
image.readyState == 'uninitialized'){
$(image).unbind("error").attr(
"src", "images/new/no-image.gif"
);
}
});
});
Now JQuery will ignore all other images on the page and only attempt to replace images that are of class product.
Simple.
Hope this gives you a little idea of what small tweaks can be made client side in order to help make the users experience a little nicer.
Feel free to leave your thoughts and comments below.













4 Comments
MyShadowSelf
06.21.2011
Great tip, I hadn’t thought of using jQuery to replace images – always tried using PHP with varying degrees of success.
But…
Just looking at your code, couldn’t it be sped up alittle (a teeny tiny amount) by NOT setting the $image variable? And wouldn’t it be more efficient and reliable by using jQuery’s built in ready() function?
Like so:
Still a nice inventive way of saving the page however you go about it. I think I’ll be using it very soon!
Robi
06.21.2011
Thanks – the reason I didn’t use document ready and instead plumped for window.ready is that document ready fires when the DOM is loaded. As we need to get the width and height of images we need to be sure that all images have finished loading. This is where window.ready comes in. It fires when all elements (including images) are loaded.
MyShadowSelf
06.21.2011
After abit of research I now see that $(document).ready() would only work if the images had already been loaded, hence $(window).load() – something I wasn’t aware of.
Everyday’s a schoolday!
Cheers Robi
Devin
06.19.2012
Does anyone know why the following code would not work with internet explorer? I’ve tested it in safari and chrome so far and it worked fine. Here it is:
$(window).load(function() {
$(“img”).each(function(){
var image = $(this);
if(image.context.naturalWidth == 0 ||
image.readyState == ‘uninitialized’){
$(‘.post’).hide(0);
$(‘#no_results’).slideDown(300);
}
});
});
Any help would be greatly appreciated! I’ve been pulling my hair out trying to get it to work.
Devin
There are no trackbacks to display at this time.