When your page performs long tasks it's very important to let the visitor know something takes a little longer than expected and patience is required. Many of them will tend to reload or even close the page thinking it's buggy or blocked. To avoid that and ensure they get the message you can use a progress bar as an indicator.
This can be easily done using javascript and may look like a silly post to you but it's actually harder than you think to represent a running task with a progress bar. You have a lot of examples on the internet but when you try to chain a real script running a real task with the actual progress bar it gets complicated.
Normally, in PHP, whatever you echo will be sent to the browser only when the script finishes it's job and not progressive. Let's consider the following loop as an example:
for ( $i = 0; $i < 10; $i++ )
{
echo $i . "<br>";
sleep(1);
}
Running this code will keep your browser busy for 10 seconds without echoing anything. So how are we supposed to display a progress of a task if the content is made available only when the script finishes?
First, let's create the code for our progress bar. We'll use pure css to display it. No background images or flash funky things, just 2 divs and some css code. One div will serve as the wrapper and will have a border to represent the progress container. The other div, placed inside the first will serve as the progress metter and will have a different background color.
<div class="progress_wrapper"> <div class="progress" style="width:0px;"></div> </div>
CSS code:
.progress_wrapper {width:300px;border:1px solid #ccc;position:absolute;top:200px;left:50%;margin-left:-150px}
.progress {height:20px;background-color:#000}
It's very important to make our wrapper div positioned absolute. If you're having problems keeping it at a very specific place on your page you can place the code inside another element with a relative position. This way you will change the top, left coordinates to that element instead of the page body.
As you can see, I used 50% as the distance from the left coordinate to the start of the progress bar. Adding a 'margin-left' of minus half of the element's length will center it.
You're probably wondering why I'm using the absolute positioning. Well, what if I tell you that PHP can be tweaked to send content to the browser even if it's job didn't finished yet? With this possibility in mind, we can send multiple instances of the same code and, having an absolute position, place them on top of each other. Basically, the current progress bar will be under the next and so on until it reaches an end.
We will have to use 'ob_start' to turn on output buffering before the loop, 'ob_flush' and 'flush' to send the content to the browser after each iteration:
ob_start ();
for ( $i = 0; $i < 10; $i++ )
{
echo $i . "<br>";
ob_flush();
flush();
sleep(1);
}
Having this working as needed, it's time to prepare our content and place it inside the loop to actually display a working progress bar:
ob_start ();
$width = 0; // the starting width
$percentage = 0; // the starting percentage
$total_iterations = 10; // the number of iterations to perform
$width_per_iteration = 300 / $total_iterations; // how many pixels should the progress div be increased per each iteration
for ( $i = 0; $i <= $total_iterations; $i++ )
{
echo '<div class="progress_wrapper"><div class="progress" style="width:' . $width_per_iteration . 'px;"></div></div>';
$width += $width_per_iteration;
ob_flush();
flush();
sleep(1);
}
Following the same criteria it's easy to add an indicator to show the percentage done, a background image to pretty up the bar a little bit and many other things.
Here's a demo of the script running and also a download link.
