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.
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;
}
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"))
;
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.
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/
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?
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
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.
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>
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.
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()
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.
This snippet of code helped me to fix browser caching problems:
$("#my_image").on('load', function() {
console.log("image loaded correctly");
}).each(function() {
if($(this).prop('complete')) $(this).load();
});
When the browser cache is disabled, only this code doesn't work:
$("#my_image").on('load', function() {
console.log("image loaded correctly");
})
to make it work you have to add:
.each(function() {
if($(this).prop('complete')) $(this).load();
});
Using this JavaScript code you can check image is successfully loaded or not.
document.onready = function(e) {
var imageobj = new Image();
imageobj.src = document.getElementById('img-id').src;
if(!imageobj.complete){
alert(imageobj.src+" - Not Found");
}
}
Try out this
I had a lot of problems with the complete load of a image and the EventListener.
Whatever I tried, the results was not reliable.
But then I found the solution. It is technically not a nice one, but now I never had a failed image load.
What I did:
document.getElementById(currentImgID).addEventListener("load", loadListener1);
document.getElementById(currentImgID).addEventListener("load", loadListener2);
function loadListener1()
{
// Load again
}
function loadListener2()
{
var btn = document.getElementById("addForm_WithImage"); btn.disabled = false;
alert("Image loaded");
}
Instead of loading the image one time, I just load it a second time direct after the first time and both run trough the eventhandler.
All my headaches are gone!
By the way:
You guys from stackoverflow helped me already more then hundred times. For this a very big Thank you!
This one worked fine for me :)
$('.progress-image').each(function(){
var img = new Image();
img.onload = function() {
let imgSrc = $(this).attr('src');
$('.progress-image').each(function(){
if($(this).attr('src') == imgSrc){
console.log($(this).parent().closest('.real-pack').parent().find('.shimmer').fadeOut())
}
})
}
img.src = $(this).attr('src');
});
Related
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.
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;
}
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"))
;
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.
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/
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?
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
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.
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>
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.
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()
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.
This snippet of code helped me to fix browser caching problems:
$("#my_image").on('load', function() {
console.log("image loaded correctly");
}).each(function() {
if($(this).prop('complete')) $(this).load();
});
When the browser cache is disabled, only this code doesn't work:
$("#my_image").on('load', function() {
console.log("image loaded correctly");
})
to make it work you have to add:
.each(function() {
if($(this).prop('complete')) $(this).load();
});
Using this JavaScript code you can check image is successfully loaded or not.
document.onready = function(e) {
var imageobj = new Image();
imageobj.src = document.getElementById('img-id').src;
if(!imageobj.complete){
alert(imageobj.src+" - Not Found");
}
}
Try out this
I had a lot of problems with the complete load of a image and the EventListener.
Whatever I tried, the results was not reliable.
But then I found the solution. It is technically not a nice one, but now I never had a failed image load.
What I did:
document.getElementById(currentImgID).addEventListener("load", loadListener1);
document.getElementById(currentImgID).addEventListener("load", loadListener2);
function loadListener1()
{
// Load again
}
function loadListener2()
{
var btn = document.getElementById("addForm_WithImage"); btn.disabled = false;
alert("Image loaded");
}
Instead of loading the image one time, I just load it a second time direct after the first time and both run trough the eventhandler.
All my headaches are gone!
By the way:
You guys from stackoverflow helped me already more then hundred times. For this a very big Thank you!
This one worked fine for me :)
$('.progress-image').each(function(){
var img = new Image();
img.onload = function() {
let imgSrc = $(this).attr('src');
$('.progress-image').each(function(){
if($(this).attr('src') == imgSrc){
console.log($(this).parent().closest('.real-pack').parent().find('.shimmer').fadeOut())
}
})
}
img.src = $(this).attr('src');
});
I'm trying to dynamically preload list of files which may be anything between images and JavaScript files. Everything is going supersmooth with Chrome and Firefox, but failing when I'm trying to preload JavaScript files with Edge. Edge still can handle images for example but no js files. And yes I've tried with addEventListener, it's not working either.
Edge doesn't give me any errors.
var object = {};
object = document.createElement('object');
object.width = object.height = 0;
object.data = path/to/javascriptfile.js
body.appendChild(object);
object.onload = function(){
console.log('hello world')
//not firing with edge
}
Anything relevant I'm missing?
UPDATE: Didn't get any success after the day. Will probably leave it for now and just skip preloading script files with edge until i find a solution.
Perhaps worth a check - from msdn:
The client loads applications, embedded objects, and images as soon as
it encounters the applet, embed, and img objects during parsing.
Consequently, the onload event for these objects occurs before the
client parses any subsequent objects. To ensure that an event handler
receives the onload event for these objects, place the script object
that defines the event handler before the object and use the onload
attribute in the object to set the handler.
https://msdn.microsoft.com/en-us/library/windows/apps/hh465984.aspx
Edit, a clarification:
You should attach the event listener before the element is added to the page.
Even doing that I'm not sure if it'll work or not though. But to make sure you've exhausted all options try the example below:
function doLoad() {
console.log('The load event is executing');
}
var object = {};
object = document.createElement('object');
object.width = object.height = 0;
object.data = 'path/to/javascriptfile.js';
object.onreadystatechange = function () {
if (object.readyState === 'loaded' || object.readyState === 'complete') doLoad();
console.log('onreadystatechange');
}
if (object.addEventListener) {
object.addEventListener( "load", doLoad, false );
console.log('addEventListener');
}
else
{
if (object.attachEvent) {
object.attachEvent( "onload", doLoad );
console.log('attachEvent');
} else if (object.onLoad) {
object.onload = doLoad;
console.log('onload');
}
}
var body = document.getElementsByTagName("body")[0];
body.appendChild(object);
If this doesn't work, you could perhaps preload using "image" instead of "object" in IE: https://stackoverflow.com/a/11103087/1996783
Working temporary solution is to put onload event directly to script element instead of object. It's sad since it works like a charm in Chrome & FF.
It turns out, object.data with css source did not load either. I don't know if it's a bug since it still can load image from to object.data.
But show must go on.
Cheers, eljuko
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.
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;
}
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"))
;
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.
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/
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?
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
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.
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>
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.
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()
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.
This snippet of code helped me to fix browser caching problems:
$("#my_image").on('load', function() {
console.log("image loaded correctly");
}).each(function() {
if($(this).prop('complete')) $(this).load();
});
When the browser cache is disabled, only this code doesn't work:
$("#my_image").on('load', function() {
console.log("image loaded correctly");
})
to make it work you have to add:
.each(function() {
if($(this).prop('complete')) $(this).load();
});
Using this JavaScript code you can check image is successfully loaded or not.
document.onready = function(e) {
var imageobj = new Image();
imageobj.src = document.getElementById('img-id').src;
if(!imageobj.complete){
alert(imageobj.src+" - Not Found");
}
}
Try out this
I had a lot of problems with the complete load of a image and the EventListener.
Whatever I tried, the results was not reliable.
But then I found the solution. It is technically not a nice one, but now I never had a failed image load.
What I did:
document.getElementById(currentImgID).addEventListener("load", loadListener1);
document.getElementById(currentImgID).addEventListener("load", loadListener2);
function loadListener1()
{
// Load again
}
function loadListener2()
{
var btn = document.getElementById("addForm_WithImage"); btn.disabled = false;
alert("Image loaded");
}
Instead of loading the image one time, I just load it a second time direct after the first time and both run trough the eventhandler.
All my headaches are gone!
By the way:
You guys from stackoverflow helped me already more then hundred times. For this a very big Thank you!
This one worked fine for me :)
$('.progress-image').each(function(){
var img = new Image();
img.onload = function() {
let imgSrc = $(this).attr('src');
$('.progress-image').each(function(){
if($(this).attr('src') == imgSrc){
console.log($(this).parent().closest('.real-pack').parent().find('.shimmer').fadeOut())
}
})
}
img.src = $(this).attr('src');
});
I'm working on a website which uses ExpressionEngine to create a list of images with img1, img2, img3 etc as the ID and creates an array with their sources imgAddresses[1], imgAddresses[2], imgAddresses[3] etc.
I'm attempting to create a function which loads the first image, then (when the first is completely loaded), load the second, third etc. The following is what I have so far:
function loadImage(counter) {
var i = document.getElementById("img"+counter);
if(counter==imgAddresses.length) { return; }
i.onload = function(){
loadImage(counter+1)
};
i.src = imgAddresses[counter];
}
document.onload=loadImage(0);
It works when refreshing the page, but not when accessing the page via the URL. As far as I can tell from research, this is because the onload event is not fired when a cached image is loaded, and refreshing the page clears the cache, whereas accessing the page via the URL does not.
Research suggests that assigning the src of the image after declaring the onload event would get around this, but it does not seem to have solved it in this case. I was thinking that this may be because the onload event is recursive in this case.
Does anyone have any ideas on how to make sure the browser is loaded a fresh copy of the image, rather than a cached version? Or whether there is a better way to write this function? Thanks for any help!
EDIT: One solution that I have found is to change the img source assignment to:
i.src = imgAddresses[counter] + '?' + new Date().getTime();
This forces the user to load a fresh copy each time, which I guess is not so much a solution, but a workaround
The only thing I can say is that you are not attaching the document.onload handler correctly. I cannot tell if it will fix your issue because image.onload is not reliable in all browsers, however the onload should be set to a function reference and that's not what you are doing.
Instead, you should have something like:
function loadImage(counter) {
//initialize the counter to 0 if no counter was passed
counter = counter || 0;
var i = document.getElementById("img"+counter);
if(counter==imgAddresses.length) { return; }
i.onload = function(){
loadImage(counter+1)
};
i.src = imgAddresses[counter];
}
document.onload = loadImage; //instead of loadImage(0);
You can tell how the browser will manage the cached resources
Take a look to HTML5 cache approach:
HTML5: The cache manifest file
This way you can avoid the browser cache for the specified resources.
Lets say I have a div, and want to inject into that div some HTML. The HTML will include 1 or more images.
Is there any way with plain JavaScript or jQuery to determine when the images have loaded?
So if I do the following, can you place an event listener onto a single element to tell when the contents, including images, is ready?:
var html = "<p>Some text <img src='image.jpg' /></p><p>Some more text <img src='image2.jpg' /></p>";
$("div.output").html(html);
The images will be different every time so I cannot preload using JavaScript image object.
One method I'm thinking of doing is running through the HTML with regular expressions or jQuery, finding all image URLs, loop through them and preload each with the image object. When all have been preloaded, then inject the HTML into the output div.
Unless you hook up an onload event to each image before it loads and count them up, there's no easy way to tell when they're all loaded.
Here's a relatively bulletproof method (demo) that uses Deferreds, tested and working in IE 6-9, Chrome 19, and Firefox 3.6-10, Opera 10.10-11.52, Android 4, and iOS 5.
First, we'll write a small jQuery plugin that returns an array of Deferreds for each element in the jQuery collection. Each Deferred will be resolved when the element loads; or rejected if the element fails to load or (optionally) takes longer than timeout seconds.
$.fn.loaded = function(opts) {
var o = $.extend({timeout:10000}, opts) // Merge default options with supplied options
, r = []; // Return value
this.each(function() {
var dfd = new $.Deferred(), el = $(this), to;
if (o.timeout) to = setTimeout(function() {
done();
dfd.reject();
}, o.timeout);
el.bind('load.dfdl', function() {
done();
dfd.resolve();
}).bind('error.dfdl', function() {
done();
dfd.reject();
});
function done() { // internal clean-up
clearTimeout(to);
el.unbind('.dfdl');
}
r.push(dfd.promise());
});
return r;
};
The timeout will guard against cases where the browser never actually fires any events. I've set the default timeout to 10 seconds here; in the real world you might want to reduce that.
Now we'll generate 10 randomly-sized placekittens to use as images in the example.
var imgs=[];
for (var i = 0; i < 10; i++) imgs.push('<img src="http://placekitten.com/' + rnd() + '/' + rnd() + '"> ');
$('#imgs').html(imgs.join());
Finally, we'll put everything together with some magic:
$.when.apply($, $('#imgs img').loaded({timeout:10000}) ).done(function() {
alert('loaded successfully');
}).fail(function() {
alert('load failed or timed out');
});
$.when creates a master Deferred that gets resolved only when all of its child Deferreds resolve, or rejects when a child rejects. It normally expects you to pass each Deferred as an argument (it does not support passing in an array of Deferreds), so we have to apply our array. (I might do $.whenall = function(dfds) { $.when.apply($,dfds); }; so that your app code has a cleaner $.whenall( $('#imgs img').loaded() )...)
Try this:
$("#preload_div").html(
'<img src="image.png" alt="preload" class="preload" width="0" height="0">'
);
The event handler can be bound to the image:
$('preload').load(function () {
var html = "<p>Some text <img src='image.jpg' /></p><p>Some more text <img src='image2.jpg' /></p>";
$("div.output").html(html);
});
Of course, you would have to incorporate an .each() for each image to loop through all images.
EDIT: On one of my AJAX websites, I preload the next image I need, so when a user clicks the 'next' button, the image that the new content needs is already cached. See http://funl.es/p/1
One method I'm thinking of doing is running through the HTML with regular expressions or jQuery, finding all image URLs, loop through them and preload each with the image object. When all have been preloaded, then inject the HTML into the output div.
var imagesLoaded = [];
var imagesErrored = [];
$('img').each(function() {
$(this).load(function() {
imagesLoaded.push($(this).attr("src"));
if( (imagesLoaded.length + imagesErrored.length) == $('img').length ) {
displayResults(imagesLoaded, imagesErrored);
}
});
$(this).error(function() {
imagesErrored.push($(this).attr("src"));
if( (imagesLoaded.length + imagesErrored.length) == $('img').length ) {
displayResults(imagesLoaded, imagesErrored);
}
});
function displayResults(imagesLoaded, imagesErrored) {
for(var i = 0; i < imagesLoaded.length; i++) {
alert(imagesLoaded[i] + " has loaded successfully.");
$('#myDiv').append("<img src='" + imagesLoaded[i] + "' />");
}
for(var i = 0; i < imagesErrored.length; i++) {
alert(imagesLoaded[i] + " did NOT load successfully.");
}
}
The above loops through all images and checks whether or not they loaded, using the load event. Using the error event, we also get a collection of all images that for whatever reason did not load correctly. After all images have been preloaded, we can then inject them onto the page in the "displayResults" function. This is based loosely on the last paragraph in your question.
However, it doesn't use regular expressions, as they are not the right tool for manipulating the DOM. Fortunately, JavaScript and jQuery provide us with the tools we need to perform DOM manipulations and parsing activities.
Finally, from your question, it sounded like you may have been interested in knowing what images loaded successfully. The above collections that are built from the load and error events will provide you with those details, should you need them.
I think you should bind the load handler after you insert the images into the html.
DEMO
//Add image
$('#result').append('<img src= "<Your_Image_URL>" width="300" height="300"/>');
//Bind handler also add condition to not bind images that was not added before.
$('#result').find('img').not('.loaded').on('load', function () {
alert('Image Loaded');
//Add code that you want to do after the image is added
}).addClass('loaded');
Also please be aware of Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load()
shortcut is to execute a function when an image (or collection of
images) have completely loaded. There are several known caveats with
this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
Reference: http://api.jquery.com/load-event/
Have you considered using the jQuery 'on' event mechanism? Using 'on' should allow you to automatically bind 'load' handlers to each image as it gets dynamically added to the container and DOM.
Link: jQuery docs for'on' function
If you're using pre 1.7 jQuery, you'll need to use the 'live' function since 'on' was added with the 1.7 release.
Link: jQuery docs for 'live' function (deprecated)
I think that there is no easy way to do that. The thing that you could do is to load all the images on a div that is hidden ( display: none ).
When you want to show the pictures you can do:
$("#myDiv").show();