Home  >  

jQuery Quickie - Broken Images

Author photo
AddThis Social Bookmark Button
Last week I discussed a simple jQuery method to handle images missing title tags. (See jQuery Quickie - Images and Alt Tags.) The code was rather simple. It used jQuery selectors to find images with missing title tags and either copy over the alt tag, or at least the file name. My thinking was that this could be useful for cases when you don't have control over the HTML. The client may be using a rich text editor that doesn't properly use the TITLE attribute.

In the same vein of thought, what about broken images? Turns out the code to handle that is even simpler! Thanks go to Todd Sharp for sharing this with me.

First, let's begin with a simple page that has some hard coded HTML in it with a mix of good and broken images.

<html>
	
<head>
<title>Image Test</title>
</head>

<body>
	
<div id="content">	
<p>
This is some content. Here is the first image...
</p>
<p>
<img src="http://www.coldfusionjedi.com/images/raymond2008small.jpg" title="Raymond">
</p>
<p>
Another paragraph, first broken image...
</p>
<p>
<img src="http://www.coldfusionjedi.com/pdfdpofopopf.jpb">
</p>
<p>
Third paragraph, will be a good image.
</p>
<p>
<img src="http://www.cflib.org/images/gravatarsample.jpg">
</p>
<p>
Last paragraph, another bad image.
</p>
<p>
<img src="http://www.coldfusionjedi.com/pdfdpofo.jpb">	
</p>
</div>

</body>
</html>
Nothing too complex here. Just a few paragraphs interspersed with images. The first and third image are valid. The second and fourth ones are not. Just to confirm they are indeed broken, check out the first demo.

So how do we fix it? Turns out rather easily. One of the events jQuery can listen out for is an error event. While not very obvious, an image with a bad url is considered an error. Maybe that is obvious, but it was a surprise to me. So to fix the broken images, we need a grand total of 3 lines of code:

$('img').error(function(){
 	$(this).attr('src', 'missing.jpg');
});
In this snippet, the error event for all images tags is bound to a function that will update the image src to point to missing.jpg. Once again, I'm impressed by how useful jQuery can make tasks. You can view a demo of this here. You will notice the 2 broken images have been replaced.

Read more from Raymond Camden. Raymond Camden's Atom feed cfjedimaster on Twitter

Comments

20 Comments

Cool! I didn't know about jQuery error() - been doing it like this:

( gleaned a while back from http://www.robgonda.com/blog/index.cfm/2008/4/21/HTML-OnMissingImage )

But your jQuery method means it can be done globally... and it is jQuery, which means double cool points.

Just make sure your replacement image is really there, or you get a nasty browser meltdown in IE (not that I would ever do that... of course not... )

So credit goes to Todd and Rob. Definitely not 'my' idea, I'm just spreading the jQuery love. :)

Jeffrey Jose said:

Same here, didnt know there was an error function. Time to dig in more on that one. Thanks for sharing.

/j

Gary Funk said:

This is great. One question though. Why does this work in FireFox and not IE.

Interesting. Not sure. Sorry - I had assumed such a simple thing would work fine in IE.

Gary Funk said:

I put your code on my site and it works fine in IE. Just doesn't work in IE on your site. I wonder, in IE, what the URL is for the missing image. I used the FULL url to the image when I tried it.

Gary Funk said:

I think I know why. It is looking for missing.jpg in the same directory that the missing image is in. Would you mind putting a different missing.jpg in your root directory. One that we can tell comes from the root directory?

Gary

Gary Funk said:

One last item. I used: http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js

instaed of the local code you used.

Gary Funk said:

Ray,

Your local jquery.js is 1.3.1. It works with IE in 1.3.2.

Bam. You are the man. I don't know why I don't use the Google API version all of the time. Thanks Gary!

anthony said:

Ray,

This method doesn't work if the dom load event fires before the img error event. I think that a better way of replacing images would be to wait for the window.onload event to fire, then check if any of the images are broken.


$(window).bind('load', function() {
$('img').each(function() {
if((typeof this.naturalWidth != "undefined" &&
this.naturalWidth == 0 )
|| this.readyState == 'uninitialized' ) {
$(this).attr('src', 'missing.jpg');
}
});
})


Hmm, but I _am_ using $(document).ready - are you saying it needs to be window load instead?

anthony said:

No. The problem here is that if the image finishes its request and errors before the dom finishes loading, it's too late for jQuery to attach the onerror event. So using the onerror event wont consistently work unless you attach the event inline.

To get around this, you can check to see if the images actually loaded instead. $(document).ready happens once the dom is done, which could be before the images have finished loading, so that won't work reliably. If we wait for everything to load (window.onload), then we can be sure that the image failed to load.

That makes sense. Thanks Anthony. Think I should write a follow up post that clearly demonstrates this?

Backing up what Raymond said....
I wrote a script to resize and center image thumbnails within a container and I used the window.onload method instead of document.ready and I got more consistent results too, with document.ready it seems to jump the gun before all the images are fully loaded.

Scott Stroz said:

I cannot get this to work in IE 7 event when using updated jQuery and using window.onload.

Unfortunately I've only got IE8 not. Works fine there.

michael said:

Thanks for the code Ray. However, if I put all the javascript at the bottom of your example (per best practice recommendation for performance), then your image src replacement doesn't work (i.e. doesn't get triggered). Would you happen to know why? Too late for img error event when placed at the bottom of html?

michael said:

update:

I just tried using anthony's code above with $(window).bind('load')... and that works for me with all the javascript at the bottom of the html (thanks anthony!, and thanks Ray for the great post!).

Glad you got it, and thanks again Anthony for the fix.

Leave a comment


Tag Cloud

Question of the Week: Dream App

If you had an unlimited budget and unlimited resources what application would you build and why would you build it?

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.