Community Pick: Many members of our community have endorsed this article.
Editor's Choice: This article has been selected by our editors as an exceptional contribution.

A jQuery Progress Bar

Published:
Updated:

Introduction

A frequently asked question goes something like this:  "I am running a long process in the background and I want to alert my client when the process finishes.  How can I send a message to the browser?"  Unfortunately, the short answer is "You can't." This is a restriction of the HTTP client / server protocol. The only time the server can send information to the client is in response to a request.  So it follows that we need a way for the client to request a progress report and a way for the server to send the progress report.  This article sets up the two parts of the application and builds them step-by-step so you can see exactly how this can be done.  We use jQuery and AJAX in a way that allows the client script to call the server-side script and to get back an indicator of progress.


The Visual Effect in the Browser

When we first load the client web page, we will have an area reserved for the progress bar.  As progress occurs (as indicated by the signal from the server) our progress bar will become visible and move across from left to right until the process is completed.  At the end, it will say "All Done" then it will fade from view and collapse out of the web page.  Here are screen-capture examples of the visual effects.  We used very bright colors for this example; your choice of size and color would be made with your design goals in mind.  These are settable via CSS.


Before the process starts:

jquery-progress-bar-1.pngAfter the progress bar appears:

jquery-progress-bar-2.pngAs the progress bar continues to show greater and greater progress:

jquery-progress-bar-3.pngWhen the progress indicator exceeds 99%:

jquery-progress-bar-4.pngAfter "All Done!" the progress bar fades out and disappears from the page:

jquery-progress-bar-5.png

The Server-Side Script

First we will build a simulation of the server side of the two-part application.  The server will sense the progress of our long-running job and will return a single value to the client - an integer, representing the percentage of completion.  In order to simulate the progress, we will use a simple counter which we will keep in the PHP session.  By storing the counter in the session, we can add to it on each request to the server-side script, creating the same effect we might see if the server-side script were taking an actual measurement of our progress toward a goal.  Have a look at line 15.  It's only there to simulate some kind of variation in the reported progress.  In real life, this "counting" scenario would be replaced by some programmatic method of determining the percentage of progress toward our goal.  The determination, however it is made, would be set into a positive integer of range 1-99 which is echo'ed to the browser output stream (and therefore returned to the client-side jQuery script that called our progress monitor).

<?php // demo/jquery_progress_bar_server.php
error_reporting(E_ALL);

// SESSION ALLOWS US TO HAVE STATIC VARIABLES
session_start();

// IF THIS IS THE FIRST STEP, SET THE PROGRESS BAR TO ZERO
if (empty($_SESSION['progress']))
{
    $_SESSION['progress'] = 0;
}

// INCREMENT THE PROGRESS COUNTER
$advance = 10;
$advance = rand(5,10);
$_SESSION['progress'] += $advance;


// IF THIS IS THE LAST STEP, ELIMINATE THE SESSION VARIABLE
if ($_SESSION['progress'] > 99)
{
    unset($_SESSION['progress']);
    session_write_close();
    die('100');
}

// RETURN THE PROGRESS
echo $_SESSION['progress'];

The Client-Side Script

Once we have the server side of the application running, it's time to build the client side (the part that runs in the client's browser).  For this we use a conventional HTML5 web page.  These notes apply to the snippet below.


Line 8: This loads the latest "minified" jQuery framework.


Line 11-13: This starts the progress bar when the document.ready event fires.  In a real-world example, this might be started by a browser event, such as a mouse click.  But for our tests, it is nice to be able to refresh the browser and see the progress bar started immediately.  The script here tells the browser to run the loadProgressBar() function, and to address it to the div named #progressBar.  In theory it would be possible to have multiple progress bars on the page, but for this demonstration, one will do.  Note that for this example to work, the document.ready event handler is not required.  I only put it into the script as a placeholder since some other event might be the initial trigger for the progress bar.


Line 16: Sets the interval value to 1,000 milliseconds (one second).  Each time the interval timer expires, the script will call the server-side script for an update on the progress.  There is no hard-and-fast rule about a one-second interval; you can choose any values that makes sense for your needs.  You might want to experiment with faster or slower values.


Line 17: Sets the interval timer to call the function loadProgressBar() every time the intval expires.


Line 22: Defines the loadProgressBar() function.  The function takes one argument called "element."  This is the name of the outer wrapper div that encapsulates the progress bar.


Line 23: Every time loadProgressBar() is run, it calls the server-side script and retrieves an integer representing the percentage of completion of the background task.  This value is assigned to the JavaScript variable percent.


Line 24-28: If the percentage indicates that the progress is not yet complete, we recompute the width of the progress bar and animate the movement of the dark green background across the bar from left to right.


Line 29-36: When the percentage indicates that progress is complete, we are finished with the progress bar.  We take the following steps.

1. We remove the interval timer -- there is no need to call this function again.

2. We remove the background color from the progress bar.

3. We set the alignment to "center" and write "All Done!" in the middle of the progress bar

4. We use jQuery fade() and hide() functionality to cause the progress bar to act like the Cheshire Cat, disappearing from view.


Line 43-47: Our CSS defines the size and color of #progressBar div.


Line 49-57: Our CSS defines the div inside the #progressBar div.  It starts with a width of zero (which grows with each call to the loadProgressBar() function) and a background-color of dark green.  With this styling and the jQuery .animate() function, we can produce the visual effect of a progress bar that slides more-or-less smoothly across the screen.

 

<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
<script>

$(document).ready(function(){
    loadProgressBar($('#progressBar'));
});

// SET INTERVAL IN MILLISECONDS TO REPEAT THE FUNCTION
var intval   = 1000;
var pBLoader = setInterval(function(){ loadProgressBar($("#progressBar")); }, intval);

// A VARIABLE TO HOLD THE RESPONSE FROM THE BACKGROUND SCRIPT
var percent = 0;

function loadProgressBar(element) {
    $.get("jquery_progress_bar_server.php", function(percent){
        if (percent <= 99){
            var pbWidth = percent * element.width() / 100;
            element.find('div').animate({ width:pbWidth }, 333);
            element.find('div').html(percent + "%&nbsp;");
        } else{
            clearInterval(pBLoader);
            element.css('background-color', 'transparent' );
            element.find('div').css('text-align', 'center' );
            element.find('div').html("All Done!");
            element.fadeTo(3000, 0.2, function(){
                element.hide('slow');
            });
        }
    });
}

</script>

<style type="text/css">
#progressBar {
    width:400px;
    height:22px;
    background-color:yellow;
}

#progressBar div {
    height:100%;
    color:yellow;
    font-family:verdana;
    text-align:right;
    line-height:22px; /* same as #progressBar height if we want text middle aligned */
    width:0;
    background-color:darkgreen;
}
</style>

<title>HTML5 Page with jQuery Progress Bar</title>
</head>
<body>

<div>This is the top content on the page.</div>

<div id="progressBar">
<div></div>
</div>

<div>This is the bottom content on the page.</div>

</body>
</html>


Try It!

Click here to see it in action!  You can copy these scripts and install them on your own server.  You might want to experiment with different colors and animation speeds.  While this looks very simple - just a few lines of code - it gives a strong visual cue.  With an "intelligent" server-side script you can reassure the client that progress is occurring, even if there is nothing to see until the process has been completed.


My Favorite Lazy Alternative

Lazy programmers always seem to come up with really great alternatives to hard-working programmers' solutions.  Their work gives almost 100% of the same results, but with much less work, and in the craft of programming, "lazy" is a virtue!  So what might be a good alternative to the jQuery/AJAX interaction in this example?  How about a spinner that appears at the time an upload is started and disappears when the upload is finished?  The concept is just like the example above, but instead of calling a background script for a progress indicator, we can just load an image like this at the start of the upload, and hide it at the end.  Easy!

https://v.cdn.vine.co/w/ccf87cd9-assets/images/loading_black.gif


Please give us your feedback!

If you found this article helpful, please click the "thumb's up" button below. Doing so lets the E-E community know what is valuable for E-E members and helps provide direction for future articles.  If you have questions or comments, please add them.  Thanks!

 

6
15,596 Views

Comments (1)

Very good!

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.