Test for broken images -- works in Safari
9 months ago / 4 Comments
I've been doing a bit of work recently on the Windmill project for OSAF -- it's pretty usable already, and we're just now approaching the 0.2 release.
One of the pieces I added awhile back was an assert to check for broken images. After doing a bunch of poking around online, the one piece that seemed to elude everyone doing this kind of check was something that works in Safari 2. We plan to support Safari in Windmill, so I did a bit more research and hammered out something that seems to work reliably.
The crux of the problem with Safari is that it doesn't support the complete attribute -- at least not for images loaded normally in markup. Interestingly though, it does support it for script-created images -- which opens to the door to this hack.
Here's the code:
function assertImageLoaded(img) { var complete = img.complete; var ret = null; // Return value // Workaround for Safari -- it only supports the // complete attrib on script-created images if (typeof complete == 'undefined') { var test = new Image(); // If the original image was successfully loaded, // src for new one should be pulled from cache test.src = img.src; complete = test.complete; } // Check the complete attrib. Use strict equality // check -- don't want undefined, null, etc. // -------------------------- // False -- Img failed to load in IE/Safari, or is // still trying to load in FF if (complete === false) { ret = false; } // True, but image has no size -- image failed to // load in FF else if (complete === true && img.naturalWidth == 0) { ret = false; } // Otherwise all we can do is assume image loaded else { ret = true; } return ret; }
The hack for Safari depends on the normal caching behavior of the browser.
When you do the check, the complete attribute for the original image will be undefined -- but when you create a new Image with JavaScript, and set its src to the src of the original, it grabs the image from cache, and the complete attribute for the script-created image is immediately set to true.
This assumes of course that Safari is pulling images from cache after the first hit, but that should be the default behavior, and in the vast majority of cases that's what you want. If you're using this code, and you get a bunch of false hits for broken images in Safari, you'll want to take a look at how both your browser and server are configured for caching.
Comments
Unfortunately this does not work in all cases. It also detects slow loading images as broken.
Dougal
Unfortunately, this doesn’t work for all cases. I’m trying to solve this exact problem with Safari, but I can’t use “new Image()” due to yet another Safari image bug:
http://alvinwoon.com/blog/2007/08/29/safaris-javascript-image-object-bug/