How to know when all images from document did load in Javascript? - javascript

I'm realoading a <div> content with an ajax function with Ruby On Rails i'm realoading a partial into a div and i want to know hot to know when all images have loaded because now i have this:
$(document).ready(function(){
$("img").load(function(){
alert("ok?");
});
});
but with this i keep getting an alet for every image on this partial....
i don't know iuf there's a selector like $(allimgs) or something like that, what do i have to do to catch when all images are loaded?
Many Thanks.

If you wish to ensure that all images loaded without errors you have to roll your own. If not you can use .load like already shown which will fire when the browser is done loading assets.
To roll your own, do something like this:
$(document).ready(function(){
var imgs = $("img"), cnt = imgs.length;
imgs
.load(function(){
if(!--cnt) {
/* all images loaded */
}
})
.error(function() { /* whoops an image failed to load */});
});

Will do something like:
First we count how many imgs we have in our page, every img load will decrement count by 1, and when it is 0, means that all images are loaded.
$(document).ready(function(){
var allimgs = $("img");
var count = allimgs.length;
allimgs.load(function(){
if(--count == 0) {
alert("all images are loaded");
}
})
});
**EDITED**
If the browser is caching the images, try this instead:
$(document).ready(function(){
var allimgs = $("img");
var count = allimgs.length;
$("img").one('load', function() {
count--;
if(count == 0) {
alert("all images are loaded");
}
}).each(function() {
if(this.complete) $(this).load();
});
});

You might need to use the image loaded plugin, to ensure that your code deals with cached images etc. https://github.com/paulirish/jquery.imgloaded
and then your code
var total_number_of_images = $("img").length;
var loaded_images = 0;
$("img").load(function(){
loaded_images++;
if loaded_images = total_number_of_images {
// do something ...
} });

Related

how to get loaded callback CSS files, JS files, font files with Jquery

I am making javascript for Page loader.
This is part of it.
$('img').each(function () {
var src = $(this).attr('src');
$('<img>').attr('src', src).on("load", function () {
alert("Loaded one of thme");
});
});
I can get callback from this, img files are OK.
But how to get callback of CSS files and JS files, especially font files?
regard.
/////////////////// add My resolve at 5/14
I resolved like this. Is this for just my case.
In HTML, Put link tags for fonts. Any where OK.
<link as="font" href="/fonts/font01.woff">
<link as="font" href="/fonts/font02.woff">
<img src="/img/img01.jpg">
<img src="/img/img02.jpg">
Next JS.
var fonts_length = $('link[as="font"]').length;
var resouce_num = $('img').length + fonts_length;
$('img').each(function () {
var src = $(this).attr('src');
$('<img>').attr('src', src).on("load", function () {
loadStatus++;
});
});
$('link[as="font"]').each(function () {
var href = $(this).attr('href');
$(document).load(href, function () {
loadStatus++;
});
});
And Compare loadStatus(loaded files count) and resouce_num(need load files count).
Is this correct using? I do not know, but working well, should be alright.
how do you think? If you have better way or found my mistake, tell me please.
And B--rian! please fix my english too!!
/////////////////// add Other nice way at 5/14
I found other one.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#Stylesheet_load_events
<script>
var myStylesheet = document.querySelector('#my-stylesheet');
myStylesheet.onload = function() {
// Do something interesting; the sheet has been loaded
}
myStylesheet.onerror = function() {
console.log("An error occurred loading the stylesheet!");
}
</script>
<link rel="stylesheet" href="mystylesheet.css" id="my-stylesheet">
important Note:
Note: The load event fires once the stylesheet and all of its imported
content has been loaded and parsed, and immediately before the styles
start being applied to the content.
This way is much simple I thought.
But today I am so tired...later I will try.
/////////////////// add My trying at 5/15
I tried above one.But "onload" function is not working well.
It does not send callback after loaded... Chrome has problem? or My mistake?
Or this way is not nice for Page loader, I thought.
Cos, Even If that is working well, Can not check each loading of font files.
I think, Page loader should tell a temporary percentage of progress with a progress bar or something.
So, Now I am back to my sample script.
CSS files:
// create a nodeElement
var node = document.createElement('link');
node.rel = 'stylesheet';
node.href = url;
document.head.insertBefore(node, document.head.firstChild);
// try to set load callback
node.onload = function () {
CSSDone('onload listener');
// do your callback
}
if (node.addEventListener) {
node.addEventListener('load', function() {
CSSDone("DOM's load event");
// do your callback
}, false);
}
node.onreadystatechange = function() {
var state = node.readyState;
if (state === 'loaded' || state === 'complete') {
node.onreadystatechange = null;
CSSDone("onreadystatechange");
// do your callback
}
};
var cssnum = document.styleSheets.length;
var ti = setInterval(function() {
if (document.styleSheets.length > cssnum) {
CSSDone('listening to styleSheets.length change');
// do your callback
clearInterval(ti);
}
}, 10);
you can see this link for reference
JS files:
// create a nodeElement
var body = document.getElementsByTagName('body')[0];
var node = document.createElement('script');
node.setAttribute('type', 'text/javascript');
node.setAttribute('src', url);
body.appendChild(node);
// try to set load callback
if(node.onload){
node.onload = function() {
// do your callback
}
}else{
// for some not support onload
node.onreadystatechange = function() {
// do your callback
}
}
font files:
document.fonts.onloadingdone = function() {
// do your callback
}
how to check font files loaded can refer this link
emm,I am New contributor.if there are some wrong can reply me.thanks
If you are trying to print out the contents of a .css or .html file, you can do this with php:
<?php
$myfile = fopen("your_file", "r") or die("Unable to open file!");
echo fread($myfile,filesize("your_file"));
fclose($myfile);
?>

Waiting for multiple iFrames to load before executing function

Forgive my naivety, this probably is quite obvious, I just can't see it now.
Please tell me what is wrong with the following code:
$('#iframe1').load(function(){
$('#iframe2').load(function(){
alert('loaded!');
});
});
The idea is to wait until both iframes have fully loaded, then alert "loaded" - of course this is a simplified example for the sake of stack.
The script sits in script tags at the end of the body of the html doc.
#Quertiy answer is perfectly fine, but not very jQuery-ish. It is hard-coded for 2 iframes only.
The beauty of jQuery is that you can make it work for the most number of people, with as little friction as possible.
I've advised a very simplistic plugin that does nearly what is present on that answer, but in a more open way. It not only works on iframes, but also on images, audio, video and whatever has a onload event!
Without further due, here's the code:
(function($){
$.fn.extend({allLoaded: function(fn){
if(!(fn instanceof Function))
{
throw new TypeError('fn must be a function');
}
var $elems = this;
var waiting = this.length;
var handler = function(){
--waiting;
if(!waiting)
{
setTimeout(fn.bind(window), 4);
}
};
return $elems.one('load.allLoaded', handler);
}});
})(window.jQuery);
It works by adding a load handler to every element in that selection. Since it is a plugin, you can use in whatever way you decide to use it.
Here's an example, that loads 30 random images:
//plugin code
(function($){
$.fn.extend({allLoaded: function(fn){
if(!(fn instanceof Function))
{
throw new TypeError('fn must be a function');
}
var $elems = this;
var waiting = this.length;
var handler = function(){
--waiting;
if(!waiting)
{
setTimeout(fn.bind(window), 4);
}
};
return $elems.one('load.allLoaded', handler);
}});
})(window.jQuery);
$(function(){
//generates the code for the 30 images
for(var i = 0, html = ''; i < 30; i++)
html += '<img data-src="http://lorempixel.com/g/400/200/?_=' + Math.random() + '">';
//stuffs the code into the body
$('#imgs').html(html);
//we select all images now
$('img')
.allLoaded(function(){
//runs when done
alert('loaded all')
})
.each(function(){
//the image URL is on a `data` attribute, to delay the loading
this.src = this.getAttribute('data-src')
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id="imgs"></div>
Your problem, as said before many times, is that you have a load event attached to your iframe. That event is fired everytime the content change.
After that, you set a new event on #iframe2. When it's content changes, it will fire events left and right, above and beyound what you wish!
The best aproach is to keep track of which ones you loaded or not. After all have been loaded, you simply run the function.
The problem is that you're waiting until #iframe1 loads before you attach a handler for #iframe2 loading. So if #iframe2 loads first, you'll never get your callback.
Instead, watch the load event on both of them and track which ones you've seen:
var seen1 = false,
seen2 = false;
$('#iframe1, #iframe2').load(function(){
if (this.id == "iframe1") {
seen1 = true;
} else {
seen2 = true;
}
if (seen1 && seen2) {
alert('loaded!');
}
});
Why do you expect 2nd iframe to load after the first one?
~function () {
var loaded = 0;
$('#iframe1, #iframe2').load(function (){
if (++loaded === 2) {
alert('loaded!');
}
});
}()

using ajax + jquery's after() function, now wait for images to load

Hi I am using ajax and json for infinite scrolling and then I create a string of html to add to my webpage and call it with jQuery's after() function.
$('.product-panel:last').after(productHTML);
Now I need to wait for all the images from my new productHTML string to load and then call another javascript function I created to do some formatting.
I tried like
$('.product-panel:last').after(productHTML).promise().done(function(){
doMoreStuff();
});
it doesn't work. Can someone help? Thanks
EDIT: after following adeneo's code this is my final result and it works flawlessly.
var productLength = $('.product-panel').length-1;
$('.product-panel:last').after(productHTML);
var images = $(".product-panel:gt("+productLength+")").find('img');
var promises = [];
images.each(function(idx, img) {
var def = $.Deferred();
img.onload = def.resolve;
img.onerror = def.reject;
if ( img.complete ) def.resolve();
promises.push(def.promise());
});
$.when.apply($, promises).done(function() {
productHeight();
});
It's not quite that easy, you'll have to find all the inserted images and wait for them to load individually, something like this
var images = $('.product-panel:last').after(productHTML).next().find('img');
var promises = [];
images.each(function(idx, img) {
var def = $.Deferred();
img.onload = def.resolve;
img.onerror = def.reject;
if ( img.complete ) def.resolve();
promises.push(def.promise());
});
$.when.apply($, promises).done(function() {
// all images loaded
});
It seems like this is working for me
where I generate my html from the json i put an imageCount variable,
and then have this counter for imagesLoaded so far set to 0. Then $(img).load() function is getting called after each image load and then I just keep checking to see if imageCount and imagesLoaded is the same.
var imagesLoaded = 0;
$('.product-panel:last').after(productHTML);
$('img').load( function() {
imagesLoaded++;
if(imagesLoaded == imageCount){
console.log("all images loaded");
productHeight();
}
});

jQuery each not functioning correctly

I have a slider with 10 slider elements. However, only 7 out of 10 elements are rendered, given my data structure contains 20 sets. The site is hosted here
The code in question
function populateCarousell(cdata) {
var x = 0; //debug
jQuery(".wslide-slides .wslide-slide").each(function() {
var single = cdata.shift();
var jcurrSlide = jQuery(this);
jcurrSlide.find(".wslide-caption-text").text(single.title);
jcurrSlide.find("a").attr('href', "https://carousell.com/p/" +single.id);
jcurrSlide.css({'background-image':Base64.decode('dXJs')+'('+single.primary_photo_full_url+')'});
jcurrSlide.css({'background-image':'contain'});
jcurrSlide.css({'background-position':'50% 50%'});
jcurrSlide.css({'background-repeat': 'no-repeat'});
x++; //debug
jcurrSlide.find(".wslide-slide-inner2").removeAttr('style').find("img").css({'display':'none'});
});
alert(x); //Outputs 7
}
which is activated by (to ensure page fully loaded)
function caroDataCallback(data) {
if(document.readyState != "complete" ) {
setTimeout(function() { caroDataCallback(data); }, 2000);
}
else{
populateCarousell(data);
}
}
Upon examination in Chrome, the results is
That's because your page is not fully loaded when you call populateCarousell(cdata) function in your javascript file. Try instead of using $(document).ready(), use the $(document).load() to make sure all the images are loaded before you initiate your carousel.
Update: Use $(window).on('load', function() { .. }); instead.
Hope this helps.

jQuery pre -loader ie-6/7 issue

I got this jQuery pre-loading script running on a index.html page loading about 10Mb before redirecting to a other page.
It works fine in IE8/9 FF3+ and Chrome.
But it does not seem to work in IE6/7, it seems to start and run but never fires the last part.
Working example: -removed-
Anyone knows why it gets stuck on 75/76 files loaded in ie6/7?
<script src="js/jquery-1.7.1.min.js"></script>
<script>
(function($) {
var imgList = [];
$.extend({
preload: function(imgArr, option) {
var setting = $.extend({
init: function(loaded, total) {},
loaded: function(img, loaded, total) {},
loaded_all: function(loaded, total) {}
}, option);
var total = imgArr.length;
var loaded = 0;
setting.init(0, total);
for (i = 0; i < imgArr.length; i++) {
imgList.push($("<img />")
.load(function() {
loaded++;
setting.loaded(this, loaded, total);
if(loaded == total) {
setting.loaded_all(loaded, total);
}
})
.attr("src", imgArr[i])
);
}
}
});
})(jQuery);
$(function() {
$.preload([
"http://www.erikderuiter.nl/images/300x300-transparent.png",
"http://www.erikderuiter.nl/images/300x300.png",
"http://www.erikderuiter.nl/images/300x600.png",
"http://www.erikderuiter.nl/images/600x300.png",
"http://www.erikderuiter.nl/images/600x600.png",
"http://www.erikderuiter.nl/images/900x300.png",
], {
init: function(loaded, total) {
$("#indicator").html("Files: "+loaded+"/"+total);
},
loaded: function(img, loaded, total) {
$("#indicator").html("Files: "+loaded+"/"+total);
$("#full-screen").append(img);
},
loaded_all: function(loaded, total) {
$("#indicator").html("Loading: Done!");
window.location.replace("http://www.erikderuiter.nl/somepage.html");
}
});
});
</script>
<div id="indicator"></div>
Any other tips or best practices to preload images on a page are welcome as well of course.
You need to also test if the image is already cached.
var img = new Image();
img.src = "foo.jpg";
if (img.complete || img.readyState === 4) {
// image is cached
}
else {
$(img).bind("load error onreadystatechange",function(e){
// image is loaded
});
}
If there is a 404 error on one of the images, you will need to catch that with a setTimeout and clearTimeout.
Edit: Just a note before i get bombarded for using .bind: I still use .bind in plugins for backwards compatibility.
Here's an example of the above method: https://github.com/tentonaxe/jQuery-preloadImages/blob/master/jquery.preloadimages.js
Edit again: After reading this over again, I'm not sure if caching is the problem you are having at the moment. It's definitely something that may come up later if you don't check for it, but it may not be related to the problem you are having.

Categories

Resources