So my issue is pretty straight forward, since there is seemingly no callback for after a .css is executed, what options do I have for making performing something after a task is done?
I'm creating a simple lightbox, and I need to wait for the center align to finish...
$("#img_lightbox").css("top", top);
So when that completes, I then need to fade in the whole thing, but since there is no callback option (to the best of my knowledge) it will occasionally start fading in before the alignment finishes... how can this prevented?
Any help is appreciated, thank you.
Anything being chained with your jQuery object will execute after the function before it. The easiest way to accomplish what you are asking is with Plugins.
jQuery.fn.myPlugin = function () {
//code to execute
return this;
}
$("#img_lightbox").css("top", top).myPlugin();
You could even write a plugin to execute a custom function, so you do not need to create plugins for every function you might happen to need to run:
jQuery.fn.myCallback= function (callback) {
this.each(function () {
callback.call($(this));
});
return this;
}
$("#img_lightbox").css("top", top).myCallback(function () {
// some code to run where this = $("#img_lightbox")
});
But incase I am still misunderstanding, you may be wanting a callback for your fade function: (otherwise please clarify more)
$("#img_lightbox").fadeIn('slow', function () {
$(this).css("top", top)
});
Adding and removing CSS styles are synchronous functions -- there is no callback because the next statement will be executed once the style has been applied. Rendering of the updated style is slightly different, since that will happen during the next repaint, but unless you're doing some serious number-crunching in your UI code, the difference would be completely unnoticeable. In any case, it would be applied before the 'fading in' starts to happen.
If you're seeing something wrong with your display, I'd suggest that the problem lies elsewhere.
jQuery provides you with a way to tell once the document is "ready" and in the correct state to execute code correctly. Use one of the following:
$(document).ready(function(){
//your code here
});
or the shorter,
$(function(){
//your code here
});
More information at http://api.jquery.com/ready/
Related
I am making a website where depending on what a column says in the database the javascript will perform a curtain task (using ajax). This is going fine, however in the if statement, when the requirements are met, it keeps repeating it since it's inside the setInterval. It is probably easier for me to just paste the code and give you a chance to take a look at it.
setInterval(function(){
$("#div").load("content.php");
if ($('#div:contains("hello")').length > 0) {
alert("Hello, world!");
}
}, 200);
As you can see above, the alert is alerted forever at the speed the interval is set to. Sorry if I have been unclear, I have no idea how to ask questions properly on forums.
I assume you use the setInterval to check if the div has gotten its content already.
This can be solved with a callback (or a promise)
The load method of jQuery (which you are using) offers a callback function "complete". See
http://api.jquery.com/load/
$("#div").load("content.php", {}, function(){alert(1)});
I think you have a lack of understanding of how to approach this task from the outset. I would suggest you look in to how asynchronous operations work in javascript.
What you're trying to achieve here can be achieved with something like this:
$.get("content.php", function( data ) {
$("div").html(data);
if (data.indexOf("hello") > -1) {
alert("Hello, world");
}
});
How to call a function after "Complete page load" and "after all external script execution" ?
I tried all 4 below option, but no luck!!!
$(document).ready..
$(window).load...
window.onload = ...
$(document).ready(function()...
Doing setTimeout works for me, But not sure if this 100% efficient!!!!
setTimeout(function(){
//your code here
}, 3000);
Please advice and help!!!
I have been terribly interested with your question and going deep to the jQuery source I came up with a mad hack :)
But the key point is that you should put this piece of code at the very beginning, right after you plug jQuery:
$.statesNum = 0;
$.fn.ready = function ( fn ) {
$.statesNum++;
jQuery.ready.promise().done( fn ).then(function () {
$.statesNum--;
if ($.statesNum == 0) {
$(document).trigger("afterReady");
}
});
return this;
};
Now whenever you want to execute something after all .ready functions are done you can do like this:
$(document).on("afterReady", function () {
alert("Hey, the ready functions are executed");
});
Scripts are loaded and executed in the order they appear in your HTML. If you have simple scripts, just put things you want to run later at the bottom.
However if you have complex scripts that run asynchronously (meaning they run in parallel), then it is impossible to know if they have finished executing without actually looking at what they do. E.g. do they (or can they) trigger an event that you can listen to? Or maybe you can use "promise" patterns.
I want to display a spinner before some complicated function, i.e. dummyCounter(). The code looks like:
function add1() {
msg.html('start counting~<br \>');
document.body.appendChild(div);
spinner.spin(div);
// display spinner before doing stuff
dummyCounter();
}
jsfiddle: http://jsfiddle.net/eGB5t/
However the spinner shows after the dummyCounter() function is finished.
I try to use callback to force spinner display earlier but still no good. Can anybody help? Thanks.
jsfiddle: http://jsfiddle.net/eGB5t/2/
You have a thinking failure. Spinners are usually used for asynchronous tasks, so you can see that there is something in progress. A callback is then used to remove the spin when the async action has finished, since you cannot tell before it starts when it will finish.
I made up a quick example to show you, how such an async function would work in this case, and you can clearly see how the spinner appears slightly before "google finished" appears.
http://jsfiddle.net/eGB5t/4/
I added the following instead of your counting method:
$.ajax("http://google.de").always(function() {
msg.append("google finished");
});
You add the spin before you count, then it counts, then you could remove the spinner. This is perfecty fine. Thing is, if you would count to let's say 9999999999999 (so it would take some seconds), a normal for loop like you're doing is completely blocking the browser, so you won't have any repaints (and therefore no spinner) at all, while the loop is running.
What you would have to do (in this case) is to introduce a worker to have multithreading functionality in javascript.
var x;
function add1() {
msg.html('start counting~<br \>');
spinner.spin(div);
x= setTimeout(document.body.appendChild(div),500);
}
I have several page elements I want to fade out. I then change the css class of them (while they are not visible) then fade them back in.
I thought I had ordered the execution flow properly but sure enough the css class transition is occurring before the fadeOut is complete. Visually what happens is that a person sees the css change and then fadeout occurs.
You can see it at the link below. Between slide 1 & 2 it happens but is not as noticeable as the css change is from class a to class a. Between slide 2 & 3 you can see it as that is from class a to class b.
http://staging.alexandredairy.com
jquery transition code onReady kicks it off:
var txtread =
{
onReady: function(_imgname)
{
txtread.fadeoutText(_imgname);
txtread.fadeinText();
},
fadeoutText: function(_imgname)
{
$("#pagetitle").fadeOut(1250);
$("#pagemenu").fadeOut(1250);
$("#pageslogan").fadeOut(1250);
$("#sitecopy").fadeOut(1550, txtread.TextReadabilityHandler(_imgname));
},
fadeinText: function()
{
$("#pagetitle").fadeIn(1250);
$("#pagemenu").fadeIn(1250);
$("#pageslogan").fadeIn(1250);
$("#sitecopy").fadeIn(1250);
},
TextReadabilityHandler: function(_imgNameSwitch)
{
if(_imgNameSwitch == 'Light')
{
$("#pagetitle").attr('class', 'sitetitle lighttextbackground');
$("#pagemenu").attr('class', 'sf-menu lighttextbackground');
$("#pageslogan").attr('class', 'slogan lighttextbackground');
}
else if (_imgNameSwitch == 'Dark_')
{
$("#pagetitle").attr('class', 'sitetitle darktextbackground');
$("#pagemenu").attr('class', 'sf-menu darktextbackground');
$("#pageslogan").attr('class', 'slogan darktextbackground');
}
else
{ alert(_imgNameSwitch); }
}
}
so I thought order of execution, longer fadeOut, and setting the fadeOut completed function last would keep things in order but alas. I was wrong.
Thank You
Edit
So now I have tried window.setTimeout and it behaves exactly the same as if the timeout doesn't even run???
OK my bad. I originally tried:
window.setTimeout(txtread.TextReadabilityHandler(_imgname), 3000);
and that didn't error or work. I then went back and reread a bit better and saw to use a callback so I rewrote this way:
window.setTimeout(function(){ txtread.TextReadabilityHandler(_imgname); }, 3000);
and now it is working.
My original question still applies though. I understand javascript is an asynchronous programming language but it is imperative no?? Perhaps I am getting terms jumbled in my head.
Does the following execute one after the other:
alert('1');
alert('2');
alert('3');
or do they all execute at once?
Your code includes the following.
onReady: function(_imgname)
{
txtread.fadeoutText(_imgname);
txtread.fadeinText();
}
You are correct in thinking that txtread.fadeinText() will not run until txtread.fadeoutText(_imgname) is complete. However, fadetextOut is completing before you are expecting it to.
fadeoutText: function(_imgname)
{
$("#pagetitle").fadeOut(1250);
$("#pagemenu").fadeOut(1250);
$("#pageslogan").fadeOut(1250);
$("#sitecopy").fadeOut(1550, txtread.TextReadabilityHandler(_imgname));
}
will return almost immediately, having told the various elements to fade out over a period of time. So calling txtread.fadeinText() will not wait for those elements to fade out.
You will need to add some form of callback to fadeinText and fadeoutText, which you can use to let other code know they have finished, like so.
onReady: function(_imgname)
{
txtread.fadeoutText(_imgname, function () {
txtread.fadeinText();
});
}
fadeoutText: function(_imgname, cb)
{
$("#pagetitle").fadeOut(1250);
$("#pagemenu").fadeOut(1250);
$("#pageslogan").fadeOut(1250);
$("#sitecopy").fadeOut(1550, function() {
txtread.TextReadabilityHandler(_imgname);
cb();
});
}
fadeinText: function(cb)
{
$("#pagetitle").fadeIn(1250);
$("#pagemenu").fadeIn(1250);
$("#pageslogan").fadeIn(1250);
$("#sitecopy").fadeIn(1250, cb);
}
The alerts would execute in order. Javascript is single threaded.
Edit: Er, I guess that is true for the most part
Check out this link for a good explination, especially regarding fades, etc.
Is JavaScript guaranteed to be single-threaded?
As Michael said, the javascript will all run at the same time. So, run your fadeout functions, then, once they're finished, call the csschange functions and, once that's complete, run the fade in functions.
I'd be able to write this in jQuery (as it's easy to add a function to run after another is complete). It should be straighforward in plain js, I just don't know the syntax so well . . .
in javascript commands are excuted in order , the thing is if you have error within just one command , it could stop the whole script from excution .
http://www.w3schools.com/js/js_statements.asp
Each statement is executed by the browser in the sequence they are
written.
I have some code, with the order of the functions in the order I want them executed. However, they seem to at the same time (they begin sequentially within microseconds of eachother presumably).
The problem is that some of the functions include animations. How do I make it so the next function doesn't execute until the previous functions are completely finished???
Following is some of my code. I created a callback chain thinking that it would be the solution, but indeed it is not. The functions themselves call jQuery animations. I'm guessing i need to use some type of notofication from jQuery to tell me when animations are done. Anyhow, any advice is greatly appreciated!
show_loader(0, function() {
close_box($target_close, '/', '#' + $target_close.attr('id') + ' .post_wrap', function() {
open_box($target_open, event.value, '.wide-col', function() {
hide_loader(function() {
scroll_to_content($target_open, function() {
});
});
});
});
});
To be precise, I want the scroll_to_content() function to be executed after all the previous actions have been completed in their entirety. Currently, it executes at the same time as everything else, and therefore my page scroll is completely off because the size of my content continues changing after scroll_to_content() is finished.
Callback chains are basically the solution but I suspect you're not threading your callbacks correctly in your calls to jQuery. $.animate(...) has an optional complete callback-- that's where you want to pass the function that should execute after your initial animation finishes. All of the Effects in jQuery UI should have a similar optional argument.
You can use a similar pattern yourself in order to chain event handlers, for instance:
function handler(event, callback) {
// do some work
// ...
callback();
}
This strategy for chaining function evaluations is called continuation-passing style and is handy in a lot of situations. Be careful using it, however, as many people find it more confusing to read than a traditional, sequential implementation.
http://api.jquery.com/queue/
Sorry, I don't have enough time to go into detail, but as the previous commenter said, queues are what you want to be focusing on to solve this problem.
you have 3 options:
1- Split your animations into multiple chained animate() calls.
This is an example to clarify it for you.
2- Follow the answer posted by #dml.
3- Try to use this plugin to add delays between your calls (don't know if it can fix this scenario or not, give it a try)
http://www.evanbyrne.com/article/jquery-delay-plugin