I'm currently working on a page that loads several images sequentially using setTimeout and onLoad. Basically when an image finishes loading, onLoad is triggered, which starts another image loading via a setTimeout call. Unfortunately, if an image load is interrupted for some reason, such as a subsequent ajax call, onload is never called and any images left to be loaded are not loaded. Is there any way in javascript to detect this situation? I've attempted to hook into onError and onAbort (on the image tag) and neither of these seem to be called.
queuePhotos: function(options)
{
this.init();
this.photo_urls = options.photo_urls;
this.photo_size = options.size
this.max_width = options['max_width'];
this.max_height = options['max_height'];
this.containers = options['containers'];
yd = YAHOO.util.Dom;
photo_tags = yd.getElementsByClassName('image_stub', 'div');
for( i in photo_tags )
{
//create new image
photo = new Image();
this.queue.push( { tag: photo_tags[i], photo: photo } );
}
setTimeout(photoLoader.prepareNextPhoto, 1);
},
prepareNextPhoto: function()
{
photo_tag_and_image = photoLoader.queue.shift();
if(photo_tag_and_image)
{
YAHOO.util.Event.addListener(photo_tag_and_image.photo, "load", photoLoader.appendPhoto, photo_tag_and_image, photoLoader);
photo_tag_and_image.photo.src = photoLoader.photo_urls[photo_tag_and_image.tag.id];
}
},
An AJAX call shouldn't cancel the loading of images. There could be something else going on here...
I don't think that you can readily detect the load failure of an image. You could fire off a timer with a certain timeout threshold to deem an image as failed if your timeout timer expires before you get the load event from the image.
You can call onload and onerror
myImage.onload = function(){ alert("loaded"); };
myImage.onerror = function(){ alert("whoops"); };
Eric
Related
I have a request calling up a bunch of images like so:
<a href='www.domain1.com'><img src='../image/img1.png' onerror='imgError(this);'/></a>
<a href='www.domain2.com'><img src='../image/img2.png' onerror='imgError(this);'/></a>
The problem is when the call is made some of the images (~20%) are not ready yet. They need another second.
So in js or jquery what I would like to do is on error get the images that failed, wait 1 second, then try to load those failed images again. If they fail on the 2nd try -- oh well, Im okay with that. But Im not doing this correctly... Should I not be calling a timeout inside of another method in js?
function imgError(image) {
image.onerror = "";
image.src = image;
setTimeout(function () {
return true;
}, 1000);
}
Add a cache breaker.
function imgError(image) {
image.onerror = null;
setTimeout(function (){
image.src += '?' + +new Date;
}, 1000);
}
(This assumes your image URL doesn't already have a query string, per the example. If it does, a little more work is obviously required.)
I try to place multiple images in my HTML, and manipulate them when they are all loaded.
But onload event is not firing in IE9 sometimes.
I set some console debug message, and found that if the readyState of image is loading when I register onload event, onload event will not fire.
Code snippet is as follows:
var loaded = function () {
// increate counter to make sure all images are loaded or not
};
var thumbnails = $('img');
thumbnails.each(function () {
console.log('this.readyState:'+this.readyState)
if (this.complete) {
loaded();
} else {
this.onload = loaded;
}
});
P.S. I don't want to use window.onload method, because my script may be a plugin, it will be insert someone's page.
try re-assigning the image source (src) to trigger the event, like:
var thumbnails = $('img');
thumbnails.each(function () {
var img = $(this);
console.log('this.readyState:'+this.readyState)
if (this.complete) {
loaded();
} else {
this.onload = loaded;
}
img.attr('src', img.attr('src'));
});
To make sure a document is ready before doing stuff, i do the following :
(function() {
var interval = window.setInterval(function() {
if("complete" === document.readyState) {
window.clearInterval(interval);
// Some stuff
}
}, 10);
})();
If somewhere in my code i create an image from JavaScript like this :
var image = new Image();
image.onload = function() {
// Some other stuff
};
image.src = 'some_url';
Will the check I perform on document.readyState also wait for "image" to be loaded, or will it just wait for the images present in the HTML code, and only those, to be loaded ?
Thanks in advance.
You don't need your setInterval.
From the MDN :
The load event fires at the end of the document loading process. At
this point, all of the objects in the document are in the DOM, and all
the images and sub-frames have finished loading.
You can simply do this for the statically included images :
window.onload = function() {
// Some stuff
};
As this doesn't take into account the images you create later, you may do this :
window.onload = function() {
var image = new Image();
image.onload = function(){
// Some stuff
};
image.src = 'some_url';
};
In jquery document.ready() function is call when entire html page is ready or we can say bind (in technical terms).
You should try with increasing Interval time. or include image load callback for performing the stuff.
I want to create an alert box after an image is loaded, but if the image is saved in the browser cache, the .onload event will not be fired.
How do I trigger an alert when an image has been loaded regardless of whether the image has been cached or not?
var img = new Image();
img.src = "img.jpg";
img.onload = function () {
alert("image is loaded");
}
As you're generating the image dynamically, set the onload property before the src.
var img = new Image();
img.onload = function () {
alert("image is loaded");
}
img.src = "img.jpg";
Fiddle - tested on latest Firefox and Chrome releases.
You can also use the answer in this post, which I adapted for a single dynamically generated image:
var img = new Image();
// 'load' event
$(img).on('load', function() {
alert("image is loaded");
});
img.src = "img.jpg";
Fiddle
If the src is already set then the event is firing in the cached case before you even get the event handler bound. So, you should trigger the event based off .complete also.
code sample:
$("img").one("load", function() {
//do stuff
}).each(function() {
if(this.complete || /*for IE 10-*/ $(this).height() > 0)
$(this).load();
});
There are two possible solutions for these kind of situations:
Use the solution suggested on this post
Add a unique suffix to the image src to force browser downloading it again, like this:
var img = new Image();
img.src = "img.jpg?_="+(new Date().getTime());
img.onload = function () {
alert("image is loaded");
}
In this code every time adding current timestamp to the end of the image URL you make it unique and browser will download the image again
I have met the same issue today. After trying various method, I realize that just put the code of sizing inside $(window).load(function() {}) instead of document.ready would solve part of issue (if you are not ajaxing the page).
I found that you can just do this in Chrome:
$('.onload-fadein').each(function (k, v) {
v.onload = function () {
$(this).animate({opacity: 1}, 2000);
};
v.src = v.src;
});
Setting the .src to itself will trigger the onload event.
Using the following script to add an event listener, basically it says "Hide the #curtain div (whole page) until .bgImage is downloaded, then wait 1500ms and fade everything in"
My question is this - sometimes due to server lag or glitchy triggering of .bind("load") the page is not fading in. How can I add some kind of timeOut to the effect so that it triggers after X miliseconds if the .bind("load) event is not triggered?
$(document).ready(function(){
// #curtain DIV begins hidden then fades in after .bgImage (curtain) is loaded - prevents "ribbon" loading effect in Chrome
$('#curtain').hide();
$(".bgImage").bind("load", function () {$('#curtain').delay(1500).fadeIn(); });
});
$(".bgImage").bind("load", function () {
setTimeout(function() {
$('#curtain').delay(1500).fadeIn();
}, 500);
});
if you want to add a delay to the fadeIn animation this will help. cheers
What you could do is this:
var url = $('.bgImage').attr('src');
var img = new Image();
img.onload = function() {
$('#curtain').delay(1500).fadeIn();
};
img.src = url;
In my experience, as long as you set up the "onload" property of an "Image" object before you set the "src", the handler will always run.
edit — if you wanted to be sure that the thing would eventually fade in, then you could do something like this:
var allDone = false;
var url = $('.bgImage').attr('src');
var img = new Image();
img.onload = function() {
if (!allDone) {
$('#curtain').delay(1500).fadeIn();
allDone = true;
}
};
setTimeout(img.onload, 5000); // show the hidden stuff after 5 seconds, image or no image
img.src = url;
You can use something like this:
var timeout;
$(".bgImage").bind("load", function(){
clearTimeout(timeout);
// do something here
});
timeout = setTimeout(function(){
$(".bgImage").unbind("load");
// do something else instead
}, 10000);
and maybe also handle errors:
$(".bgImage").bind("error", function(){
// do something else here as well
});
UPDATE: I added code to cancel your timeout when the load does happen. Those two functions has to be able to cancel out each other.
Try adding this to your css:
#curtain {
display:none;
}
and using this in your document read():
$(.bgImage).load(function() {
$('#curtain').fadeIn(3000);
});