AJAX progress bar

With few lines of JavaScript and CSS it’s possible to make simple AJAX progress bar. JavaScript will periodically ask for progress value and server will respond with JSON data. Progress value is being read and displayed as DIV element width. To start progress bar demo, click on Start button and wait few seconds to begin. To watch how this page sends requests to Web server just open DOM inspector “Network” card.

 


More precisely, every 1000ms sendRequest() method sends request to server – see setInterval line in pollingStart() method. ajax-progress-bar.php responds and requestHandler() processes received JSON data. Progress value in JSON data has meaning of job completion (in percentage).

In following JavaScript source, please focus on sending and handling requests. Property onreadystatechange is function that receives server feedback. It’s important to note that feedback function must be assigned before each send, because after request is completed, onreadystatechange property is cleared.

// create redips container
let redips = {};

// initialization
redips.init = function () {
    // set reference to the progress bar DIV
    redips.div = document.getElementById('progress');
    // create XML HTTP request object
    redips.xhr = new XMLHttpRequest();
    // set interval ID to false
    redips.intervalID = false;
};

// send request to server
redips.sendRequest = function () {
    let numberMax = 20, // limit number of requests (needed only for demo)
        xhr = redips.xhr;
    // if server is asked less than numberMax
    if (redips.number < numberMax) {
        xhr.open('GET', 'ajax-progress-bar.php', true); // open asynchronus request
        xhr.onreadystatechange = redips.requestHandler; // set request handler
        xhr.send(null);                                    // send request
        redips.number++;                                // increase counter
    }
    // otherwise stop polling
    else {
        redips.pollingStop();
    }
};

// request handler
redips.requestHandler = function () {
    let xhr = redips.xhr;
    // if operation is completed (readyState === 4)
    if (xhr.readyState === XMLHttpRequest.DONE) {
        // if HTTP status is OK
        if (xhr.status === 200) {
            // get progress level from JSON output
            let level = JSON.parse(xhr.responseText).progress;
            // set progress bar width and innerHTML
            redips.div.style.width = redips.div.innerHTML = level + '%';
        }
        // if request status is not OK
        else {
            redips.div.style.width = '100%';
            redips.div.innerHTML = 'Error:[' + xhr.status + ']' + xhr.statusText;
        }
    }
};

// button start
redips.pollingStart = function () {
    if (!redips.intervalID) {
        // reset number of requests
        redips.number = 0;
        // start polling
        redips.intervalID = window.setInterval(redips.sendRequest, 1000);
    }
};

// button stop
redips.pollingStop = function () {
    let xhr = redips.xhr;
    // abort current request if status is 1, 2, 3
    // 0: request not initialized
    // 1: server connection established
    // 2: request received
    // 3: processing request
    // 4: request finished and response is ready
    if (xhr.readyState > 0 && xhr.readyState < 4) {
        xhr.abort();
    }
    window.clearInterval(redips.intervalID);
    redips.intervalID = false;
    // display 'Demo stopped'
    redips.div.style.width = '100%';
    redips.div.innerHTML = 'Demo stopped';
};

// add onload event listener
if (window.addEventListener) {
    window.addEventListener('load', redips.init, false);
}
else if (window.attachEvent) {
    window.attachEvent('onload', redips.init);
}

Here you can see ajax-progress-bar.php source (how job progress is emulated). In your case you will have to calculate percentage of completion and return it in JSON format. Caching for ajax-progress-bar.php should be disabled. Many proxies and clients can be forced to disable caching with “header” lines pragma, cache-control and expires.

<?php
// no cache
header('Pragma: no-cache');
// HTTP/1.1
header('Cache-Control: no-cache, must-revalidate');
// date in past
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
// prepare demo progress value
$progress = (time() % 50) * 2;
// return progress level in JSON format
print "{\"progress\": \"$progress\"}";
?>

Download source code: redips6.tar.gz

11/21/2010 – Code tested with JSLint & enabled source download
06/10/2011 – Added limit of how many times to request the server (automatic demo stop)
26/03/2020 – Code tested with ESLint & changed to use JSON instead of XML

64 thoughts on “AJAX progress bar”

  1. Yes, ajax-progress-bar.php could have only one line and in this case progress value should be taken with responseText method (instead of responseXML). Hmm, but then the post should be called “AJA progress bar”.
    ;)
    I’m just kidding, I wanted to show how is easy to create the XML communication between client JavaScript and PHP backend. This way you can extend XML and send even more data if you want instead of progress value only.

  2. Nice article.

    But I have a question: is it possible to stop sending requests when the progress bar has reached 100%?

    Thanks in advance!

  3. I’ve found the solution myself (maybe I can help some people with it):

    In request_handler, I check if the progress >= 100, if it is so, I call the function polling_stop().

  4. I have want to use your progress bar in my web application. And im using JSP as my client side. How can i generate XML from my JSP. and instead of using mktime() method what should i use. Thanks in advance

  5. Noel,
    I suppose that the simplest way to create XML from the JSP page is with out.println (JSP experts, please correct me). This page is only demo and shows how to display work progress. In your case (instead of mktime) you will have to build some logic in JSP and return percentage of job done.

  6. i made a large mysql insert query (500,000+ insert lines) and i want to show the users how far they’ve gone.
    is it possible to get the current insert point while the insert page is still loading?

  7. Thats a very impressive article. But, how do I implement the same in Asp.net? Can U help me out for this?

  8. @Wilson – I suppose if you have insert in loop, then you can increase progress value after let’s say every 5000 inserts. This progress value should be read in ajax-progress-bar.php. Or just read count(*) of inserted rows, but I’m not sure if MySQL could respond fast with counted rows while inserting at the same time.

    @Ronny – I’m sorry but ASP.NET is not in list of my technologies. Anyway, your main task will be to customize ajax-progress-bar.php to become ajax-progress-bar.aspx (that means to create simple code to output XML). In send_request() function, you will have to rename function call also. I hope that somebody familiar with ASP.NET will help you more.

  9. Great article. But how exactly do you embed that to html code. Say I want to execute a command on the server on the click of a button on the page which javascript function do I need to run. Can you please help. Many thanks!

  10. @Mark – Please see the request_handler() function. After browser got reply from the server, element width changes according to the PROGRESS value in XML. To execute command on the server on the button click, you can use classic post-back approach or you can try with AJAX. AJAX can send request to the server in “background”, so the current page will not refresh. To start with AJAX, you can use initXMLHttpClient(), send_request() and request_handler() functions. Please do not forget to initialize XMLHttpClient object before sending request.

    In this example, ajax-progress-bar.php emulates progress of some server work. Actually, it only generates XML with progress value.

    @Janki – Demo in this post should work in IE6. I test it with IETester and it works. Please try to click on the button “Start” and wait few seconds. Progress bar should grow every 1.5 seconds.

  11. @Nick – ajax-progress-bar.php emulates some job progress. Actually it calculates percentage based on current time for this demo. Simply enough to show a communication between server side and AJAX JavaScript.

  12. I’m an AJAX newb but I think I get most of this.
    I’m just finding the mechanism by which you time a process a little vague.

    If ajax-progress-bar.php was just
    <?php
    $y=0;
    for($x=0;$x

    at what point and how would I enable the above to send anything meaningful to your javascript code?

    Thanks for any clarification,
    R

Leave a Comment