Sunday, May 24, 2009

Client-Side Progress Indicator

Long ago I learned how to properly wire up the AJAX UpdateProgress control. This works perfectly to display a wait indicator while the AJAX UpdatePanel is performing a partial page postback. That's fine for server-side operations but what about on the client-side?

Lately I've been doing a lot more work on the client-side, in no small part due to my adoption of jQuery as a standard for all of my web programming. What once was always frustrating is now quite fun! As such, I'm in the process of doing the following with all of my Javascript code:
  1. Converting as much as possible to jQuery.
  2. Streamlining everything I can.
  3. Turning custom code into generic, reusable code.
  4. Moving all of the reusable code to common external Javascript files.
The User Manager module in one of my projects includes two different treeviews:
  • One for Roles/Users
  • The other for something proprietary called "Contract Rights"

Both treeviews have an "Expand All / Collapse All" button below them, providing a one-touch way for the user to quickly expand/collapse all the nodes of the treeview. This operation is done entirely with client-side code. Depending on the number of nodes, the delay time can be upwards of 5 seconds. While it's occurring, there was no wait indicator, so I decided to add one.

I thought I could just add the same jQuery code to the beginning & end of the function as I had successfully deployed to the AJAX Event Handler functions, namely:

$("#<%=UpdateProgress1.ClientID%>").css("display", "block");

$("#<%=UpdateProgress1.ClientID%>").css("display", "none");

I tried it and . . . nothing happened. There was no wait indicator whatsoever! After scratching my head for awhile, it occurred to me that the problem may lay with the web equivalent of the DoEvents() necessity that every WinForms developer is familiar with, namely that the UI needs to be given time to catch up. So I did a little research and found this old, but excellent article on MSDN. It confirmed that the Javascript setTimeout() function had to be used for a similar reason to why DoEvents() is needed with Windows programming.

So I moved the bulk of the code within my buttonExpandCollapse_Click function into one called ExpandCollapseNodes. And then I called the latter from the former as follows:

setTimeout(function() { ExpandCollapseNodes(button, hidVar, treeView, waitAnimID) }, 1);

It works beautifully! Note that just a 1 millisecond delay is all that's necessary to cause the wait indicator to display. The code to turn on the wait indicator is executed in the calling function and the code to turn off the display is the very last line of ExpandCollapseNodes.

I'd more than happy to provide a more complete set of the code if it would help anyone. Just ask!

2 comments:

  1. jQuery has that .css stuff built in you can actually do $("#").show(); or .hide(); Just some quick shorthand.

    Nice article though, I haven't done to much client-side programming, and the setTimeout never made much sense to me.

    ~PNasser

    ReplyDelete
  2. I'm still learning jQuery so wasn't up to speed with that pair of functions. Just tested them and they work great! Thank you.

    ReplyDelete