Loading image while JavaScript function(s) run - javascript

is there a way to show a loading image while a JavaScript function is running. I have one that takes about 2-5 seconds, would be nice if i could have something like the jQuery-ajax function
$("#loading").bind("ajaxStart", function(){
$(this).attr("style", "visibility: visible")
}).bind("ajaxStop", function(){
$(this).attr("style", "visibility: hidden")
});
clarification edit:
The idea is that every time a JavaScript function runs and takes over, say 3/4 of a second, the loading image would be displayed. It really has nothing to do with this ajax function, just the same principle of always catching a running JavaScript and timing it.
Thanks!

Well then... After you commented, that changes everything.
You cannot have it automatically show when any javascript runs because there is no real hook for that. You can however leverage jquery custom events through the use of .trigger() and .bind() using your own custom event.
function myFunctionThatDoesSomething() {
$('body').trigger('Custom.BeginWork');
// Do Something ...
$('body').trigger('Custom.EndWork');
}
Although long running operations should probably be done asynchronously so they don't block on the event:
$("#Something").click(function() {
$('body').trigger('Custom.BeginWork');
setTimeout(function() { DoWorkFunction(/* you can pass params here if you need */); }, 0);
// Causes it to be executed in the background 0ms from now
});
function DoWorkFunction() {
// Stuff...
$('body').trigger('Custom.EndWork');
}
Then register a .bind() event much like .ajaxStart() and .ajaxStop()
$('#Working').bind('Custom.StartWork', function() {
$(this).show();
});
$('#Working').bind('Custom.EndWork', function() {
$(this).hide();
});
Here is a working jsFiddle Example.
Update:
In your jsFiddle you've done a double setTimeout. Here:
setTimeout(function() {
// Call Operation Here
try { setTimeout(function () { LongRunningOperation(10000); }, 1000);
}
finally
{
$("body").trigger('Custom.End');
}
}, 50); // 50ms delay because some browsers *cough*IE*cough* are slow at rendering dom changes
What this translates to is:
So the Custom.End event is getting fired after scheduling the long running function to run, not when it completes. setTimeout is asynchronous and non-blocking.

Related

Using $.ajaxStop() to determine when page is finished loading in CasperJS

So far in my tests written in CasperJS, I've been using waitForSelector() on page-specific elements to determine if a page has fully loaded (including all the async ajax requests). I was hoping to come up with a more standard way of waiting for page load and was wondering if the following was possible?
Inject as clientscript the following (include.js)
$(document).ajaxStop(function() {
// Do something
})
Description of ajaxStop according to jquery api: Register a handler to be called when all Ajax requests have completed.
Define a casper.waitForLoad function that when called would wait for the "something" in above code block
Use the function in several parts of the test.
Also any tips on the // Do Something part would also be appreciated :) I was thinking about using the window.callPhantom feature in phantomJS but I'm reading that it's not officially supported in casperjs.
I would do something like this in include.js:
(function(){
window._allAjaxRequestsHaveStopped = false;
var interval;
$(document).ajaxStop(function() {
if (interval) {
clearInterval(interval);
interval = null;
}
interval = setTimeout(function(){
window._allAjaxRequestsHaveStopped = true;
}, 500);
});
$(document).ajaxStart(function() {
window._allAjaxRequestsHaveStopped = false;
if (interval) {
clearInterval(interval);
interval = null;
}
});
})();
This sets a (hopefully unique) variable to the window object that can be later retrieved. This also waits a little longer incase there is another request after the previous batch ended.
In CasperJS you would probably do something like the following to wait for the change in the request status. This uses adds a new function to the casper object and uses casper.waitFor() internally to check the change.
casper.waitForAjaxStop = function(then, onTimeout, timeout){
return this.waitFor(function(){
return this.evaluate(function(){
return window._allAjaxRequestsHaveStopped;
});
}, then, onTimeout, timeout);
};
And use it like this:
casper.start(url).waitForAjaxStop().then(function(){
// do something
}).run();
or this:
casper.start(url).thenClick(selector).waitForAjaxStop().then(function(){
// do something
}).run();

Recursive setTimeout calls mysteriously stop running

I want to call a function in JavaScript continuously, for example each 5 seconds until a cancel event.
I tried to use setTimeout and call it in my function
function init()
{ setTimeout(init, 5000);
// do sthg
}
my problem is that the calls stops after like 2 min and my program is a little bit longer like 5 min.
How can i keep calling my function as long as i want to.
thanks in advance
The only conceivable explanations of the behavior you describe are that:
As another poster mentioned, init is somehow getting overwritten in the course of executing itself, in the // do sthg portion of your code
The page is being reloaded.
The //do sthg code is going into some kind of error state which makes it looks as if it not executing.
To guarantee that init is not modified, try passing the // do sthg part as a function which we will call callback:
function startLoop(callback, ms) {
(function loop() {
if (cancel) return;
setTimeout(loop, ms);
callback();
}());
}
Other posters have suggested using setInterval. That's fine, but there's
nothing fundamentally wrong with setting up repeating actions using setTimeout with the function itself issuing the next setTimeout as you are doing. it's a common, well-accepted alternative to setting up repeating actions. Among other advantages, it permits the subsequent timeouts to be tuned in terms of their behavior, especially the timeout interval, if that's an issue. If the code were to be rewritten using requestAnimationFrame, as it probably should be, then there is no alternative but to issue the next request within the callback, because requestAnimationFrame has no setInterval analog.
That function is called setInterval.
var interval = setInterval(init, 5000);
// to cancel
clearInterval(interval);

Set minimum time and timeout

I have loading animation which displays while the webpage is loading in the background. Once loading is complete it disappears.
What I'd like...
1. The animation to appear for a minimum of 1 second.
2. Once the 1 second minimum has expired, the animation will be naturally removed following page loading.
3. To avoid the possibility of a fault (and watching an endless animation loop), I want the animation to time out if it takes more than 5 seconds to load.
Here's what I have so far...
$(window).load(function()
{
$('#followingBallsG').hide();
$('#backgroundcolor').hide();
});
Any assistance you can provide would be greatly appreciated. Thanks.
There are no built-in jQuery features for this. You will need to write out the logic for this. Here is a simple implementation, free of race-conditions.
(function(){
var didDone = false;
function done() {
//Prevent multiple done calls.
if(!didDone)
{
didDone = true;
//Loading completion functionality here.
$('#followingBallsG').hide();
$('#backgroundcolor').hide();
}
}
//Variables to keep track of state.
var loaded = false;
var minDone = false;
//The minimum timeout.
setTimeout(function(){
mindone = true;
//If loaded, fire the done callback.
if(loaded)
{
done();
}
}, 1000);
//The maximum timeout.
setTimeout(function(){
//Max timeout fire done.
done();
}, 5000);
//Bind the load listener.
$(window).load(function(){
loaded = true;
//If minimum timeout done, fire the done callback.
if(minDone)
{
done();
}
});
})();
I've wrapped it in a immediately invoked function expression and assumed $(window).load is the event you are listening for. It should be easy to adapt this to another event or to run at another time if this is not the desired effect.

How to stop/override a Jquery TimeOut function?

I have a small jquery snippet that displays notification message at the top of the screen in response to user actions on a page. The notification is often displayed after Ajax actions with dynamic content inside it.
For example:
$("#mini-txt").html("Thank you!");
$("#mini").fadeIn("fast");
setTimeout(function() {$("#mini").animate({height: "hide", opacity: "hide"}, "medium");}, 3000);
The notification works well, except when a user does two or more actions in rapid succession, in which case the TimeOut function will confuse itself and the second message appears to come inside the previous 3000 milliseconds.
Is there a way to "kill" the previous notification if a new action is performed. I've got no problem with the actions/selectors, just the TimeOut function.... either stopping it or overriding it somehow. Or perhaps there's a better alternative for getting the message to linger on the screen for a few seconds before disappearing?
Thank you.
First, you store the return value for the setTimeout function:
// Set the timeout
var timeout = setTimeout(function()
{
// Your function here
}, 2000);
Then, when you're ready to kill the timeout...you just call clearTimeout with the stored value from the previous call to setTimeout.
// Then clearn the timeout
clearTimeout(timeout);
You can use .stop()
Stop the currently-running animation
on the matched elements.
jQuery 1.4 has a built in method to handle delays for animations you can do something like this:
$("#mini-txt").html("Thank you!");
$("#mini").fadeIn("fast").delay(3000).animate({height: "hide", opacity: "hide"}, "medium");
And then later when you want to clean the animation queue you can do:
$("#mini").stop(true);
This will clear timeout after function run with delay 500ms
var timeout = setTimeout(function(){
/* YOUR FUNCTION */
}, 500, function(){
clearTimeout(timeout);
});

In jQuery Form, 'success' is being called before 'beforeSubmit' is finished

I'm using the jQuery Form plugin to upload an image. I've assigned a fade animation to happen the beforeSubmit callback, but as I'm running locally, it doesn't have time to finish before the success function is called.
I am using a callback function in my fade(); call to make sure that one fade completes, before the next one begins, but that does not seem to guarantee that the function that's calling it is finished.
Am I doing something wrong? Shouldn't beforeSubmit complete before the ajax call is submitted?
Here's are the two callbacks:
beforeSubmit:
function prepImageArea() {
if (userImage) {
userImage.fadeOut(1500, function() {
ajaxSpinner.fadeIn(1500);
});
}
}
success:
function imageUploaded(data) {
var data = evalJson(data);
userImage.attr('src', data.large_thumb);
ajaxSpinner.fadeOut(1500, function() {
userImage.fadeIn(1500);
});
}
I think you may be getting too fancy with those fade animations :)... In the beforeSubmit the fadeOut is setup but the function returns immediately causing the submit to happen. I guess the upload is happening under 3 seconds causing the new image to appear before your animations are complete.
So if you really really want this effect, then you will need to do the image fadeout, spinner fadein, and once that is complete triggering the upload. Something like this:
if (userImage) {
userImage.fadeOut(1500, function() {
ajaxSpinner.fadeIn(1500, function(){
//now trigger the upload and you don't need the before submit anymore
});
});
}
else {
// trigger the upload right away
}
Even though the beforeSubmit callback is called before submitting the form, the userImage.fadeOut function is synchronous (i.e. it spawns a separate thread of execution to execute the fade animation then it continues execution) and it returns immediately. The fade animation takes 1.5 seconds to complete and as you are running on localhost the ajax response is returned faster than 1.5 seconds and thus you won't see the animation, in real world applications it mostly unlikely that ajax requests would take less than 1.5 seconds, so you are good :)

Categories

Resources