A Dynamic Progress Bar for your ASP Pages

By Peter A. Bromberg, Ph.D.

Peter Bromberg  

If you have a long - running query or other processing operation going on in an ASP page, with no visual feedback to the user while they are waiting, this can cause problems. People might quit the page, thinking there is something wrong, or at a minimum, it can cause some confusion while they are waiting, wondering what is going on.

Here I'll present an elegant, adaptible way to show a "progress bar" to your users that you can update at a frequency that you choose. My solution is "code only", and best of all, it requires NO GRAPHICS or external pages of any kind!

The easiest way to understand how this works is to simply step through the code, so let's do it:



At the top of your page, you'll want to turn off Response object buffering, and optionally to set the Server Script timeout to a large number if you have a particularly long - running processing operation:
<%
Response.Buffer = False
Server.ScriptTimeout =25000
%>

Next, we render a div that holds our progress bar object. Note that this is outside the ASP server-side script tags so it gets rendered as HTML when the page is loaded:

<div id="ProgBar" style="font-family:Verdana; font-size=9pt;">Progress:<BR>
<TABLE style="color:red;" HEIGHT="16" Border=1><TR><TD BGCOLOR=RED ID=statuspic></TD></TR></TABLE><BR>
</div>

Next, we write out a script block that instantiates our progBarWidth variable:

<script language="Javascript">var progBarWidth=250;</script>

Finally, we have our ASP Script block that does the actual "meat" of the operation:

<%
iProcessedSoFar = 0
iTotalRecords = 200
strHTML=" <Table width=""80%""><TR><TD Width=""100%"" BGCOLOR=""gray"" align=""CENTER"">Results:<td></tr>"
for i = 0 to iTotalRecords
' next few lines are just a surrogate for whatever your processing function to be timed
strHTML = strHTML & "<tr width=""100%""><td width=""100%"" BGCOLOR=""#FFCC66""> Your results</td></tr>"
iProcessedSoFar = iProcessedSoFar + 1
pctComplete = (iProcessedSoFar / iTotalRecords)
if i mod 8 = 0 then
ShowProgress pctComplete
end if
next
FinishProgress
strHTML=strHTML & "</TABLE>"
Response.write strHTML
Sub ShowProgress(nPctComplete)
Response.Write "<SCR" & "IPT LANGUAGE=""JavaScript"">" & vbCrlf
Response.Write "statuspic.width = Math.ceil(" & nPctComplete & " * progBarWidth);" & vbCrlf
Response.Write "</SCR" & "IPT>"
End Sub
Sub FinishProgress
Response.Write "<SCR" & "IPT LANGUAGE=""JavaScript"">" & vbCrlf
Response.Write "ProgBar.style.visibility ='hidden';" & vbCrLf
Response.Write "</SCR" & "IPT>"
end sub

%>

Now how does this work? We've rendered a small table to our page, contained inside a "<DIV>" tag with an ID of "ProgBar". When we enter our ASP processing loop, we set the iProcessedSoFar variable to zero, and we set the number of total records we will process (This could be such as rs.recordcount, etc.).

Each time we process a record or whatever our time-consuming operation is, we increment the iProcessedSoFar variable, and compute a new value for the pctComplete variable, e.g. "pctComplete = (iProcessedSoFar/iTotalRecords)". Then in this particular scenario I don't want to do a progress bar update on every single iteration, so I test with "if i mod 8 = 0" (i.e., only do an update if this iteration is evenly divisible by 8) before calling the ShowProgress subroutine, passing the parameter of my latest value for pctComplete.

Each time it's called, ShowProgress writes out a new Script block (note we split up the "<SCR" + "IPT... tags so the script engine doesn't choke) which dynamically RESETS the width property of the statuspic element, which is the <TD> element of our table that's colored, in this case, "red". In effect, what happens is that we get a client-side updating DHTML table display that is controlled by our SERVER SIDE script operation. Finally, when the processing is finished, we call a second sub "FinishProgress" that sets the visibility of the ProgBar element to "hidden", making it disappear from view so that the presentation (result of all our processing) can be displayed.

Copy and paste the entire code below, save it as "ProgBar.asp" and you can try it out for yourself.


<%
Response.Buffer = False
server.scriptTimeout =25000
%>
<div id="ProgBar" style="font-family:Verdana; font-size=9pt;">Progress:<BR>
<TABLE style="color:red;" HEIGHT="16" Border=1><TR><TD BGCOLOR=RED ID=statuspic></TD></TR></TABLE><BR>
</div>
<script language="Javascript">var progBarWidth=250;</script>
<%
iProcessedSoFar = 0
iTotalRecords = 200
strHTML=" <Table width=""80%""><TR><TD Width=""100%"" BGCOLOR=""gray"" align=""CENTER"">Results:<td></tr>"
for i = 0 to iTotalRecords
' next few lines are just a surrogate for whatever your processing function to be timed
strHTML = strHTML & "<tr width=""100%""><td width=""100%"" BGCOLOR=""#FFCC66""> Your results</td></tr>"
iProcessedSoFar = iProcessedSoFar + 1
pctComplete = (iProcessedSoFar / iTotalRecords)
if i mod 8 = 0 then
ShowProgress pctComplete
end if
next
FinishProgress
strHTML=strHTML & "</TABLE>"
Response.write strHTML
Sub ShowProgress(nPctComplete)
Response.Write "<SCR" & "IPT LANGUAGE=""JavaScript"">" & vbCrlf
Response.Write "statuspic.width = Math.ceil(" & nPctComplete & " * progBarWidth);" & vbCrlf
Response.Write "</SCR" & "IPT>"
End Sub
Sub FinishProgress
Response.Write "<SCR" & "IPT LANGUAGE=""JavaScript"">" & vbCrlf
Response.Write "ProgBar.style.visibility ='hidden';" & vbCrLf
Response.Write "</SCR" & "IPT>"
end sub
%>

NOTE: If you would like to see a similar solution for ASP.NET, visit this article.

 

 

Peter Bromberg is an independent consultant specializing in distributed .NET solutions in Orlando and a co-developer of the NullSkull.com developer website. He can be reached at info@eggheadcafe.com