|
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 EggheadCafe.com
developer website. He can be reached at pbromberg@yahoo.com
|