AJAX progress bar

More...

With few lines of JavaScript and CSS you can make a simple AJAX progress bar. JavaScript will periodically ask for progress value and server will respond with XML. Progress value should be extracted from the XML and displayed as width of the DIV element. To start progress bar in this example, please click on the Start button and wait for a second to begin. If you have installed Firebug, open Net tab and watch how this page sends request to the Web server.

More precisely, every 1000ms send_request() function sends request to the server (see setInterval line in polling_start() function). ajax-progress-bar.php returns XML and request_handler() processes received XML. Progress value from XML has meaning of percentage completion of a job.

In the following JavaScript source, please focus to the sending and handling requests. Initialization of the XMLHttpRequest is written in the cross-browser manner and there's nothing more to add. The onreadystatechange property is a function that receives the feedback. It is important to note that the feedback function must be assigned before each send, because upon request completion the onreadystatechange property is reset. This is evident in the Mozilla and Firefox source.

// create XMLHttp request object in a cross-browser manner
initXMLHttpClient = function () {
    var XMLHTTP_IDS,
        xmlhttp,
        success = false,
        i;
    // Mozilla/Chrome/Safari/IE7+ (normal browsers)
    try {
        xmlhttp = new XMLHttpRequest();
    }
    // IE(?!)
    catch (e1) {
        XMLHTTP_IDS = [ 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0',
                        'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ];
        for (i = 0; i < XMLHTTP_IDS.length && !success; i++) {
            try {
                success = true;
                xmlhttp = new ActiveXObject(XMLHTTP_IDS[i]);
            }
            catch (e2) {}
        }
        if (!success) {
            throw new Error('Unable to create XMLHttpRequest!');
        }
    }
    return xmlhttp;
};

// send request to the server
send_request = function () {
    if (number < number_max) {
        request.open('GET', 'ajax-progress-bar.php', true); // open asynchronus request
        request.onreadystatechange = request_handler;       // set request handler
        request.send(null);                                 // send request
        number++;                                           // increase counter
    }
    else {
        polling_stop();
    }
};

// request handler (started from send_request)
request_handler = function () {
    var level;
    if (request.readyState === 4) {   // if state = 4 (operation is completed)
        if (request.status === 200) { // and the HTTP status is OK
            // get progress from the XML node and set progress bar width and innerHTML
            level = request.responseXML.getElementsByTagName('PROGRESS')[0].firstChild;
            progress.style.width = progress.innerHTML = level.nodeValue + '%';
        }
        else { // if request status is not OK
            progress.style.width = '100%';
            progress.innerHTML = 'Error:[' + request.status + ']' + request.statusText;
        }
    }
};

// button start
polling_start = function () {
    if (!intervalID) {
        // set initial value for current number of requests
        number = 0;
        // start polling
        intervalID = window.setInterval('send_request()', 1000);
    }
};

// button stop
polling_stop = function () {
    // 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 (0 < request.readyState && request.readyState < 4) {
        request.abort();
    }
    window.clearInterval(intervalID);
    intervalID = false;
    // display 'Demo stopped'
    progress.style.width = '100%';
    progress.innerHTML = 'Demo stopped';
};

Here you can see the source of ajax-progress-bar.php (how is job progress emulated). In your case you will have to calculate percentage of completion and return it in XML 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 the past
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
// define XML content type
header('Content-type: text/xml');
// print XML header
print '<?xml version="1.0"?>';
// prepare demo progress value
$progress = (mktime() % 50) * 2;
?>
<DOCUMENT><PROGRESS><?php print $progress ?></PROGRESS></DOCUMENT>

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)

This entry was posted on May 14, 2009 and is filed under JavaScript

Related posts

61 Responses to AJAX progress bar

  1. Said says:

    I just wana thank you for your JS snippet it war very helpful for me.

    Using it i proceed a large traitement that takes 2 hours It works perfectely on mozila and chrome

    but the internet explorer obort the XMLHttpRequests.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

In case of posting HTML tags or JavaScript code please convert special characters to HTML entities.
Especially pay attention to convert "<" character to "&lt;" entity!