I want to show progress with jquery ui progress bar when an ajax request fires and when it finishes. The problem is I don\'t know how to set values for the progress bar depe
Edit: For posterity I've left my previous answer below, but seeing as how it doesn't actually answer the question being asked I'm providing a new answer.
Some of the comments on the question have pointed out newer methods of accomplishing this. Thanks to HTML5 and the newer XHR2 it's possible to put callbacks on the progress of AJAX requests. This involves you adding event listeners to the XHR object and providing callbacks to the appropriate properties. This page has good examples for both upload and download and this git repo looks good and has been updated recently.
Also, if you're really interested in digging into the XHR and overrides, this Mozilla doc post should help out a lot as well. And in fact, this doc post seems to be what the git repo I mentioned was based off of.
Old Answer: This is an age old problem for people writing web apps and while Thilo was right, this is no longer as difficult as it once was. The best (imo) current solution is to "chunk" the files you're uploading and update your progress bar every time you upload a chunk. This SO question and it's answer is a good place to start understanding this concept and even how to apply it to your situation.
But suffice it to say, what you'll do is take the file you're uploading and split it up into smaller pieces on the client side. There are several potential benefits to this, but the primary one in this case is that it allows you to know every time a specified percentage of the file has been uploaded to the server. And obviously every time a chunk is uploaded you can update the progress bar accordingly.
Chunking the file like this also allows you to effectively "pause" or "resume" uploads since you can upload different parts of a file at any given time.
The fundamental problem is that you do not know how long the request is going to take.
For the progress bar, you need to set a percentage, or a number of completed steps.
If you do not want the progress bar to just jump from 0 to 100, you need to have some way to measure the completion rate before the request is finished.
If you can guess how long it takes, you could use a timer to have it incrementally advance to, say, 90%, automatically, and when the server response comes it, set it to 100%. Of course, that is faking it quite a bit.
If you have more than one request, you could use the number of completed requests as a percentage. If it makes sense, you could break down your single request into multiple, but carefully think about the impact this has on network traffic and response times. Don't just do it for the sake of the progress bar.
If the request really takes long, you could fire off additional requests to the server to inquire the progress. But that could mean a lot of work server-side.
Sorry, but progress bars are hard...
i don't use jquery,but this maybe can help you.
It's a Animated Ajax Progress Bar with Fake Fallback.
i just pass a fake size knowing the average size of my scripts
so if my scripts are around 50-100kb i set the fake size to 150kb.
if the computed length is not available i use the fake size.
in this script i added also a extra check that the bar size is always smaller than the container.
simply by multiplying the fake-size *2 .. if its smaller than the loaded data.
to make things look nice i added also a css3 transition effect so that it delays 700ms.
this animation delay adds everything you need to make the progress bar look real.
copy & paste into a html file and check with a modern browser like chrome.
replace YOURSITE with a ajax content site... or whatever.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Ajax Progress</title>
<style>
#progress{
width:300px;
height:20px;
border:1px solid rgba(0,0,0,0.5);
}
#bar{
width:0%;
height:20px;
background-color:green;
-webkit-transition:width 700ms ease;
}
</style>
<script>
var
pb,
fakeSize=100000,//~100kb
progress=function(e){
fakeSize=(e.loaded>fakeSize?(fakeSize*2):fakeSize);//Bonus
var tot=(e.lengthComputable?e.total:fakeSize);
pb.style.width=(100/tot*e.loaded)+'%';
},
onloaded=function(e){
pb.style.width='100%';
},
ajax=function(a,c){
c=new XMLHttpRequest;
c.open('GET',a);
c.onprogress=progress;
c.onload=onloaded;
c.send()
};
window.onload=function(){
pb=document.getElementById('bar');
ajax('YOURSITE');
}
</script>
</head>
<body>
<div id="progress"><div id="bar"></div></div>
</body>
</html>
you basically just need to use the progress function in jquery and then set the bar to 100% when script has loaded.
This should be possible with server side events
I faced this situation in our company's in-house app. It was a critical app and we needed to show progress to the user. So, despite the fact that @Thilo mentioned about network traffic, we had to implement it so that the user could be informed when the long running process was finished and how it progressed over time.
We broke it down to small pieces.
Spawn a thread on the server-side code to run the particular process. For ASP.Net it was like this:
System.Threading.ThreadPool.QueueUserWorkItem(AddressOf MyProcessRoutine, objectParameter)
Within this "MyProcessRoutine" run your long-running code and update a static variable for counter or persist in database, for each step you want to monitor.
Create another function routine which keeps checking this counter and returns the current value. For example: Public Shared Function CheckStatus() As Integer
From your client-side code keep polling this routine say every 5 seconds (depending on how much network traffic you can afford and how much precision you want.
For example: timer = setInterval("MyWebService.CheckStatus();", 500);
In your client-side code, use this returned value (counter) to update your progress bar.
Besides just a counter, you can also return an object containing relevant details like record-id to show the user about where the process is currently at.
Make sure you handle the thread very carefully, handle all possible exceptions and have proper cleanup.