How to add a CSS class to images that did not load?

20

I have an HTML page with numerous images displayed as follows:

<img alt="img1" width="50" height="120" src="my_image.jpg" />
<img alt="img2" width="50" height="120" src="another_image.jpg" />
<img alt="img3" width="50" height="120" src="yet_another_image.jpg" />

If any of the images do not load for either A or B, there will be breaks in the layout or in some browsers, the image square will appear with alternate text, making it look a bit ugly.

Question

Example:

<img alt="img1" width="50" height="120" src="my_image.jpg" class="failToLoad" />
    
asked by anonymous 04.01.2014 / 15:51

3 answers

9

The most "natural" way would be to use onerror (jQuery: error ), but care is needed because this event will only be captured if it occurs after the handler has already been added. So one solution would be to put the script that adds the class at the beginning of the document ( head , or start body - before any img ). To not get too heavy, a solution jQuery:

<script type="text/javascript">
function erro(elemento) { 
    elemento.className += ' failToLoad'; // Adiciona a classe às já existentes, se houver
}
</script>
...
<img src="..." onerror="erro(this)" />

Example in jsFiddle .

An alternate way, based in this answer in the English OS, seems to work correctly if you need to put JavaScript at the end (in% of document%, for example).

$('img').each(function() {
    if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
        $(this).addClass('failToLoad');
    }
});

Example . The advantage of this technique is that you do not need to change HTML tags.

    
04.01.2014 / 16:26
3

You can assign an event of error to the desired images and add the class failToLoad

Example

$("#falha")
.on('error',function(){
   $(this).addClass('failToLoad');
   console.log('Essa imagem nao carregou');
})
.attr('src','falha.png');

Remembering that you can not retrieve the error after the image and DOM are loaded , since the browser will already have propagated the error event while loading the image , so you should enter src after attaching the event to it.

This difficulty is highlighted in the jQuery API .error ()

JsFiddle Example

Solution

An automated solution would be to use the tags data-*

HTML
<img data-src="falha.png">
JavaScript
//Para cada <img> da página
$('img').each(function(){
    //Selecionar essa imagem
    $(this)
    //Atribuir o evento de erro
    .on('error', function(){
        //Caso ocorra o erro, adicionar a classe failToLoad
        $(this).addClass('failToLoad');
    })
    //Definir o src da imagem recuperando do atributo data-src
    .attr('src',$(this).data('src'));
});

So all your images that have error loading will automatically gain the failToLoad class

JsFiddle Solution

    
04.01.2014 / 16:35
1

For new dynamically inserted elements you can do it using MutationObserver . And for the remaining images just get them and add the event.

var observer = new MutationObserver(
    function(mutations) 
    {
        for (var m in mutations)
        {
            var mutation = mutations[m];

            if (mutation.addedNodes) // todos nodos adicionados
            {
                for (var i = 0; i < mutation.addedNodes.length; ++i)
                {
                    var node = mutation.addedNodes[i];

                    if (node.nodeName == "IMG") // se for imagem
                    {
                        // adiciona o evento "error"
                        // caso o erro ocorra, a classe será adicionada
                        node.addEventListener("error", function() {
                            node.className += " failToLoad";
                        }, false);
                    }
                }
            }
        }
    }
);

// inicia o observer
observer.observe(document, { childList: true, subtree: true });

And for elements already on the page:

$(function() { // quando a página carregar o DOM

    // para todas imagens da página
    $("img").each(function(i,e) {

        // adiciona o evento
        e.addEventListener("error", function(imgEvents) {
            var img = e;

            e.className += " failToLoad"; // em caso de erro adiciona classe

        }, false);

    });
});

See this example in jsFiddle . Note that dynamically inserted images are also validated. In this example the script is being inserted between the <head> tag.

Note that if the image is external, eg imgur, and you pass an invalid link, the site will not generate the 404 error instead it will generate a default image.

    
04.01.2014 / 18:32