views:

87

answers:

4

Is there a way to tell, after the fact, whether an image (placed with the <img> tag, not via JS) has loaded correctly into a page? I have a gallery of head shots, and occasionally the third-party image server ends up serving up a 404. I can change the server-side code to use an onerror="showGenericHeadshot()", but I really want to avoid making changes to server-side code. Ultimately, I want to determine if an image is missing or broken and replace it with a generic "Image Not Found" graphic. Things I've tried:

  1. Image.prototype.onerror = showGenericHeadshot -- doesn't work for <img> tags
  2. $('img[src*=thirdpartyserver.com]).error(showGenericHeadshot) -- doesn't work in IE
  3. $('img[src*=thirdpartyserver.com]).css('backgroundImage','url(replacementimage.gif)') -- works, but still doesn't get rid of the broken image icon in IE
+2  A: 
<img scr='someUrl' id="testImage" />

jQuery('#testImage').bind('load',function(){
         alert ('iamge loaded');
});

to avoid race condition do as below

<img _src="http://www.caregiving.org/intcaregiving/flags/UK.gif" />
// i have added an underscore character before src



jQuery('img').each(function(){
        var _elm=jQuery(this);
        _elm.bind('load',_imageLoaded).attr('src',_elm.attr('_src'))
    });

    function _imageLoaded()
    {
        alert('img loaded');
    }
Praveen Prasad
Except if you do that, you create a race condition. Sometimes the load event will fire before you hook it. The only way to be certain is to create the image element, hook its `load` event, and *then* set its `src`.
T.J. Crowder
@TJCrowder - Confirmed. There is a race condition. The code works locally if I place it high in the page and it doesn't work if I place it further down. Would it work if I, at DOMReady, replaced the image element with a new image element or would that result in, possibly, two requests going out?
Andrew
Cool. Thanks. I definitely do not want to cause two requests. Traffic is one of the reasons the image server goes down and I don't want my fix to make things worse. I may just have to bite the bullet and change the server side code. I'll leave this up for another day and see what other answers I get. Thanks to everyone so far for their help!
Andrew
i have added code to fix race around
Praveen Prasad
@Andrew: Ignore all of my vague thoughts from my earlier comments on this answer (sorry, Praveen, we ended up using your answer for a discussion). I think I've [got it sussed](http://stackoverflow.com/questions/3780344/how-to-tell-if-an-image-has-loaded-correctly/3780930#3780930). I've deleted the earlier wild ideas. :-)
T.J. Crowder
@Praveen: Not bad, although it does mean the images don't get loaded unless JavaScript is enabled. I don't know if that would be a problem for Andrew (it would for me). Also, they don't start loading until the page is otherwise complete (which could be good or bad, depending on what he wants). Separately: Rather than `_src`, I'd recommend `data-src` since although neither of them is valid HTML4, `data-src` is/will be valid HTML5.
T.J. Crowder
+1  A: 

Would an alternate text be sufficient? If so you can use the alt attribute of the img tag.

GôTô
its reasonable, if you have the image inside a defined block level element with width and height etc. Should have alt tags all set anyway! :)
danp
It's unfortunately not sufficient. I'm trying to provide a way for the page to fail gracefully. And the images do all have alt text already.
Andrew
+1  A: 
T.J. Crowder
A: 

Unfortunately, I'm not able to accept either @TJ Crowder's nor @Praveen's excellent answers, though both do perform the desired image-replacement. @Praveen's answer would require a change to the HTML (in which case I should just hook into the <img> tag's own error="" event attribute. And judging by network activity, it look like if you try to create a new image using the url of an image that just 404ed in the same page, the request actually does get sent a second time. Part of the reason the image server is failing is, at least partly, our traffic; so I really have to do everything I can to keep requests down or the problem will only get worse..

The SO question referred to in @danp's comment to my question actually had the answer for me, though it was not the accepted answer there. I'm able to confirm that it works with IE 7 & 8, FF and webkit browsers. I'm doubtful it will work with older browsers, so I've got a try/catch in there to handle any exceptions. The worse case will be that no image-replacement happens, which is no different from what happens now without doing anything. The implementation I'm using is below:

$(function() {
    $('img[src*=images.3rdparty.com]').each(
        function() {
            try {
                if (!this.complete || (!$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0))) {
                    this.src = 'http://myserver.com/images/no_photo.gif';
                }
            } catch(e) {}
        }
    );
});
Andrew