I am trying to prevent an element from being animated until a specific function is complete. The problem is that the animation starts while the function still is running, so the animation is extremely laggy and jumpy instead of smooth and calm as it is when I disable the function.
My code looks something like this:
function editElement() {
// Do a lot of calculations and edit what is inside #box (no Ajax)
}
$("#click").click(function() {
editElement();
$("#element").slideDown("slow");
});
How can force the slideDown animation to wait until the function is complete before running?
I have tried callbacks and $.Deferred suggested in other questions, but most of them seem to be directed towards Ajax and do not work for me. Thank you for your time!
slideDown is always executed after editElement has finished executing its code because JavaScript is a "linear language". The only exception is when there are asynchronous functions inside, including AJAX and setTimeout / setInterval.
One suggestion though is that you can do this:
function ediElement(..., callback){
//codes here....
//Make sure there is no asynchronous functions.
callback();
}
$("#click").click(function() {
editElement(function(){
$("#element").slideDown("slow");
});
});
Related
Based on what I understand you need 60fps on your animations to make the animations appear smooth. Basically what I'm trying to do is to do the heavy calculations at the start of the frame so by the time the rendering is actually going to happen there won't be much work left to do.
I understand you can use window.requestAnimationFrame to run a function right before the screen is redrawn. But that will cause a jerking effect if the function takes a long time. Is there a way to run a function right after the screen has done a repaint?
I tried something like this but its miss and hit:
window.requestAnimationFrame(do_before);
do_before(){
window.setTimeout(do_after, 1);
}
do_after(){
//code to execute after animation frame
}
As you can see in the picture below the do_after code is still executing in the same frame and because of this I sometimes get long frames:
Link to image
Is there a way to make do_after() run after the screen has finished drawing itself?
Thanks in advance
Actually, the code from you question is right. setTimeout(do_after) is enough in Chrome and Safari (I haven't tested in other browsers). It makes the browser execute the function when the browser is free of other tasks.
If you want to delay the execution from inside a requestAnimationFrame callback, just call setTimeout(do_after) and the callback will be executed right after the frame flush:
requestAnimationFrame(() => {
do_before();
setTimeout(do_after);
});
If you want to delay the execution from another place (e.g. a click handler or an AJAX response handler), call requestAnimationFrame first and then setTimeout:
document.addEventListener('click', () => {
do_before();
requestAnimationFrame(() => {
setTimeout(do_after);
});
});
Unfortunately I haven't found a universal way to execute a callback right at the start of the next frame because there is no straightforward way to know if a code is executed inside a requestAnimationFrame handler. You may use a trick to solve it
If you need to execute a callback right after any frame flush, use the second approach (requestAnimationFrame + setTimeout). It may lead to idling a whole animation frame before running the callback.
There is no API function to do what you want, but you can do the following:
window.requestAnimationFrame(function()
{
do_before();
window.requestAnimationFrame(do_after);
});
This makes sure your do_after is called after the first animation frame, and will trigger a second one after it's done executing.
How do I make sure the alert comes after the loading of the external HTML?
function changeContent(){
$('#contentmain').load("contentmain.html", function(){
alert("something");
}
)}
I've been playing around with $(document).ready, but no luck so far.
Many thanks!
Update:
The result of this code is that it depends (on what, I don't know): sometimes the alert comes first, sometimes it comes second...
Your code is right.
From the jquery documentation:
Callback Function
If a "complete" callback is provided, it is executed after post-processing and HTML insertion has been performed. The callback is fired once for each element in the jQuery collection, and this is set to each DOM element in turn.
are you loading iFrames?
try the .load() function.
$('#iframeID').load(function(){
// I am totally loaded and lets begin the hunt now.
});
Alternatively, If you are loading content via ajax, you can use .ajaxComplete
$(document).ajaxComplete(function(){
// ajax call has completed and lets begin the hunt now.
});
Calling toggle takes a long time to load, so I'm trying to add a loading img while loading but it doesn't seem to load when you .showall is activated look at * in the following code
$('#loading').hide();
$(".showall").toggle(
function(){
$('#loading').show(1); // * added
$(".toggle_container").slideDown();
$('#loading').hide(); // * added
},
function () {
$('#loading').show(1); // * added
$(".toggle_container").slideUp();
$('#loading').hide(); // * added
}
);
The other response of calling hide in the callback is the correct approach, but I figured I'd answer to point out why.
There are actually multiple issues here. Your intention is to show #loading then slideup and once that is complete, hide #loading. However, when slideup is called, the animation is queued up and your code moves on, the code does not wait for slideup to complete and then move on to the next line. This is why you need to use the callback, to call hide after slideup completes.
Another thing that many people overlook is that show and hide when called with a duration are animations and are therefore queue, however, when no duration is passed these calls are NOT animations and will NOT be queued. So, calling show with a duration and then immediately calling hide with no duration will never show the element. See this for an illustration of that: http://jsfiddle.net/zZHhm/ notice that you never see DIV2.
Also, the durations passed to show and hide are in milliseconds, so hide(1) gives a duration of 1 millisecond (you may be aware of this).
I admit, something weird is happening while using show/hide with or without parameter. This version works, but I don't know why these methods without parameters doesn't behave as they should.
Code: ( http://jsfiddle.net/z3HRQ/2/ )
$('#loading').hide(1);
$('.showall').toggle(
function () {
$('#loading').show(1);
$('.toggle_container').slideUp(function () {
$('#loading').hide();
});
},
function () {
$('#loading').show(1);
$('.toggle_container').slideDown(function () {
$('#loading').hide();
});
}
);
There are several posts relating to this, but none actually gives a solution.
What actually happens is as follows:
function LoadSpinner()
{
$("#divSpinner").css('display','block'); // could have done with .show()
}
function UnloadSpinner()
{
$("#divSpinner").css('display','none'); // could have done with .hide()
}
function OnClickMyButton()
{
LoadSpinner();
AnAjaxCall(); // it's set to async: false, that means the ajax call must finish before execution continues
UnloadSpinner();
}
I tried commenting the UnloadSpinner() and it does show in IE 8. Could it be that it happens so fast that I don't see it. But I am not too sure about that, cause even for some slower operation it does not show up.
It's working fine on Firefox though.
Is the issue that you're doing a synchronous ajax call? I believe this freezes the browser from executing any other actions including repainting the screen to show your spinner. Try making your ajax call asynchronous and hide the spinner in the callback. I bet you that works. Something like this:
function OnClickMyButton()
{
LoadSpinner();
AnAjaxCall(function() { UnloadSpinner() } );
}
function AnAjaxCall(callback)
{
//do ajax. On complete, call callback. check the web for examples.
}
I would bet you the issue has nothing to do with jquery, but with the synchronous ajax call.
To test my theory try this code:
function OnClickMyButton()
{
LoadSpinner();
setTimeout(function() { UnloadSpinner() }, 2000);
}
I bet you the spinner appears for 2 seconds just fine. If it doesn't then ignore this post.. I'm completely wrong.
$(function() {
$("#d").hide();
$('#b').click(function() {
$('#d').show();
});
});
<div id="d">hello</div>
<input type="button" id="b" />
Works fine for me in IE.
Do you have a specific example ? I don't recall encountering that problem despite I use show() quite often.
I have done a bit of debugging on it and found that the Browser wasn't doing the necessary updates on time. That is why by the time it was suppose to be visible, the Unloader() was called and it got hidden again.
How can I in jQuery test when a javascript function is fully loaded?
I would like to use a gif, which displays loading, while the javascript function loads, and hide it when the function is fully loaded?
$(function(){
$("#loadingGIF").show();
WaitForFunction();
});
function WaitForFunction()
{
if (!$.isFunction(FUNCTION_TO_WAIT_ON_HERE)) {
setTimeout( WaitForFunction, 100);
return;
}
Function_Loaded();
}
function Function_Loaded(){
$("#loadingGIF").hide();
}
Just call yourself after defining the function. The statements after the function definition will only be executed after the preceding source text is read (and thus executed).
I'm not sure what you mean by loading but the following should apply anyway:
When you start loading the JavaScript code, display the GIF
In the code you load, add a statement to hide the GIF at the end
This should solve your problem in a "simple" way without having to use timers, etc.