views:

303

answers:

5

I have a tree that gets populated through the web service - this part is super fast, the part that's a bit slower is populating the tree...I have a gif rotating image that rotates while the service is loading. Since I use ajaxStop and ajaxStart trigger, the gif stops rotating after ajax request has completed, which is correct. However, because the loading takes a split second, the gif freezes for that split second which looks unprofessional.

How do I make the gif rotate until the tree is finished loading?

+2  A: 

Browsers give a low priority to image refreshing, so in the time your code is manipulating/inserting in the DOM, the browser is busy with that and doesn't have time to repaint the image.

There's not a whole lot you can do, besides optimizing your code so that the processing you're doing with the ajax data is less intensive, or for example if you're getting a list of 1000 items, insert them in the page in intervals of 50, with a small delay between each, so the browser has time to repaint.

YMMV, maybe it looks great as is in Chrome, but freezes for 5 seconds in IE.

Infinity
I've had good luck with setting a threshold, say 60-100ms, and pausing the DOM modifications once that's been exceeded (resuming after a similarly short delay for UI updates). This doesn't account for browsers that delay lengthy calculations 'till after the script completes, so it's worth keeping the threshold slightly lower than what's absolutely necessary, especially if the modifications are causing significant layout changes.
Shog9
I have reverted to replacing GIF with text
gnomixa
A: 

Use the jQuery load event: http://api.jquery.com/load-event/

then just display the load image until the load event for the tree load handler is called.

For example, consider a page with a simple image:

<img src="book.png" alt="Book" id="book" />

The event handler can be bound to the image:

$('#book').load(function() {
  // Handler for .load() called.
});

As soon as the image has been loaded, the handler is called.

Todd Moses
You do not understand the question.
SLaks
Sorry. I must not understand.
Todd Moses
A: 

While manipulating the DOM on the fly is really tedious for a lot of browser (especially older one) you might want to optimize what you are doing there as much as you can.

Also, another good idea would be to make sure you are running jQuery 1.4 which is a lot faster for doing such operations.

You can see useful benchmark(1.3 vs 1.4) done by the jQuery team that illustrates that here:

http://jquery14.com/day-01/jquery-14

matdumsa
i am considering to upgrade, but i am between deadlines, so i would rather not at this point. Something to keep in mind for next version anyways.
gnomixa
+1  A: 

Browsers won't typically update images whilst JavaScript code is executing. If you need the spinner to continue animating during DOM population, your population function will have to give up control back to the browser several times a second to let it update the image, typically by setting a timeout (with no delay, or a very short delay) that calls back into the population process, and then returning.

Unfortunately this will usually make your population function much more complicated, as you have to keep track of how far you've got in the population process in variables instead of relying on loops and conditional structures to remember where you are. Also, it will be slightly slower to run, depending on how you're populating the page structures, and if there are click or other events that your application might get delivered half-way through population you can end up with nasty race conditions.

IMO it would probably be better to stop the spinner and then update the DOM. You'll still get the pause, but without the spinner stuttering to a halt it won't be as noticeable. To give the browser a chance to update the spinner after ajaxStop has changed its src, use a zero-delay-timeout-continuation in your AJAX callback function so that on completion the browser gets a chance to display the altered spinner before going into the lengthy population code.

Making this population step faster is definitely worthwhile, if a slightly different topic. (Appending lots of DOM elements one after the other is inherently slow as each operation has to spend more time trudging through list operations. Appending lots of DOM elements all at once via a DocumentFragment is fast, but getting all those DOM elements into the fragment in the first place might not be. Parsing the entire innerHTML at once is generally fast, but generating HTML without injection security holes is an annoyance; serialising and re-parsing via innerHTML+= is slower and totally awful. IE/HTML5 insertAdjacentHTML is fast, but needs fallback implementation for many browsers: ideally fast Range manipulation, falling back to slow node-by-node DOM calls for browsers with no Range. Don't expect jQuery's append to do this for you; it is as slow as node-by-node DOM operations because that's exactly what it's doing.)

bobince
I am using dynatree jquery plugin - essentially I populate a tree recursively with the results from JSON web service. I already optimized node population from 1.5 minutes to half a second.
gnomixa