1

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!

4
  • 1
    By the way @(...).show() and $(...).hide() are the jquery methods for visibility. Commented Jun 5, 2012 at 22:24
  • @Aren thanks for the catch..don't know why I'm doing it this way. Commented Jun 5, 2012 at 22:30
  • @thomas Just to be clear, jQuery show and hide methods set the element's "display" attribute to "none" or "block" (or whatever it was before it was "none"). This is a little different than what you're doing here, which is setting the visibility attribute. One time this difference come into play is when you want to get the dimensions of the image without showing it, which won't work if the display is set to "none". Commented Jun 5, 2012 at 22:40
  • @JoshNoe Good catch, yes visibility doesn't collapse the element. I just glanced at it and assumed hide/show was what he was looking for. Commented Jun 5, 2012 at 22:44

1 Answer 1

12

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:

Diagram

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.

Sign up to request clarification or add additional context in comments.

15 Comments

No, I'm just using the ajax thing as an example, I'm just looking for something that will show a loading image whenever javascript runs. thinking sensibly, probably only if it takes over 3/4 of a second.. That wasn't clear from my question
whenever javascript runs 3/4 of a second How many thousands of lines of JS are you running? Your browser would freeze up unless you're talking about ajax/loading other DOM elements asynchronously. Unless you're talking about timeOut/intervals or animations. Provide sample code or link to a page that takes more than a couple miliseconds to execute your pieces of code which aren't async.
@FabrícioMatté My Answer was originally different because I mid-interpreted his question. I think he wants the same thing for long-running operations that may be computational in nature vs. waiting for a ajax response. I think the 3/4th of a second is more of a guideline for himself a UX concern, such that if the user has to wait more than 3/4th of a second he wants a visual indicator that work is being done.
Alright, I see. I just don't see how that applies to non-ajax non-async functions, as the browser would simply hang until the function is processed. Nevertheless I'll +1 for your effort.
The problem is your long running operation is going to block the browser's rendering pass. The best way to optimize this so there's cycles to show/hide things is to use a HtmlFragment (DOM) or a Container DIV in jQuery. Basically instead of writing to the document, create a div in memory var container = $("<div></div>") and just append your changes to it. When you're done add container.html() to your page body and it'll add the resulting DOM quickly. This way events fired while it's working on building the result should be able to execute. Also your function will probably be faster.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.