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:
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 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.
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).