Invoke function once, only after JQuery created images are loaded - javascript

I've been searching for a solution but all i'm getting is $(window).on("load", fuction(){}) which just loads the html resources.
I'm creating a variable amount of images and inserting them in a div with jquery using an each() function after the window is loaded.
$.each(footeradds, function(fad){
$("<div class=\"footerads\"><img src=\"image" + fad + ".jpg\"/></div>").appendTo(".footer");
});
I need to calculate the width of the container of these images which depends on the amount of images and their width, which they only have after they've loaded.
if i do
$(".footer img").on("load", function() {})
that function is called every time an image loads, and need it to only be called once, after ALL images have loaded.
My question is: how can i invoke a function after images created with jquery are loaded?

there is no methods for it but you can do one thing
take a variable A = count all images , then create other variable B = 1 and increment it on every image load and
check condition A == B
that condition will true when last image will called .....:)

Turn the event off after first time
$(".footer img").on("load", function() {
$( this ).off( event );
})

So i ended up using Pratik Bhalodiya's idea and made this:
var footerW = 0;
var fimgs = 0;
$(".footer img").on('load', function() {
footerW += + $(this).width();
fimgs++;
if (fimgs == $(".footerads").length){
//do stuff here
}
});
thanks for your help everyone!

You could just use a deferred for each image, and $.when to check that all are resolved etc
var p = $.map(footeradds, function(fad){
var def = new $.Deferred,
div = $('<div />', {
'class' : 'footerads'
}),
img = $('<img />', {
on : {
load : function() {
def.resolve(this);
}
},
src : 'image' + fad + '.jpg'
});
$(".footer").append( div.append(img) );
return def.promise();
});
$.when.apply($, p).then(function(images) {
// all images loaded
var images = [].slice.call(arguments);
// use images here
});

Related

Hide loading gif after ajax callback

I have a simple question but I couldn't find a clean answer. I need to load heavy images after an ajax call and I want to use an animated gif as a pre-loader. I'm using the follow code:
function loadProducts(url) {
$("#loading").show();
$('#inner').fadeOut(1).load(url + ' .product-list', function() {
$('#inner').fadeIn(1000, function() {
$("#loading").hide();
});
});
}
The #loading is hiding when the HTML is loaded .load(url + ' .product-list'. The problem is that the heavy images are still rendering on the screen and I would like to keep showing the animated .gif until the renders of the images are finished. Is there a way to know when the images on the screen are rendered?.
Thanks in advance.
You can use promises to check when all the images have loaded, and then remove the loading gif.
This creates a promise that is resolved when the image has loaded, all the promises are kept in an array, and when all promises are resolved, i.e. all images are loaded, the callback fires.
function loadProducts(url) {
$("#loading").show();
$('#inner').fadeOut(1).load(url + ' .product-list', function() {
var promises = [];
$('#inner').find('img').each(function(_, image) {
var img = new Image(),
def = new $.Deferred();
img.onload = function() {
def.resolve();
}
promises.push( def.promise() );
img.src = image.src;
if (img.complete) img.onload();
});
$.when.apply(undefined, promises).done(function() {
$('#inner').fadeIn(1000, function() {
$("#loading").hide();
});
});
});
}
You can use ImagesLoaded
Sample usage
imagesLoaded( document.querySelector('#container'), function( instance ) {
console.log('all images are loaded');
});
// selector string
imagesLoaded( '#container', function() {...});
// multiple elements
var posts = document.querySelectorAll('.post');
imagesLoaded( posts, function() {...});
Could add/remove the loader as a class? I have base 64encoded the loader, so there is no pre loader required. This also uses a closure to allow the counter to remember its value.
var imgDiv = document.getElementById("imgDiv");
imgDiv.onclick = (function () {
"use strict";
var count = 0; // init the count to 0
return function () {
count++; //count
if (count === 1) { // do something on first click
$('.img-loader-content').addClass('loader');
$('.imgDiv').load("images/img.jpg", function () {
$('.img-loader-content').removeClass('loader');
});
}
if (count > 1) {
$('.imgDiv').slideToggle(400);
}
};
})
();
You may try using Image object. E.g:
function loadImage(url) {
$("#loading").show();
var img = new Image();
img.src = url;
img.onload = function(e) {
$("#loading").hide();
//ur code to append/show the image
};
}
the most approach to this is using onLoad , so basically after the success call of ajax , invoke another call into success function :
http://www.w3schools.com/jsref/event_onload.asp
onload is most often used within the element to execute a
script once a web page has completely loaded all content (including
images, script files, CSS files, etc.).
or use native solution like this :
<img src="w3javascript.gif" onload="loadImage()">
http://www.w3schools.com/jsref/event_img_onload.asp
Also last answer of this question is very useful in your case :
Is there something similar to `$(window).load();` for executing a function after newly inserted Ajax content has finished loading?
You can do it easily by ajaxComplete callback, here check an example http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_ajax_ajaxcomplete

Temporary creation of html div using Jquery

I am trying to create div's on demand which then timeout and are then hidden and removed from the dom.
The display property of "load_bar" is set to none so that I can use the last selector to get a reference to the instance I have just created.
It is important that this solution can create several div's which are running on their own timeout clock
$(document).ready(function () {
$('#add').click(function () {
var t = Math.random()*20;
alert(t);
var destination = $('input').val();
$('#holding_pen').append('<div class="load_bar">'+destination+'</div>');
$('.load_bar:last').show().delay(t).hide().remove();
});
});
Every thing works to create divs when I remove .delay().hide().remove();
However when I add this the div is not shown at all
Create proper elements, that way you'll have a reference to the element within the function:
$(document).ready(function () {
$('#add').click(function () {
var t = (Math.random()*20)*1000,
destination = $('input').val(),
div = $('<div />', {'class':'load_bar', text: destination});
$('#holding_pen').append(div);
div.show(1).delay(t).hide(1, function() {
$(this).remove();
});
});
});
Also, hide() and show() does not work with the animation queue and subsequently not with delay() unless a duration is given, and that's why the element is never shown, delay() doesn't work and the element is hidden right away.
EDIT:
Also, remove() is not an animated method, so it doesn't work with delay(), but hide() a useful callback for that, see edited code above.
FIDDLE
The problem is because delay is used to stop jQuery animation queue, which both show and hide do not use. Therefore your div is being shown and them immediately hidden. Use setTimeout instead:
$('#add').click(function () {
var destination = $('input').val();
$('#holding_pen').append('<div class="load_bar">'+destination+'</div>');
$('.load_bar:last').show();
setTimeout(function() {
$('.load_bar:last').hide();
}, Math.random() * 20 * 1000); // * 1000 = seconds
});
Example fiddle
The delay() function only applies to actions queued on the element.
$(document).ready(function () {
$('#add').click(function () {
var t = Math.random()*20;
alert(t);
var destination = $('input').val();
$('#holding_pen').append('<div class="load_bar">'+destination+'</div>');
$('.load_bar:last').show().delay(t).queue(function( nxt ) {
$(this).hide().remove();
nxt(); // continue the queue
});
});
});
$(document).ready(function () {
$('#add').click(function () {
var t = Math.random()*20;
alert(t);
var destination = $('input').val();
$('#holding_pen').innerHTML='<div class="load_bar">'+destination+'</div>';
});
});

How to make a list of image links in jQuery?

I have a list of links. What I want to do is attach a function to each link with jQuery; when the link is clicked, the function will run, and a pair of images will be loaded into a div (img ids "img1" and "img2"). Each link has the class "link", and will load a different pair of images. So, the first link will load Image 1A and Image 1B, the second will load Image 2A and 2B, and so on. I have the images in two arrays.
However, instead of attaching the calls like I want, it ends up loading the last two images of the arrays, after the page stops loading. What's more, clicking on the links does nothing!
var loadImages =
{
init: function()
{
var links = $( ".link" );
myArray1 = [
"imgs/png/image1.png",
"imgs/png/image2.png",
"imgs/png/image3.png",
];
myArray2 = [
"imgs/jpg/image1.jpg",
"imgs/jpg/image2.jpg",
"imgs/jpg/image3.jpg",
];
for ( var i = 0, ii = links.length; i < ii; i++ )
{
$( links[ i ] ).bind( "click", loadImages.imgLoader( myArray1[ i ],
myArray2[ i ] ) );
}
},
imgLoader: function( firstURI, secondURI )
{
document.getElementById( "img1" ).src = firstURI;
document.getElementById( "img2" ).src = secondURI;
}
};
loadImages.init();
You don't bind a callback function. You execute loadImages.imgLoader and pass the result.
Normally you could just bind a callback function, but since you're using a counter variable within the callback itself, you need to be wary of the scope of i:
$(links[i]).on("click", (function(j) {
return function() {
loadImages.imgLoader(myArray1[j], myArray2[j]);
}
})(i));
A better approach would be to bind the event handler to all of the links at once and handle the image swapping without a for loop:
$('.link').click(function() {
var index = $(this).index();
$('#img1').prop('src', myArray1[index]);
$('#img2').prop('src', myArray2[index]);
});
Try Using the .each() method.
var loadImages = {
init: function(){
var myArray1 = ['imgs/png/image1.png', 'imgs/png/image2.png', 'imgs/png/image3.png'];
var myArray2 = ['imgs/jpg/image1.jpg', 'imgs/jpg/image2.jpg','imgs/jpg/image3.jpg'];
$('.link').each(function(i){
$(this).click(function(){
loadImages.imgLoader(myArray1[i], myArray2[i]);
});
});
},
imgLoader: function(firstURI, secondURI){
$('#img1').attr('src', firstURI);
$('#img2').attr('src', secondURI);
}
};
loadImages.init();
Also, you should use the keyword var so your variables don't have a global scope, and remove commas at the end of your Arrays. Visit http://api.jquery.com/each/ for more information on .each().

document ready after dom manipulation

I'm doing an application with Phonegap and I'm using a self-built slide transition to change the pages.
It works like this:
Every page is a div with 100% height and width, so if I change the Page, I set the next div right to the currently active and slide both to the left side.
Now to the Problem: the sliding works fine, but it's executed before the content of the right div is completely loaded. So the right div slides in empty, and only after a few hundred miliseconds the content will appear.
I tried it with document.ready, but as I've read this event is only executed the first time the DOM is loaded.
Does anybody know how I can wait for the DOM to be completely rendered again after I've manipulated the DOM with Javascript?
In your case, you can pick one element in the content of the next div and keep checking it with $(...).length. If the value is > 0, the DOM is loaded and you can change the page.
You may want to try this function:
Function.prototype.deferUntil = function(condition, timeLimit) {
var ret = condition();
if (ret) {
this(ret);
return null;
}
var self = this, interval = null, time = ( + new Date());
interval = setInterval(function() {
ret = condition();
if (!ret) {
if (timeLimit && (new Date() - time) >= timeLimit) {
// Nothing
} else {
return;
}
}
interval && clearInterval(interval);
self(ret);
}, 20);
return interval;
};
Usage:
(function() {
console.log('Next page loaded');
}).deferUntil(function() {
return $('#nextDiv').length > 0;
}, 3000);
The above example will check the div that has id="nextDiv" in every 20ms (not longer than 3 seconds). When the div is loaded, it will show 'Next page loaded' in the console.
You can try on this fiddle
There is a DOMNodeInserted event that is supposed to work like document.ready but for individual DOM nodes. But it is deprecated and has lots of issues. StackOverflow users found a good alternative to it that works quite well in all mobile browsers: Alternative to DOMNodeInserted
Here is a function that will trigger a callback once all images matching a jquery selector have finished loading
Js Fiddle Sample
//css
input {width: 420px;}
//html
<div id="container"></div>
<input type="text" value="http://goo.gl/31Vs" id="img1">
<br><input type="text" value="http://wall.alafoto.com/wp-content/uploads/2010/11/Fractal-Art-Wallpapers-09.jpg" id="img2">
<br><input type="text" value="http://pepinemom.p.e.pic.centerblog.net/ssg8hv4s.jpg" id="img3">
<br><input type="button" value="Load images" name="loadImages" id="btn">
<div id="message"></div>
//javascript
//Call a function after matching images have finished loading
function imagesLoadedEvent(selector, callback) {
var This = this;
this.images = $(selector);
this.nrImagesToLoad = this.images.length;
this.nrImagesLoaded = 0;
//check if images have already been cached and loaded
$.each(this.images, function (key, img) {
if (img.complete) {
This.nrImagesLoaded++;
}
if (This.nrImagesToLoad == This.nrImagesLoaded) {
callback(This.images);
}
});
this.images.load(function (evt) {
This.nrImagesLoaded++;
if (This.nrImagesToLoad == This.nrImagesLoaded) {
callback(This.images);
}
});
}
$("#btn").click(function () {
var c = $("#container"), evt;
c.empty();
c.append("<img src='" + $("#img1").val() + "' width=94>");
c.append("<img src='" + $("#img2").val() + "' width=94>");
c.append("<img src='" + $("#img3").val() + "' width=94>");
evt = new imagesLoadedEvent("img", allImagesLoaded);
});
function allImagesLoaded(imgs) {
//this is called when all images are loaded
$("#message").text("All images loaded");
setTimeout(function() {$("#message").text("");}, 2000);
}
You could use jQuery ajax to load the content, and on success run a function with the slide.
$("#page1").load('page2.html', function() {
//do your custom animation here
});
Althoug I'm not completely sure how you're loading the content. Is it static (Already there but just not visible?) Or is it loaded with ajax?
EDIT: You could just do a small .delay() or setTimeout with a few millisec, and then animate the sliding.
I had a similar problem making a masonry site responsive. I use window.onload which waits for all elements to complete loading before initialising masonry.js. I also placed the window.onload inside .onchange function and it fired everytime the viewport resized.
I am sure applying similar principles will solve your problem.
try once
$(window).bind('load',function(){
//code
});
Maybe you can set an event on your div.
myDiv.onafterupdate = myHandler;
function myHandler() {
// Do here what you want to do with the updated Div.
}
Does this help you?
In jquery you could use $() just after your DOM manipulation code.
$(function(){
//code that needs to be executed when DOM is ready, after manipulation
});
$() calls a function that either registers a DOM-ready callback (if a function is passed to it) or returns elements from the DOM (if a selector string or element is passed to it)
You can find more here
difference between $ and $() in jQuery
http://api.jquery.com/ready/

How to know when all images inside a specific "div" are loaded?

Part of my HTML page is the following div:
<div id="images_wrapper">
<img ... />
<img ... />
<img ... />
...
</div>
Initially, this div is hidden, and I show it only when all images are loaded:
$(window).load(show_images_wrapper);
However, if I'm not mistaken, show_images_wrapper will be called only when all the page is loaded. I would like show_images_wrapper to be called as soon as all images inside images_wrapper has been loaded, and don't wait until all the page is loaded.
I tried:
$("#images_wrapper").load(show_images_wrapper);
but it didn't work.
How should I do this?
Set up a counter to the quantity of the images using the length[docs] property, that is decremented as the images load.
var imgs = $("#images_wrapper > img").not(function() { return this.complete; });
var count = imgs.length;
if (count) {
imgs.load(function() {
count--;
if (!count) {
$("#images_wrapper").show();
alert('all done');
}
});
} else {
$("#images_wrapper").show();
}
The the not()[docs] method is removing from the matched set the images where their .complete property is true. This means the image has already downloaded, and was perhaps cached by bhe browser.
Of course the load()[docs] method fires as each image finishes loading.
Example: http://jsfiddle.net/uhmAR/1/
EDIT: Changed it so that the container will show if all the images happened to be cached.
EDIT:
Another variation on the above is to bind the .load() to all the images, and use the filter()[docs] method to get the ones that are .complete, and just manually invoke the .load() on them.
This removes the need for the if/else statement.
var imgs = $("#images_wrapper > img")
var count = imgs.length;
imgs.load(function() {
count--;
if (!count) {
$("#images_wrapper").show();
alert('all done');
}
}).filter(function() { return this.complete; }).load();
Example: http://jsfiddle.net/uhmAR/3/
I wrote a jQuery plugin that can do this.
$('#images_wrapper').waitForImages(function() {
// Done.
});
Alternatively,
var images = $('#images_wrapper img'),
imagesLength = images.length;
images.load(function() {
if ( ! --imagesLength) {
// Done.
}
});

Categories

Resources