Only apply jQuery waterfall 'reflow' after the images have loaded - javascript

i am using jQuery waterfall for my grid style display.
To stop the common images overlapping issue i have wrapped the waterfall method in a .load() function such as:
$(window).load(function(){
$('#buildcontainer').waterfall({
colMinWidth: 260,
defaultContainerWidth: 1000,
autoresize: true
});
});
The images overlap because the waterfall function is called before the images have fully loaded there for their height cannot be determined. Wrapping the function in the load function prevents this.
The problem is, i have a button which loads more database results via ajax and appends them to the container.
When the items are appended, the images overlap. jQuery waterfall comes with a 'reflow' function which re sorts all of the items inside the container.
In my ajax success i run it like so:
success: function(html) {
$("#buildcontainer").append(html).waterfall('reflow');
}
The issue i see here is that the images are being appended, and then the waterfall function is being called but the images are not yet fully loaded.
Is there a way i can only run the waterfall('reflow') after the items have fully loaded. In the same style as the:
$(window).load(function(){
});
I have tried wrapping the line where the items are appended into this function, i have also tried just appending the items and then applying the reflow inside a .load function but both of these dont append any items.
Any help / ideas on what to try next? Thanks!
Note: The images dont overlap in FF, but do in chrome and safari.
Thanks!

Have a look at the imagesLoaded library / jquery plugin: http://imagesloaded.desandro.com/

Try this in your success function:
success: function(html) {
$("#buildcontainer").append(html);
var loaded = 0,
imgs = $("img"),
totalImgs = imgs.length;
imgs.load(function() {
++loaded;
// Check if all images have loaded
if (loaded === totalImgs) {
// Run waterfall
$('#buildcontainer').waterfall('reflow');
}
});
}

Assuming all the images are being added in here:
success: function(html) {
$("#buildcontainer").append(html).waterfall('reflow');
}
Then, you can do the following to monitor them all after adding them:
success: function(html) {
function checkCnt() {
if (remainingCnt === 0) {
$("#buildcontainer").waterfall('reflow');
}
}
var remainingCnt = $("#buildcontainer").append(html)
.find("img")
.filter(function() { return !this.complete; })
.load(function() {
// one more is loaded now, see if they are all loaded
--remainingCnt;
checkCnt();
}).length;
checkCnt();
}

Related

Function initiated in ajax call only works one time

I am using a plugin called mixitup that makes sure I have a masonry layout with some animations.
The masonry comes from another page which gets loaded in through ajax. I have a search bar which searches for photos and returns them from the masonry page. The issue is this works the first time but not the second time and so on. Why is that?
My code for the search input:
$('.photosearchinput').keyup(function(e) {
clearTimeout($.data(this, 'timer'));
if (e.keyCode == 13){
searchphotos(true);
}else{
$(this).data('timer', setTimeout(searchphotos, 500));
}
});
My function that makes the ajax call and which has my masonry mixitup function in the complete:
function searchphotos(force) {
var photoform = $(".photosearchform").serialize();
$.ajax({
type:'post',
url:"includes/photoresults.php",
data:({photoform: photoform}),
success:function(data){
$( "#searchphotos" ).show().empty().append( data );
},
complete:function(){
// I tried calling #masongallery from the body (body always stays the same and does not get added again)
$('body').find('#masonrygallery').mixItUp({
selectors: {
target: '.tile',
filter: '.filter',
sort: '.sort-btn'
},
animation: {
animateResizeContainer: false,
effects: 'fade scale'
}
});
}
});
}
I thought maybe the DOM gets reloaded and jquery cannot find the element #masonrygallery anymore so I tried calling it like this: $('body').find('#masonrygallery').mixItUp({ the body never gets reloaded so maybe this would fix it, but no. I get the same result. It works the first time, but not any time after that.
I have made a video to show what I mean: https://streamable.com/njy6x7
I get no errors in my console. And when I look in the network tab to see what ajax is retrieving, I see the correct images, they are just not visible as masonry layout (in fact they are not visible on the page at all but this is because of the plugin).

jQuery load() and how to know when dynamically added images have finished loading?

With jQuery 3.3.1 load() I am adding content with a few HTML img tags inside and then I want to check the viewport for visible elements AFTER
all the pictures have finished loading.
My problem is that I am unable to know when the dynamically added pictures have been fully loaded in my <div id="#content">.
This is my JS code for loading the new content:
// Replace the #content with content from a file containing a few `img` tags
$("#content").load("image-list.html", function() {
console.log("Now my images have fully loaded???");
});
I have tried this:
// Show me which event is triggered after load()
$(window).on("load resize scroll", function(event) {
console.log(event);
});
// Check if I can get when the images have fully loaded
$("img").on("load", function() {
console.log("Load image event???");
});
I also have tried some black-magic with waiting X milliseconds and looping through all image tags but this is for sure NOT the way to go as it is obscure!
The result of the above is:
I get the Now my images have fully loaded message immediately after I have loaded the file but it does not wait to show the message to after everything has been rendered
I do not get the console.log(event) message at all
I do not get any Load image event messages at all
I am debugging this by slowing down the speed with Chromes network option:
The reason your Load image event??? log is not firing, because you are not late binding the event handler on the images, thus, the on function will not fire for images that were added dynamically to your html.
To late bind, you can modify that function the following way:
$(document).on('load', 'img', function() {
console.log("Load image event???");
});
But if an image takes a long time to load, and you are trying to do something after all the new images were loaded which came from your image-list.html, I suggest something like the below approach:
Try putting the load listener, inside the callback function of the load method, like this:
$("#content").load("image-list.html", function() {
var numberOfImages = jQuery("#content img").length;
$("#content img").one('load', function() {
numberOfImages--;
if (numberOfImages == 0) {
console.log("All the images have loaded");
}
});
$("#content img").each(function() {
if (jQuery(this)[0].complete) jQuery(this).trigger("load");
});
});
You just have to be careful, as apparently, the load event will not fire, if the image you are loading was already cached, and loaded from the cache. There are workarounds for that too.
EDIT: The above code will take care for the situation where the images are loaded from cache also.

How to append data from another PHP file

I am using jQuery waterfall as a responsive grid layout.
I was using masonry, and had a load more button function but I am modifying what I have and trying to understand what the code does.
So for the load more button I have this:
$(document).ready(function(){
var pageIndex = 1;
$('#loadmorebuilds-div').click(function() {
$("#buildcontainer").append('<div class="blogresults"><br><br></div>');
});
});
In theory, this works fine. However I have another page which loads all of the extra content from my database.
This is what have used before:
$(document).ready(function(){
var pageIndex = 1;
$('#loadmorebuilds-div').click(function() {
$('.countvar').detach();
$('#buildcontainer').imagesLoaded( function(){
$.ajax({
url: 'includes/loadmorebuilds.php?type=' + type + '&pageIndex=' + pageIndex,
success: function(html) {
var el = $(html);
$("#buildcontainer").append(el);
$("#loadmorebuilds-div").stop().fadeOut();
pageIndex++;
var rowCount = $(".countvar").html();
if (rowCount < 16) {
$('#loadmorebuilds-div').remove();
$('.countvar').detach();
} else {
$('.countvar').detach();
}
}
});
});
});
});
This also works, and does load the new data but seems to load the data and not fit it into the grid properly. One of the results sit underneath the others, but the other ones overlap in the top left and sit underneath others etc.
I can manually append as many divs using the first example and it works fine.
Also when using the second example the items seem to refresh and appose to just the new data being loaded.
In my eyes, its to do with this:
success: function(html) {
var el = $(html);
Is there a better way to get the content from the requested page and simply append it back to the div.
The page that is called simply run a query on the database and echoes out the divs in a foreach statement. So the div layout would just be e.g.
<div class="blogresults"></div>
Any ideas on this one?
on the ajax success event you should do this:
success: function(data) {
$('blogresults').html(data);
}
Searched arround the examples in the waterfall folder and it seemed to use a 'reflow' feature with works the same (i guess) and the masonry 'reload'.
Tried it as
$("#buildcontainer").append(html).waterfall('reflow');
And it works :)

How to load a jQuery function only after the document finish loading

Strange situation:
I am building a menu bar using jQuery and CSS.
In my JavaScript file, I have an on-ready function like so:
$(document).ready(function(e) {
mark_active_menu();
}
and...
function mark_active_menu() {
var elementWidth = $("nav li").width();
alert(elementWidth);
}
For some reason, even BEFORE all the document finish loading, I'm getting the alert message with an incorrect width. Only when I release the message, the rest of the document loads and I'm getting the right width as it should be.
Why my function is being called BEFORE all the document finish loading?
Is there a way to load the function only AFTER a certain element done loading (Example: the nav element)?
You can use window.load, it will be triggered after all the resource have completed loading.
$(window).load(function(e) {
mark_active_menu();
});
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, Reference
All the current solutions are just treating symptoms of the main problem. If you want your handler to execute after all your ajax loads, then you may use a promise.
var ajax1 = $.ajax();
var ajax2 = $.ajax();
jQuery(function($) {
$.when.apply($, [ajax1, ajax2]).done(function() {
// your code here
});
});
Try on the window load event :
$(window).load(function() {
//Stuff here
});
To be sure, Try window load
$(window).load(function(e) {
mark_active_menu();
}
Before(sometimes, doesn't load absolutely at the beginning, a few milliseconds after(0-200ms about)):
$(document).ready(function(){
$('body').hide(0);
});
After:
$(window).load(function(){
$('body').delay(500).show(0);
});
In my situation of work with AJAX and HTML. I have the same problem with functions $(document).ready() and $(window).load(). I solved this problem by adding handler of my event (that should work at HTML DOC), to the jQuery function that runs right after AJAX reguest was finished. Read this: "
jQuery.post()" (third parameter in the function).
In my code it looks like this:
var RequestRootFolderContent = function(){
$.post(
'PHP/IncludeFiles/FolderContent.inc.php',
function(data){
$('[class~="folder-content"]').html(data);
//Here what you need
$('[class~="file"]').dblclick(function(){
alert("Double click");
});
}
)
}

How to run a jQuery Code after loading all the images in my page?

How to run a jQuery Code after loading all the images in my page ?
$(window).load(function(){})
Checking to see that all images have loaded is slightly involved, so unless you have a pressing need to be so precise, it is much easier to check that all image and everything else has loaded:
$(window).load(function() { ... });
This makes use of the jQuery .load() method.
If you do really need to check for specifically only images, then things get a little trickier. I initially wanted to do this:
$("img").load(function() { ... }); \\ THIS IS INCORRECT!!!!!
However the above creates a jQuery object that contains all images, and then it binds function() { ... } to each of these images. So the above will trigger a function as many times as there are images on the page!
To get around this, we should check how many images there are on the page, and only fire the function once after all those images have been loaded:
$(function() {
// To keep track of how many images have loaded
var loaded = 0;
// Let's retrieve how many images there are
var numImages = $("img").length;
// Let's bind a function to the loading of EACH image
$("img").load(function() {
// One more image has loaded
++loaded;
// Only if ALL the images have loaded
if (loaded === numImages) {
// This will be executed ONCE after all images are loaded.
function() { ... }
}
});
});
jsFiddle example
$(function() {
var length = $('img').length ;
var counter = 0;
$('img').each(function() {
$(this).load(function(){
counter++;
if(counter == length) {
Callback(); //do stuff
}
});
});
});
I did something like this recently, but went about it differently.
$('img').on('load', function(){
$('img').off('load'); //detaches from load event, so code below only executes once
// my code to execute
});
Not a direct answer. Still worth referring.
Refer
Run JavaScript Only After Entire Page Has Loaded
jQuery callback on image load (even when the image is cached)
Code
$(window).bind("load", function() {
// code here
});
#Peter Ajtai answer will work except on IE's cached images. To make it work with IE, here's a solution: https://stackoverflow.com/a/3877079 or by using the imagesLoaded plugin.
For anyone using jquery this little snippet does the trick (it ensures that all images are loaded before any script inside it are run)...
$(window).bind("load", function() {
// code goes here here
});

Categories

Resources