Detecting an image 404 in Javascript

JavascriptJqueryCross BrowserDom Events

Javascript Problem Overview


After a user uploads a file we have to do some additional processing with the images such as resizing and upload to S3. This can take up to 10 extra seconds. Obviously we do this in a background. However, we want to show the user the result page immediately and simply show spinners in place until the images arrive in their permanent home on s3.

I'm looking for a way to detect that a certain image failed to load correctly (404) in a cross browser way. If that happens, we want to use JS to show a spinner in it's place and reload the image every few seconds until it can be successfully loaded from s3.

Javascript Solutions


Solution 1 - Javascript

Handle the <img> element's onerror event.

Solution 2 - Javascript

First option:

<img src="picture1.gif" onerror="this.onerror=null;this.src='missing.gif';"/>

Second option:

<html>
<head>
<script type="text/javascript">
    function ImgError(source){
	    source.src = "/noimage.gif";
	    source.onerror = "";
	    return true;
    }
</script>
</head>
<body>
    <img src="image_example1.jpg" onerror="ImgError(this)" />
</body>
</html>

PS: it's pure javascript! you don't need any libraries. (Vanilla JS)

Example in Fidler

https://jsfiddle.net/dorathoto/8z4Ltzp8/71/

Solution 3 - Javascript

From: http://lucassmith.name/2008/11/is-my-image-loaded.html

// First a couple helper functions
function $(id) {
    return !id || id.nodeType === 1 ? id : document.getElementById(id);
}
function isType(o,t) {    return (typeof o).indexOf(t.charAt(0).toLowerCase()) === 0;}

// Here's the meat and potatoes
function image(src,cfg) {    var img, prop, target;
    cfg = cfg || (isType(src,'o') ? src : {});

    img = $(src);
    if (img) {
        src = cfg.src || img.src;
    } else {
        img = document.createElement('img');
        src = src || cfg.src;
    }

    if (!src) {
        return null;
    }

    prop = isType(img.naturalWidth,'u') ? 'width' : 'naturalWidth';
    img.alt = cfg.alt || img.alt;

    // Add the image and insert if requested (must be on DOM to load or
    // pull from cache)
    img.src = src;

    target = $(cfg.target);
    if (target) {
        target.insertBefore(img, $(cfg.insertBefore) || null);
    }

    // Loaded?
    if (img.complete) {
        if (img[prop]) {
            if (isType(cfg.success,'f')) {
                cfg.success.call(img);
            }
        } else {
            if (isType(cfg.failure,'f')) {
                cfg.failure.call(img);
            }
        }
    } else {
        if (isType(cfg.success,'f')) {
            img.onload = cfg.success;
        }
        if (isType(cfg.failure,'f')) {
            img.onerror = cfg.failure;
        }
    }

    return img;
}

And here how to use it:

image('imgId',{
    success : function () { alert(this.width); },
    failure : function () { alert('Damn your eyes!'); },
});

image('http://somedomain.com/image/typooed_url.jpg', {
    success : function () {...},
    failure : function () {...},
    target : 'myContainerId',
    insertBefore : 'someChildOfmyContainerId'
});

Solution 4 - Javascript

just bind the attr trigger on the error event.

$(myimgvar).bind('error',function(ev){
    //error has been thrown
    $(this).attr('src','/path/to/no-artwork-available.jpg');
}).attr('src',urlvar);

Solution 5 - Javascript

This worked for me (mine is in coffeescript). You'll need to replace with a spinner instead, of course.

checkImages = ->
  $("img").each ->
    $(this).error ->
      $(this).attr("src", "../default/image.jpg")

$(document).on('page:load', checkImages)

I'm guessing the javascript equivalent is something like

function checkImages() {
  $("img").each(function() {
    $(this).error(function() {
      $(this).attr("src", "../default/image.jpg");
    });
  });
};

$(document).on("page:load", checkImages);

Solution 6 - Javascript

I just did

if ($('#img')[0].naturalWidth > 0) {

as i noticed there was no naturalWidth if the image 404'd.

However, i can understand wanting to use a method above.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTobias L&#252;tkeView Question on Stackoverflow
Solution 1 - JavascriptSLaksView Answer on Stackoverflow
Solution 2 - JavascriptDorathotoView Answer on Stackoverflow
Solution 3 - JavascriptunomiView Answer on Stackoverflow
Solution 4 - JavascriptoasisfleetingView Answer on Stackoverflow
Solution 5 - Javascriptdav1dhuntView Answer on Stackoverflow
Solution 6 - JavascriptAdam MacView Answer on Stackoverflow