Image load event - some progress
I know there's been a few discussions centred around the image load
event. This (previously suggested) workaround works fine for catching
both new loads and cached images in the testing I have done:
$('img').bind('load readystatechange', function(e) {
if (this.complete || (this.readyState == 'complete' && e.type ==
'readystatechange')) {
... do stuff ...
}
})
The problem is that binding a load event to the images isn't
guaranteed to happen before the image itself has loaded. So we might
not catch the loading at all.
The workaround to this is fairly straightforward - check to see if
(this.complete || this.readyState == 'complete') { ... do stuff ... }
else [bind as above].
Further problems arise when trying to bind an error event to the image
to catch loading broken images. It works fine if the image hasn't
loaded, but is there any way to tell if the image is broken if it's
already loaded? Well here's the catch: in IE there's no way of
differentiating between images that haven't been loaded at all, and
broken images. In both cases the readyState is 'uninitialized' and the
fileSize is -1.
This makes it impossible to guarantee using $('IMG').bind
('error' .... ) will catch broken images.
But I've stumbled across a solution that has greatly simplified my
code. Like this:
$('img').each(function(){
$(this)
.bind('load readystatechange' .... )
.bind('error' .... )
this.src = this.src; // <-----
});
... then the load / readystatechange / error events will be fired (as
appropriate). Using Fiddler and HttpHeaders, it doesn't seem to
generate another request for the image. This is really useful - it
means we can skip all the code we need to check if the image has
already completed before binding - all you have to do is bind the load
and error events, do 'this.src = this.src' and if the image has
already been loaded it will behave as if it's just been loaded. If the
image hasn't been loaded, this.src = this.src doesn't appear to have
any effect. So you can stop worrying about whether your events are
going to miss some images. It also means you can detect broken images
in IE.
I'm quite encouraged by my initial testing on this. I've testing under
IE 7 and FF 3, and a number of different scenarios (early jquery-loop,
posponed jquery-loop, slow loading images, cached images) but it'll
need some more robust tests before I would suggest it as a thorough
solution. I know IE6 has particular issues, so I'll need to look at
that too.
A
PS One unexpected result - detecting broken images is useful for
putting up a slightly more friendly 'broken image' than the default
browser one by changing the src attribute - but if you do this then
your load event will immediately fire! Took me a few minutes to work
out why the load event was firing on broken images because I was doing
this.