fadeIn callback doesn't work from inside jquery.ajax success - javascript

I get some data using AJAX, prepend element to body and then display it. After it's displayed I need to perform some client-side operations on a new element (say, I need to render Latex using codecogs' script). My code looks like this:
$.ajax({
/* ... */
success: function(data){
/* new element generation... */
$(newelement).fadeIn(100, LatexIT.render('*'));
},
/* ... */ });
As you can see I call LatexIT.render('*') as a callback from fadeIn. It should perform whatever LatexIT.render('*') does right after the animation is over. But when called from $.ajax success the callback doesn't work, although fade itself occures normally.
UPDATE: I tried to replace LatexIT.render('*') with any simple function but it doesn't work. And fadeIn(100, function () { LatexIT.render('*') }); does work when called from outside of ajax success.

LatexID.render('*') is the syntax to call the .render method rather than bind it. Unless that itself returns a function, which is unlikely, you need to use this syntax:
.fadeIn(100, function () { LatexIT.render('*') });
You could also do:
.fadeIn(100, LatexIT.render.bind(undefined, '*'))
assuming the browsers you need to support have .bind

There you are not giving it a success callback, you are executing your render and giving what the render method returns to the complete argument of the fade animation, which is actually not a function that the animation can call at the end.
You should just wrap it into an anonymous function:
$(newElement).fadeIn(100, function() { LatexIT.render("*"); })

Related

jQuery wait for a function to complete before new fires

I have two functions in jQuery that I want to fire in a specific order. The first function is an ajax function which updates a partial view. The other one is supposed to do some styling on the partial view, once the ajax function has completed - this function takes a parameter.
ajaxFunction();
stylingFunction(params);
I have tried the following:
ajaxFunction(function() {
stylingFunction(params)
});
Also, I have tried to use a callback:
ajaxFunction(stylingfunction(params));
ajaxFunction(callback)
{
//Do update
callback()
}
None of these do however work. The styling appears shortly where after it dissapears because the partial view is getting updated. Where am I going wrong here?
Both functions are written in my "parent" view.
You can use .done() and .fail() chained to the $.ajax call ...
I created a couple callback functions with psuedo-code inside the successCallback() since you said you only need to run the styling function "sometimes". You will want to test whatever condition inside that function to determine if you want to run the styling function. Hope this helps.
(function($) {
$(function() { //document.ready
$.ajax({ cache: false,
url: "/blah/vlah/lah",
data: { somedata: somedata }
})
.done(successCallback)
.fail(failCallback);
});
function successCallback(data) {
if (someCondition) {
stylingFunction(params);
}
};
function failCallback(jqXHR, status, error) {
console.log(jqXHR);
console.log(error);
console.log(status);
};
})(jQuery);
I created another gist which handles ajax event delegation, you may want to review and incorporate anything that seems helpful to your situation.
https://gist.github.com/inceptzero/a753d020648f49da90f8
I also created this gist on github for an ajax request queue which is a bit more elegant and robust.
https://gist.github.com/inceptzero/e64756f9162ca6aeeee5
Since you are using jQuery you could const ajaxFunc = callback => $.ajax({...}).done( data => callback) Also you could use async/await. You can read more about it on MDN.

What are callback function?

I ask a friend and ask what is (data, function(i,e) in this code and he said this is callback then i search the internet about callback and doesn't understand it. I read about this What are callback methods?what is callback in simpliest way ?
$.each(data, function(i,e){
console.log(e.id);
});
What is the use of (data, function(i,e) here?
$.ajax({
type: "GET",
url: pbxApi+"/confbridge_participants/conference_participants.json?cid="+circle,
dataType: "jsonp",
jsonpCallback: 'callback',
contentType: "application/javascript",
success: function(data) {
console.log(data);
}
});
A callback function is a function you specify to an existing function/method, to be invoked when an action is completed, requires additional processing, etc.
*Here's a little something for you to understand callbacks better:
Guy 1 to Guy 2: hey dude I wanna do something when a user clicks in there, call me back when that happens alright?
Guy 2 calls back Guy 1 when a user clicks here.*
A callback method which is called back.
Who calls it back at you ?
Your framework calls it back.
Why it calls it back ?
Because you ask for it to get called back because you want to do some processing when something happens.
Examples
You are doing some processing and don't know when it completes. You provide a callback , and you continue with some other work. Your call-back function will be called back to tell you that processing is finished and you can do something at your end now.
You want to know when some control fires some event so that you can do some processing. You provide a call-back function as event handler.
You are not happy with default processing done by framework and want to override that processing, you provide a call-back and framework calls it back to use your own processing.
So, in general : You ask a component/framework to call your provided method. You never call that provided method from your code, someone else calls it back.
A callback function is a function that is passed to another function as a parameter, and the callback function is called (or executed) inside the another Function.
Like this
(data, function(i,e)
We can pass functions around like variables and return them in functions and use them in other functions. When we pass a callback function as an argument to another function, we are only passing the function definition.
Note that the callback function is not executed immediately. It is “called back” at some specified point inside the containing function’s body. For more info Refer Here
Normally, JavaScript statements are executed line by line. However, with effects, the next line of code can be run even though the effect is not finished. This can create errors.
To prevent this, you can create a callback function.
A callback function is executed after the current effect is finished.
For e.g, this is a call back function:
$("button").click(function(){
$("p").hide("slow", function(){
alert("The paragraph is now hidden");
});
});
In this case the function hide will be executed before that alert which is precisely what we want.
On the other hand if you don't use call back function say this way:
$("button").click(function(){
$("p").hide(1000);
alert("The paragraph is now hidden");
});
In this case alert will be executed even before the function hide is executed. This is the typical use of callback function in Javascript.

forcing one javascript function to wait to run until the first has finished

Afternoon all, I am running into an issue where i need to run one function, then after that is finished, run the next, and do this for four functions, i have been at this for a while trying to find the correct syntax to layout my function calls in and cant seem to find anything to address this specific scenario.
html:
<div id = "putcontenthereafterajax">
</div><!--end putcontenthereafterajax-->
<div id = "putfooterhereafterajax">
</div<!--end putfooterhereafterajax-->
jquery:
$(window).load(function() {
function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
$('<img/>')[0].src = this;
//alert("I cached "+this+"");
});
$('#progressbarinner').css("width","200px");//change the width of the inner progress bar div
}
function changecss(){
$('.hidetillcache').css("visibility","visible");//make the page visible
$('#loadingscreen').fadeOut("slow");
}
function contentajax(){
$.post("templates/content.php",
{
whatamidoing:"imgettingthecontent"
},
function(data){
$('#putcontenthereafterajax').after(''+data+'');
$('#progressbarinner').css("width","400px");//change the width of the inner progress bar div
});
}
function footerajax(){
$.post("templates/footer.php",
{
whatamidoing:"imgettingthefooter"
},
function(data){
$('#putfooterhereafterajax').after(''+data+'');
$('#progressbarinner').css("width","500px");//change the width of the inner progress bar div
});
}
preload([
'images/careers.jpg',
'images/careers.png',
'images/contact.jpg',
'images/facebook.png',
'images/footer.png',
'images/footerblack.png',
'images/footergrey.png',
'images/home.jpg',
'images/media.jpg',
'images/media.png',
'images/myitv3.jpg',
'images/newindex.jpg',
'images/newindex.png',
'images/services.jpg',
'images/twitter.png'
], contentajax(), footerajax(), csschanges());
});
basically i have a loading bar that fills up a bit after each function is finished which in turn requries each function to be ran one after another in the correct order, all the functions do work, the caching and the ajax and even the css changes work. however i cant seem to find a way to force them in the right order and to wait to run until the previous is finished in order to compliment the loading bar. Anyone have any ideas?
You want to chain asynchronous function calls.
Use jQuery's deffered.then method :
ajax functions, like $.ajax(), $.post(), $.get(), return a Deferred object.
You can use this in your case :
function contentajax(){
// add the return instruction to return the Deferred object
return $.post("templates/content.php", {... });
}
function footerajax(){
//same here
return $.post("templates/footer.php", { ... });
}
// chain the deferred calls :
contentajax()
.then( footerajax() )
.then( csschanges() )
If you also want to wait for the loading of the images to complete, you can still use this Deferred abstraction by wrapping the loading mechanism inside a single Promise. I googled around and found this gist (due credit should be given to the author : Adam Luikart).
Try to use callback function.
Instead of using .css try using .animation({'':''},200,function(){"........another function here......"})
Same with fadeOut as .fadeOut(200,function(){".....another function here........."})
So at the end you will only call contentajax().
Hope that helps.
By default your ajax calls are async. You can't guarantee the order of returns async. It sounds like you want execution in synchronous order. Either use
async: false
in your ajax calls, or use each next function as a success callback to the current one and don't loop through them in preload.
success: function(data, textStatus, jqXHR)
{
successCallback(successCallbackArgs);
}

Extending jQuery for recursive ajax method

i would like to know if is possible to generate a method/extension/change for the jQuery lib to specify for all $.ajax() calls a method to be executed for example in timeout:, or in beforeSend:, statments
Of course. There are many ways, but one of the simple methods for having a centralized method to be run on every ajax call, is to wrap jQuery ajax in your custom ajax wrapper.
(function ($){
$.customAjax = function(path, data, successCallback, errorCallback){
function errorFallback(){
// Here, do what you want to do on any ajax call, which doesn't have error callback
};
errorCallback= errorCallback|| errorFallback;
$.ajax({
// Calling the jQuery ajax, passing either specified error callback or a default callback.
});
};
})(jQuery);

send $.post() one at a time ("adding a pause" but really: toggling a 'transmit' flag)

in jQuery, I iterate over an xml list of areas and do a POST request to get detailed information about each area. Because sending thousands of requests at once is debilitating for the client and server, I would like to set a flag so that I wait for a request to finish before sending the subsequent [next] request.
if the xml looks like this:
<area>5717</area>
<area>5287</area>
<area>5376</area>
then the xml parsing kinda looks like:
$(xml).find("area").each( function() {
doPost();
}
and the doPost() function looks like
doPost : function () {
$.post( ... )
}
Basically, I would like to add a toggling "wait" but I'm not sure how to achieve this. Is there a way I can keep the essential ".each" iteration or is another type of loop better for this?
Thanks in advance.
A general algorithm off the top of my head:
You could put the whole list into an array. Take the first item of the array and post it. In the success handler of your post you could recursively call the function with the next index int the list.
I wouldn't use async: false because it would then be a blocking operation, which I assume the OP doesn't want.
You can use:
$.ajaxSetup({async:false});
at the top of your script to make your AJAX calls synchronous.
Alternately, you can replace $.post() with $.ajax() and set the async flag to false.
can you do a setTimeout ? that will allow for the function to still process asynchronous and allow for you to wait for some time in there too.
http://www.w3schools.com/js/js_timing.asp
setTimeout(function() {}, 5000)
You can refactor your doPost() function to take the <area> element to process as an argument, and chain into the next element from your success callback. Something like:
(function doPost($area) {
if ($area.length > 0) {
$.post({
// your options,
success: function() {
// your success handling...
doPost($area.next("area"));
}
});
}
})($(xml).find("area").first());
EDIT: Maybe the code above was a little too compact indeed.
Basically, the aim is to refactor your function so that it takes a jQuery object containing the next <area> element to process, or nothing if processing should stop:
function doPost($area) {
if ($area.length > 0) {
// Perform POST request and call ourselves from success callback
// with next <area> element (or nothing if there's no such element).
}
}
Then call this function with the first <area> element to process:
doPost($(xml).find("area").first());
The first code fragment in my answer does both at the same time. Functions are first-class objects in Javascript, and you can call a function you've just defined by enclosing its definition with parenthesis and providing the usual argument list, also surrounded by parenthesis.

Categories