CSS style as ASP.NET AJAX progress indicator
AJAX, ASP.NET, CSS, UI By Dave Ward on January 16th, 2007
I noticed that a lot of people found my mouse pointer as AJAX progress indicator example by using search terms suggesting they were looking for a more graphical indicator. So, here’s an example of doing something more… Web 2.0.
Like last time, I’ll base it on a standard UpdatePanel demo using a button control to set a time/date label, with an artificial delay:
<asp:ScriptManager ID="ScriptManager1" runat="server" /> <div id="Container" class="Normal"> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text="Update Me" /> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /> </ContentTemplate> </asp:UpdatePanel> </div>
protected void Button1_Click(object sender, EventArgs e) { Thread.Sleep(5000); Label1.Text = DateTime.Now.ToString(); }
I’ll style the container div with CSS to add a simple border and set up a class for the progress state:
.Normal { border: dashed 1px #000000; background-color: #FFFFFF; cursor: auto; padding: 10px; width: 200px; text-align: center; } .Progress { border: dashed 1px #000000; background-color: #EEEEEE; background-image: url(spinner.gif); background-position: center center; background-repeat: no-repeat; cursor: wait; padding: 10px; width: 200px; text-align: center; }
Finally, hook up our event handlers for BeginRequest and EndRequest:
<script language="javascript"> // Get a reference to the PageRequestManager. var prm = Sys.WebForms.PageRequestManager.getInstance(); // Using that prm reference, hook _initializeRequest // and _endRequest, to run our code at the begin and end // of any async postbacks that occur. prm.add_initializeRequest(InitializeRequest); prm.add_endRequest(EndRequest); // Executed anytime an async postback occurs. function InitializeRequest(sender, args) { // Change the Container div's CSS class to .Progress. $get('Container').className = 'Progress'; // Get a reference to the element that raised the postback, // and disables it. $get(args._postBackElement.id).disabled = true; } // Executed when the async postback completes. function EndRequest(sender, args) { // Change the Container div's class back to .Normal. $get('Container').className = 'Normal'; // Get a reference to the element that raised the postback // which is completing, and enable it. $get(sender._postBackSettings.sourceElement.id).disabled = false; } </script>
The end result isn’t too shabby at all:
What do you think? Your comments are welcome.
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 instead.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this" link underneath the comment you're replying to.


I have been searching everywhere for this, but need it to work with php. can you please help me put it in a php form?
For implementing it in PHP, take a look at this: http://codeplex.com/phpmsajax
Nice code… and thanks for pointing to the PHP reference ;o)
Nice idea, will certainly be using it.
Great, thanks.
Nice, Microsoft should really make this a built in feature. Good demo and code.
It works good if I place script at the end of the .aspx file. But if I put this script
into separate file, I get runtime error “prm is empty or it is not an object”.
Certainly i removed tags and added script reference to ScriptManager.
Why then it don’t work?
Dave Ward put solution to this problem in comment under “How to improve ASP.NET AJAX error handling”
Just do something like this and it will work fine:
function appLoad(){
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
}
appLoad is an event handler set with this code:
Sys.Application.add_load(appLoad);
Ok, yet another change ;)
If you use pageLoad instead of appLoad you don’t have to set event handler like this:
Sys.Application.add_load(appLoad);
hi, just want to know, i running this code under firefox, but it seem not working for me, did anyone knows why.. thank you
It definitely works cross browser (I use FireFox 99% of the time, myself). Did you get a particular error?
i’m sorry, i already find the real problem, my firefox not working so well, i reinstall my firefox and run back the code, it just find, thank you so much for the code…
Ok, might be a silly question. Where do you get the animated spinner.gif image? Can you post the URL or the image for download :-)
This is a great source for progress indicator graphics: http://www.ajaxload.info/
Many thanks for posting this! Exactly what I was looking for.
I liked it!!! Great!
I would like how make any function generic for all the updatePanel in my page??? is it possible ???
ps: sorry for my english!
Thanks a lot. When users upload their optin list in our email marketing application, we save the list which can take a while. We tested your solution and it’s just what we needed!
EXCELLENT CODE . JUST WHAT I NEEDED THANKS! Love the little addition of disabling control that posted back.
I offer you my 2 most fullsome goats as payment for your wonderful work! May they bring you much milk and good fortune. xx
This works well for one update panel, but how do you accomodate multiple update panels where a user could update one and then decide to update another while the other is still loading?
The second request would cancel the first. Only one partial postback can be active at a time.
So, using this single progress indicator for the entire page method, it basically takes care of itself.
Very usefull Thanks a lot. Had to look around for the spinner.gif. Just a suggestion maybe you could add a download code url. Thanks again
Would be great code, but I’m getting that *expletive* ‘Sys undefined’ error. Using IIS 7, AJAX enabled website, VS 2005.
Sounds like it’s probably a problem along these lines: http://encosia.com/2007/08/16/updated-your-webconfig-but-sys-is-still-undefined/
still doesn’t work. i tried the option in the link above, now I get prm null/not defined or something like that.
Do UpdatePanels work on that page, without the progress indicator?
started new AJAX enabled-site, dragged script manager, update panel onto page. dragged label and button into update panel. added CSS code in head tag, added jscript in head code (originally), tried it under script manager too, tried it as a seperate file. No go.
To answer the question: yes. i click the button, it waits, then displays the date/time.
Email me that page’s code, and I’ll take a look at it.
Hi Allan and Dave,
I am also facing the same problem. Did you find any solution to this problem?
Great article.
However, i got a question.
If i have 2 DIV, how can i have the progress icon appear on the one i click?
To clarity further, i want the progress pic to appear on DIV 1 if i click on the button inside DIV 1, and the progress pic to appear inside DIV 2 when DIV 2 button is clicked.
If those two divs are in different UpdatePanels, you can use sender._postBackSettings.panelID to determine which UpdatePanel raised the partial postback.
Dave,
thx for your reply.
I am fairly new to MS AJAX.
Can you show an example how to use sender._postBackSettings.panelID?
What is panelID? Is it the Div ID?
Please point me to the right direction.
Hi,
Your site is very helpfull. Thanks for all the usefull info. Theres a silly thing i need to point to in the above post,
$get(args._postBackElement.id).disabled = true;
The $get is not required since “args._postBackElement” gives you the reference to the element itself, so the code can be “args._postBackElement.disabled = true”. The same is true for
$get(sender._postBackSettings.sourceElement.id).disabled = false;
Regards,
Hi, Ratish.
You’re right about that. It’s always “interesting” to look back at our code after a year or so, isn’t it?
Why not use an UpdateProgress control? It basically does the same. So why fiddle around with the request hooks???
If the UpdateProgress control works well for you, that’s definitely a valid way to solve the problem.
In my experience, it doesn’t provide enough flexibility in most real-world apps (like so many other leaky abstractions).
What if there are many postback controls on the page and not just one button? For example I have a big form with several postback controls. Basically I don;t want any user input at all when ajax postback occurs. They can start typing in a textbox and then the postback returns, erasing everything they typed.
Will the progress div solve this issue? does it need z index to block user input?
Something like this would be a better solution in that situation: http://encosia.com/2008/10/04/using-jquery-to-enhance-aspnet-ajax-progress-indication/
Really great example Dave, very clean code. I was not able to use the UpdatePanel or UpdateProgressIndicator to get around users who are click-happy. This was a perfect solution. I actually commented out the ‘className’ lines, and included the snippet on the UserControl where I add the ScriptManager. Works like a charm for every PostBack Trigger in my UpdatePanel, without my having to associate it at any element level.
Thanks again!
In your code I did not see how you display and hide the loading.gif, can you elaborate that and provide the code?
Since it’s part of the CSS class, the loading.gif image is automatically shown and hidden when the corresponding CSS class is added or removed from the element.
great script thanx dude
Hi Dave, I’m new to AJAX was trying to implement your code, unfortunately it doesn’t work, what do you think am I doing wrong? I’m not sure about the js. code I pasted it in my Master.page?
Since you’re using a Master, you’re probably running into the ClientID problem. See this post for more information and some solutions: http://encosia.com/2007/08/08/robust-aspnet-control-referencing-in-javascript/
It’s you code running in Framework 2.0 instead ?
i try in framework 3.5 its work, but when i change to 2.0 it’s not working anymore
It works on 2.0 (2.0 was the only option when this post was published). You’ll need to be sure your web.config is set up properly for ASP.NET AJAX and that you have the ASP.NET AJAX Extensions 1.0 installed on both your development machine and server.
It’s work like a magic…
Thanks Dave
I don’t think you need to re-enable the button in the end request function, because when the postback is completed the updatepanel should be refreshed, and the button is ‘automatically’ enabled again. Refer to my blog post on similar topic: http://symphony-of-dot-net.blogspot.com/2010/03/how-to-disable-button-display-sending.html
That’s often true, but you can’t assume that the UpdatePanel containing the button will be refreshed just because it raised the async postback. If its UpdateMode is set to Conditional, ChildrenAsTriggers is set to false, and the button isn’t one of its triggers, it wouldn’t be refreshed at the end of the async postback.
I tried it, it is great but appears behind my gridview…