Function initiated in ajax call only works one time - javascript

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).

Related

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

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();
}

jQuery ajaxForm complete works sometimes, other times it only fires a native javascript function then stops

This may be a duplicate of this topic, but I must revive it as my issue seems to be a little deeper than this. I'm currently using ajaxForm() to submit a 4 question quiz to a PHP script, receive the result, and then populate it back into the DIV. The beforeSend function fires, sending the information to the ajax.php script. beforeSend also shows a loading graphic in the quiz container. Then the complete function fires properly as ajax.php returns the HTML to be populated back into the DOM. At that point, everything stops. The next line is a call to slideUp the loading div and then display the returned information in the quizContainer.
At this point if I put in a javascript alert it always fires, meaning that complete is at least firing when it should, but the jQuery reference to the loading div is completely ignored. Here's the code for the javascript file that handles the submission - the section handling this is "Handle the quiz submission":
$(document).ready(function () {
// Get rid of the message box after 15 seconds
setTimeout(function() {
$('#message').slideUp('fast');
}, 10000);
// Handle the Course List LIs
$('#courseList li').on('click', function () {
// Get the background color as it's set initially
var color = $(this).attr('oColor');
jQuery('div', this).toggle('slow', function () {
if ($(this).is(":hidden")) {
$(this).css('background-color', color);
}
});
// Change the background to be the same as the content background when it's expanded
if ($(this).is(":hidden")) {
$(this).css('background-color', '#33CC66');
} else {
$(this).removeAttr('style');
}
});
// Handle the quiz submission
jQuery.fn.exists = function(){return this.length>0;}
if ($('#quizForm').exists()) {
$('#quizForm').ajaxForm({
beforeSend: function() {
$('#quizContainer').slideUp('fast', function () {
$('#loading').show();
});
},
complete: function(xhr, theStatus) {
alert(theStatus);
$('#loading').slideUp('fast', function () {
$('#quizContainer').html(xhr.responseText);
$('#quizContainer').show();
});
}
});
}
});
If necessary I can provide more information and a temporary login to access this if anybody would like to see it in action. I'm currently using jQuery 1.8.1(.)
Thanks for any help!
Jon
I believe the first argument of the complete function is xhr.responseText rather than an xhr object which is actually the third argument. Try removing .responseText from your complete: function.

Wrapping all AJAX calls jQuery

I populate many parts of my website using
$("#theDivToPopulate").load("/some/api/call.php", callBackToBindClickEventsToNewDiv);
Where /some/api/call.php returns a built list, div, or some other HTML structure to place directly into my target div. The internet has been running slow lately and I've noticed that the time between a button click (which kicks off these API calls) and the div populating is several seconds. Is there an easy way to globally wrap all the load calls so that a div containing "Loading..." is displayed before the call is even made and hidden once the API call is complete.
I can not simply put the code to hide the div into the callBackToBindClickEventsToNewDiv as some load events have different call backs. I would have to copy the code into each function which is ugly and defeats the purpose. I want the flow of any .load to go as follows:
1) dispplayLoadingDiv()
2) Execute API call
3) Hide loading div
4) do callback function.
The loading div must be hidden first as the callback contains some animations to bring the newly loaded div in nicely.
EDIT:
Expanding on jacktheripper's answer:
var ajaxFlag;
$(document).ajaxStart(function(){
ajaxFlag = true;
setTimeout(function (e) {
if(ajaxFlag) {
hideAllDivs();
enableDivs(['loading']);
}
}, 500);
}).ajaxStop(function(){
ajaxFlag = false;
var load = $("#loading");
load.css('visibility','hidden');
load.css('display','none');
load.data('isOn',false);
});
This way loading is only displayed if the page takes more than 500 MS to load. I found the loading flying in and out real fast made things kind of choppy for fast page loads.
Use the following jQuery:
$(document).ajaxStart(function(){
$('#loader').show();
}).ajaxStop(function(){
$('#loader').hide();
});
Where you have an element called #loader that contains what you want to show when an AJAX request is being performed. It could be a span with text, an image (eg a gif), or anything similar. The element should be initially set to display: none
You do not even need to call the function anywhere else.
Try this
$("#someButtonId").click(function(e){
e.preventDefault();
$("#theDivToPopulate").html("Loading...");
$.get("/some/api/call.php",function(data){
$("#theDivToPopulate").fadeOut(100,function(){
$("#theDivToPopulate").html(data).fadeIn(100,function(){
//Do your last call back after showing the content
});
});
});
});

How to show progress dialog when i move from one page to another using jquery mobile?

I am developing an app using jquery mobile..
In that i want to show something like progress dialog from one page to another.
I have tried
$.mobile.showPageLoadingMsg();
but it takes a specific amount of time while showing...
Actually my other page loads few graphs so it takes time...
How can we show progress as soon as the graph loads on the other page?
I think You can make use of the events like pagebeforecreate or pagecreatelike
And placing the $.mobile.showPageLoadingMsg() in proper place in the code can place major thing.
$('#aboutPage').live('pagebeforecreate',function(event){
alert('This page was just inserted into the dom!');
});
$('#aboutPage').live('pagecreate',function(event){
alert('This page was just enhanced by jQuery Mobile!');
});
You can go though the follwing like :
http://jquerymobile.com/demos/1.0a3/#docs/api/events.html
Surround it in
$(document).ready(function() { ... }
if you aren't already
If you use AJAX to switch between pages you can do the following:
jQuery.ajaxSetup({
beforeSend: function() {
$('#loadingDiv').show()
},
complete: function(){
$('#loadingDiv').hide()
},
success: function() {}
});
"loadingDiv" is your container with spinner gif image (for example).

JQuery AJAX success + fadeIn

I'm using AJAX to load survey content into a container on a page, and during the transition, I fadeOut the container and fadeIn when it's done. It works fine for pages 1-4, but stops working for page 5. The content loads for page 5, but the container doesn't fadeIn.
success: function(data){
$("div#surveyContainer").fadeOut(function(){
$("div#surveyContainer").html(data).hide().fadeIn();
}); // end fadeout
}
There is no reference to surveyContainer anywhere in page 5. All I can think of is that something is timing out causing the fadeIn to not get triggered. The load time is about 36ms. I set the php script to where it's sending data to report all errors (and the data is making it into the Db just fine), but all I'm getting is the content I expect, but the container stays display:none. If I remove the fades, everything works fine :/
I've also tried this to no avail:
success: function(data){
$("div#surveyContainer").fadeOut(function(){
$("div#surveyContainer").html(data);
$("div#surveyContainer").fadeIn();
}); // end fadeout
}
Try adding a .stop(); see reference here
success: function(data){
$("div#surveyContainer").fadeOut(function(){
$(this).html(data).stop(true, true).fadeIn();
}); // end fadeout
}
This should stop any animations that are currently happening, force them to go straight to their ending point (where they were animating to) and clear the animation queue. You can probably get rid of the hide() this way too.
Also, you can just use this inside the callback for, well, I dont' know why. but you can.
Not sure why it would break on a individual page tho.
Perhaps you could try it in the callback of .hide():
$("div#surveyContainer").html(data).hide('slow', function(){
$(this).fadeIn();
});
As Interstellar_Coder pointed out. You have already hidden the div#surveyContainer when you faded it out. You now just need to load up your data and fade it in.
success: function(data){
$("div#surveyContainer").fadeOut(function(){
$(this).html(data).fadeIn(); // Removed the .hide()
}); // end fadeout
}
Don't link to http://code.jquery.com/jquery-latest.js from a page using encryption (HTTPS). Host the code locally.

Categories

Resources