views:

170

answers:

5

Do you know how to hide the classic “Image not found” icon from a rendered HTML page when an image file is not found?

Is it feasible with JavaScript\jQuery\CSS?

+13  A: 

You can use the onerror event in JavaScript to act when an image fails to load:

var img = document.getElementById("myImg");
img.onerror = function () { 
    this.style.display = "none";
}

In jQuery (since you asked):

$("#myImg").error(function () { 
    $(this).hide(); 
});

Or for all images:

$("img").error(function () { 
    $(this).hide();
    // or $(this).css({visibility:"hidden"}); 
});

You should use visibility: hidden instead of .hide() if hiding the images might change the layout. Many sites on the web use a default "no image" image instead, pointing the src attribute to that image when the specified image location is unavailable.

Andy E
is that crossbrowser?
jAndy
andy - what would be the 'global' solution to apply to ALL images?? i'm thinking it would be easy enough if they were all in the same div - just wondered about ALL images in the document...
jim
@jAndy: I was fairly sure it is, but your comment made me double-check. A quick Google returned this [w3schools page](http://www.w3schools.com/jsref/event_img_onerror.asp) (sorry David, if you're reading this) indicating cross browser support.
Andy E
@jim: If you're using jQuery, you can apply the event to all images. just use the tag selector, e.g. `$("img").error(function () { /*...*/ });`.
Andy E
@Andy E: sounds good, +1. next interesting question would be, is "`error`" boundable with `live()` or `delegate()`.
jAndy
StackOverflow engine seems to have a different approach, i've searched your solution on master js but i did not found any .error at all. Do you know how they handle it?
systempuntoout
thanks andy - doh :)
jim
Unfortuantly, its not possible to `live` bind the `error` event.
jAndy
@jAndy: I'm pretty sure you can only use `live()` and `delegate()` for custom events, events that bubble and events that don't bubble but have a bubbling alternative. Check the [ *Caveats* ](http://api.jquery.com/live/#caveats) section of the docs.
Andy E
`visibility` would be better, since `display` can break the layout.
galambalazs
@systempuntooout: I'm not sure there is any other way to handle it. There's possibly some clever trick that I'm not aware of. If you want to know how something is implemented in Stack Overflow you could try asking over at http://meta.stackoverflow.com.
Andy E
@galambalazs: it depends on the usage, but `visibility` would be more useful. Many sites on the web do neither, instead swapping the image for a default, "no image" image.
Andy E
+3  A: 

Andy's reply is correct, however, you might want to use style.vsibility instead.

If you set visibility, the element still keeps its space on your document, thus no funny document movements.

Christian Sciberras
+1, I meant to add this to my answer early on but was inundated by alerts so I got distracted :-)
Andy E
+2  A: 

Doing a quick research on Andy E's answer, its not possible to live() bind error.

// won't work (chrome 5)
$('img').live('error', function(){
     $(this).css('visibility', 'hidden');
});

So you have to go like

$('<img/>', {
  src:    'http://www.notarget.com/fake.jpg',
  error:  function(e){
    $(this).css('visibility', 'hidden');
  }
}).appendTo(document.body);

directly binding the error event handler on creating a new element.

jAndy
+1, the reason for this is that the *onerror* DOM event doesn't bubble. *live* and *delegate* work by placing the event handler further up the DOM hierarchy and capturing the event as it bubbles up. Of course, the jQuery devs have worked around this for some events like *focus* and *blur*
Andy E
@Andy E: Yay, they already workedaround that, might be not the worst of ideas to do a similar thing for `error`. Sounds like a `nice to have` for me.
jAndy
+1  A: 
<img onerror='this.style.display = "none"'>
Gary Willoughby
Unluckily i can't use this solution because html content is downloaded from a third party website via Json and i can't edit it. Thanks anyway.
systempuntoout
A: 

All images: javascript( you add this script at the bottom of your page - just before the closing body tag)

    (function(){

    var allimgs = document.images;

    for(var i=0; i<allimgs.length; i++){

    allimgs[i].onerror = function () {

        this.style.visibility = "hidden"; // other elements not affected 

      }

  }

})();
Q_the_dreadlocked_ninja
Your code is executed in the window.onload event, which fires after all images have loaded. This means you're setting the *onerror* handler after the event would have already fired.
Andy E