Mouse pointer as ASP.NET AJAX progress indicator
AJAX, ASP.NET, CSS, UI By Dave Ward on January 1st, 2007Update: If you’re looking for something more graphical, also see my example of using a CSS style as AJAX progress indicator.
The ASP.NET AJAX UpdatePanel control provides us a quick and easy way to AJAX enable websites without changing our familiar design patterns. It’s certainly much better than using full postbacks in many situations.
However, it lacks usability. While the user waits on the async postback to occur, they are left without any of the usual indicators. We’ve spent decades training our users to wait when they see an hourglass icon. Why throw all that away for a spinning Web 2.0 progress indicator that means little to an average user?
Luckily, the ASP.NET AJAX framework provides us with tools to correct this shortcoming.
We’ll start with a run of the mill UpdatePanel setup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <html> <body> <div id="Container"> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Update Me" /> <br /><br /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /> </ContentTemplate> </asp:UpdatePanel> </form> </div> </body> </html>
public partial class _Default : System.Web.UI.Page { protected void Button1_Click(object sender, EventArgs e) { Thread.Sleep(3000); Label1.Text = DateTime.Now.ToString(); } }
This is how it works with just an UpdatePanel:
First, we need to expand the Container div to fill the entire page using CSS:
html,body { height:99% } #Container { height:99%; min-height:99%; } html>body #outer { height:auto }
Next, we need to hook and handle the initializeRequest and endRequest events exposed by the ASP.NET AJAX framework, using this JavaScript embedded in the page anywhere after the ScriptManager control:
<script language="javascript"> var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); function InitializeRequest(sender, args) { $get('Container').style.cursor = 'wait'; } function EndRequest(sender, args) { $get('Container').style.cursor = 'auto'; } </script>
To further enhance usability, we can disable the update button for the duration of the async postback:
<script language="javascript"> var prm = Sys.WebForms.PageRequestManager.getInstance(); prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); function InitializeRequest(sender, args) { $get('Container').style.cursor = 'wait'; // Get a reference to the element that raised the postback, // and disables it. $get(args._postBackElement.id).disabled = true; } function EndRequest(sender, args) { $get('Container').style.cursor = 'auto'; // Get a reference to the element that raised the postback // which is completing, and enable it. $get(sender._postBackSettings.sourceElement.id).disabled = false; } </script>
Now, we have a much better user experience:
Of course, this is only the tip of the iceberg. The code could use some refinement, but it demonstrates the concept well.
Similar posts
What do you think? Your comments are welcomed.
I appreciate all of your comments, questions, and other feedback, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums. If you post there and then contact me with a link to the post, I'll try to take a look at it for you.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this comment" link underneath the comment you're replying to.

Comments
I have been looking for this, thank you so much, great article!
Me too! I’ve searched everywhere for this functionality. Thank you so much for this. :)
Sensational stuff. Thanks.
Thank you. sooo much.
Excellent article, and the animations for demonstrating what you are trying to achieve are a great tool - well done and thanks
Hi i am using 2 updatepanel in my webpage but i want to find out the updatepanel id in EndRequest(sender, args) function, so i can call different javascript as per updatepanel ID.
In that EndRequest function definition, sender._panelsToRefreshIDs will contain an array of UpdatePanel IDs to be refreshed at the end of the request. You can parse that to act accordingly.
Thanks a million!
thank alots! that’s really what i’ve been waiting for.
Hi. I try your method but I succeded to make it works only without the use of a MasterPage.
I tried to put in the masterpage the div with id=”Content” and your code but it dosn’t change the mouse icon when I use an UpdatePanel in a page that use that MasterPage ! Do you have an idea why?
What you have to keep in mind is that you can only change the mouse cursor over an HTML element, not necessarily on a wholesale basis. In the example, the effect is that it changes in the entire window, because of the full page “Container” div.
In a master/content page, depending on the structure of your page, that “Container” div inserted in a content area would probably be constrained to the size of the content area. So, you wouldn’t be able to get the effect in the full screen area.
However, if your master page template has a container type element at the top level, you can change the $get(’Container’) calls to manipulate that instead.
Thank you for your answer.
I realize that it wasn’t a problem of MasterPage but of the fact that the button was in a panel with “GroupingText” defined. In fact I notice that if my pointer is inside a panel (ONLY if the “GroupingText” label is defined) it doesn’t change look. The same if I have an other asp element (ex, textbox) and my pointer is inside that element … but in this last case is less evident while in the case of a panel is much more bad!!
Can you understand why and do you have any idea how to avoid it?
I look at the html generated in the two cases and I see the following:
(1) [working] panel without “GroupingText” label
(2) [NOT working if mouse is inside panel]
panel with “GroupingText” label
It is the fieldset tag that makes the cursor not change look if it is inside the panel!!!
Master:
Example master
I cannot post aspx code example, sorry!!!
I tried this one. But the hour glass is not coming for the mouse icon. Any clues.
See my answer to the comment above yours.
bless you! I’ve been looking all over for this!