Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if an image is loaded (no errors) with jQuery

I'm using JavaScript with the jQuery library to manipulate image thumbnails contained in a unordered list. When the image is loaded it does one thing, when an error occurs it does something else. I'm using jQuery load() and error() methods as events. After these events I check the image DOM element for the .complete to make sure the image wasn't already loaded before jQuery could register the events.

It works correctly except when an error occurs before jQuery can register the events. The only solution I can think of is to use the img onerror attribute to store a "flag" somewhere globally (or on the node it's self) that says it failed so jQuery can check that "store/node" when checking .complete.

Anyone have a better solution?

Edit: Bolded main points and added extra detail below: I'm checking if an image is complete (aka loaded) AFTER I add a load and error event on the image. That way, if the image was loaded before the events were registered, I will still know. If the image isn't loaded after the events then the events will take care of it when it does. The problem with this is, I can easily check if an image is loaded already, but I can't tell if an error occurred instead.

like image 678
William Avatar asked Dec 30 '09 00:12

William


People also ask

How do I know if an image is loaded?

To determine whether an image has been completely loaded, you can use the HTMLImageElement interface's complete attribute. It returns true if the image has completely loaded and false otherwise. We can use this with naturalWidth or naturalHeight properties, which would return 0 when the image failed to load.

Does jQuery wait for images to load?

In jQuery when you do this: $(function() { alert("DOM is loaded, but images not necessarily all loaded"); }); It waits for the DOM to load and executes your code. If all the images are not loaded then it still executes the code.

How do you handle loading of images that may not exist?

Handle it in your application If an image does not exist, we can replace it with a new one. Another way to handle this issue is by listening to the error event that gets fired when the image fails to load. In HTML, this can be done with the onerror attribute of the <img> tag.


11 Answers

Check the complete and naturalWidth properties, in that order.

https://stereochro.me/ideas/detecting-broken-images-js

function IsImageOk(img) {
    // During the onload event, IE correctly identifies any images that
    // weren’t downloaded as not complete. Others should too. Gecko-based
    // browsers act like NS4 in that they report this incorrectly.
    if (!img.complete) {
        return false;
    }

    // However, they do have two very useful properties: naturalWidth and
    // naturalHeight. These give the true size of the image. If it failed
    // to load, either of these should be zero.
    if (img.naturalWidth === 0) {
        return false;
    }

    // No other way of checking: assume it’s ok.
    return true;
}
like image 94
SLaks Avatar answered Oct 04 '22 16:10

SLaks


Another option is to trigger the onload and/or onerror events by creating an in memory image element and setting its src attribute to the original src attribute of the original image. Here's an example of what I mean:

$("<img/>")
    .on('load', function() { console.log("image loaded correctly"); })
    .on('error', function() { console.log("error loading image"); })
    .attr("src", $(originalImage).attr("src"))
;

Hope this helps!

like image 45
Xavi Avatar answered Oct 04 '22 17:10

Xavi


Based on my understanding of the W3C HTML Specification for the img element, you should be able to do this using a combination of the complete and naturalHeight attributes, like so:

function imgLoaded(imgElement) {
  return imgElement.complete && imgElement.naturalHeight !== 0;
}

From the spec for the complete attribute:

The IDL attribute complete must return true if any of the following conditions is true:

  • The src attribute is omitted.
  • The final task that is queued by the networking task source once the resource has been fetched has been queued.
  • The img element is completely available.
  • The img element is broken.

Otherwise, the attribute must return false.

So essentially, complete returns true if the image has either finished loading, or failed to load. Since we want only the case where the image successfully loaded we need to check the nauturalHeight attribute as well:

The IDL attributes naturalWidth and naturalHeight must return the intrinsic width and height of the image, in CSS pixels, if the image is available, or else 0.

And available is defined like so:

An img is always in one of the following states:

  • Unavailable - The user agent hasn't obtained any image data.
  • Partially available - The user agent has obtained some of the image data.
  • Completely available - The user agent has obtained all of the image data and at least the image dimensions are available.
  • Broken - The user agent has obtained all of the image data that it can, but it cannot even decode the image enough to get the image dimensions (e.g. the image is corrupted, or the format is not supported, or no data could be obtained).

When an img element is either in the partially available state or in the completely available state, it is said to be available.

So if the image is "broken" (failed to load), then it will be in the broken state, not the available state, so naturalHeight will be 0.

Therefore, checking imgElement.complete && imgElement.naturalHeight !== 0 should tell us whether the image has successfully loaded.

You can read more about this in the W3C HTML Specification for the img element, or on MDN.

like image 22
Ajedi32 Avatar answered Oct 04 '22 15:10

Ajedi32


I tried many different ways and this way is the only one worked for me

//check all images on the page
$('img').each(function(){
    var img = new Image();
    img.onload = function() {
        console.log($(this).attr('src') + ' - done!');
    }
    img.src = $(this).attr('src');
});

You could also add a callback function triggered once all images are loaded in the DOM and ready. This applies for dynamically added images too. http://jsfiddle.net/kalmarsh80/nrAPk/

like image 20
Kal Avatar answered Oct 04 '22 17:10

Kal


Use imagesLoaded javascript library.

Usable with plain Javascript and as a jQuery plugin.

Features:

  • officially supported by IE8+
  • license: MIT
  • dependencies: none
  • weight (minified & gzipped) : 7kb minified (light!)

Resources

  • Project on github: https://github.com/desandro/imagesloaded
  • Official website: http://imagesloaded.desandro.com/
  • https://stackoverflow.com/questions/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load
  • imagesloaded javascript library: what is the browser & device support?
like image 44
Josh Harrison Avatar answered Oct 04 '22 17:10

Josh Harrison


Retrieve informations from image elements on the page
Test working on Chrome and Firefox
Working jsFiddle (open your console to see the result)

$('img').each(function(){ // selecting all image element on the page

    var img = new Image($(this)); // creating image element

    img.onload = function() { // trigger if the image was loaded
        console.log($(this).attr('src') + ' - done!');
    }

    img.onerror = function() { // trigger if the image wasn't loaded
        console.log($(this).attr('src') + ' - error!');
    }

    img.onAbort = function() { // trigger if the image load was abort
        console.log($(this).attr('src') + ' - abort!');
    }

    img.src = $(this).attr('src'); // pass src to image object

    // log image attributes
    console.log(img.src);
    console.log(img.width);
    console.log(img.height);
    console.log(img.complete);

});

Note : I used jQuery, I thought this can be acheive on full javascript

I find good information here OpenClassRoom --> this is a French forum

like image 40
Julha Avatar answered Oct 04 '22 16:10

Julha


After reading the interesting solutions on this page, I created an easy-to-use solution highly influenced by SLaks' and Noyo's post that seems to be working on pretty recent versions (as of writing) of Chrome, IE, Firefox, Safari, and Opera (all on Windows). Also, it worked on an iPhone/iPad emulator I used.

One major difference between this solution and SLaks and Noyo's post is that this solution mainly checks the naturalWidth and naturalHeight properties. I've found that in the current browser versions, those two properties seem to provide the most helpful and consistent results.

This code returns TRUE when an image has loaded fully AND successfully. It returns FALSE when an image either has not loaded fully yet OR has failed to load.

One thing you will need to be aware of is that this function will also return FALSE if the image is a 0x0 pixel image. But those images are quite uncommon, and I can't think of a very useful case where you would want to check to see if a 0x0 pixel image has loaded yet :)

First we attach a new function called "isLoaded" to the HTMLImageElement prototype, so that the function can be used on any image element.

HTMLImageElement.prototype.isLoaded = function() {

    // See if "naturalWidth" and "naturalHeight" properties are available.
    if (typeof this.naturalWidth == 'number' && typeof this.naturalHeight == 'number')
        return !(this.naturalWidth == 0 && this.naturalHeight == 0);

    // See if "complete" property is available.
    else if (typeof this.complete == 'boolean')
        return this.complete;

    // Fallback behavior: return TRUE.
    else
        return true;

};

Then, any time we need to check the loading status of the image, we just call the "isLoaded" function.

if (someImgElement.isLoaded()) {
    // YAY! The image loaded
}
else {
    // Image has not loaded yet
}

Per giorgian's comment on SLaks' and Noyo's post, this solution probably can only be used as a one-time check on Safari Mobile if you plan on changing the SRC attribute. But you can work around that by creating an image element with a new SRC attribute instead of changing the SRC attribute on an existing image element.

like image 44
data-dan Avatar answered Oct 04 '22 15:10

data-dan


Realtime network detector - check network status without refreshing the page: (it's not jquery, but tested, and 100% works:(tested on Firefox v25.0))

Code:

<script>
 function ImgLoad(myobj){
   var randomNum = Math.round(Math.random() * 10000);
   var oImg=new Image;
   oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
   oImg.onload=function(){alert('Image succesfully loaded!')}
   oImg.onerror=function(){alert('No network connection or image is not available.')}
}
window.onload=ImgLoad();
</script>

<button id="reloadbtn" onclick="ImgLoad();">Again!</button>

if connection lost just press the Again button.

Update 1: Auto detect without refreshing the page:

<script>
     function ImgLoad(myobj){
       var randomNum = Math.round(Math.random() * 10000);
       var oImg=new Image;
       oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
       oImg.onload=function(){networkstatus_div.innerHTML="";}
       oImg.onerror=function(){networkstatus_div.innerHTML="Service is not available. Please check your Internet connection!";}
}

networkchecker = window.setInterval(function(){window.onload=ImgLoad()},1000);
</script>

<div id="networkstatus_div"></div>
like image 41
Jenei Tamás Avatar answered Oct 04 '22 15:10

Jenei Tamás


This is how I got it to work cross browser using a combination of the methods above (I also needed to insert images dynamically into the dom):

$('#domTarget').html('<img src="" />');

var url = '/some/image/path.png';

$('#domTarget img').load(function(){}).attr('src', url).error(function() {
    if ( isIE ) {
       var thisImg = this;
       setTimeout(function() {
          if ( ! thisImg.complete ) {
             $(thisImg).attr('src', '/web/css/img/picture-broken-url.png');
          }
       },250);
    } else {
       $(this).attr('src', '/web/css/img/picture-broken-url.png');
    }
});

Note: You will need to supply a valid boolean state for the isIE variable.

like image 2
Justin Vincent Avatar answered Oct 04 '22 16:10

Justin Vincent


var isImgLoaded = function(imgSelector){
  return $(imgSelector).prop("complete") && $(imgSelector).prop("naturalWidth") !== 0;
}

// Or As a Plugin

    $.fn.extend({
      isLoaded: function(){
        return this.prop("complete") && this.prop("naturalWidth") !== 0;
      }
    })

// $(".myImage").isLoaded() 
like image 2
boubkhaled Avatar answered Oct 04 '22 17:10

boubkhaled


As I understand the .complete property is non-standard. It may not be universal... I notice it seem to work differently in Firefox verses IE. I am loading a number of images in javascript then checking if complete. In Firefox, this seems to work great. In IE, it doesn't because the images appear to be loading on another thread. It works only if I put a delay between my assignment to image.src and when I check the image.complete property.

Using image.onload and image.onerror isn't working for me, either, because I need to pass a parameter to know which image I am talking about when the function is called. Any way of doing that seems to fail because it actually seems to pass the same function, not different instances of the same function. So the value I pass into it to identify the image always ends up being the last value in the loop. I cannot think of any way around this problem.

On Safari and Chrome, I am seeing the image.complete true and the naturalWidth set even when the error console shows a 404 for that image... and I intentionally removed that image to test this. But the above works well for Firefox and IE.

like image 1
user1018645 Avatar answered Oct 04 '22 16:10

user1018645