Progress Handler

HTML_Progress

Prev |  | Next
Progress Handler how to control your progress meter You have a long task to execute, and you want to display a progress meter that show the progress of the task. How can you do it ? There are two main way: your task is master and the progress meter is slave (never use a progress callback) your task is slave and the progress meter is master (use a progress callback) # Table of Contents Without Progress callback Use a Progress callback ## Without Progress callback Goal of this example is to simulate packages download (user task). Here is a screenshot of what we will produces : On left frame we find a form used to select what package the user want to download. On right frame we show an horizontal progress bar with results of download process. Code listing 2.2: a package select-download demonstration

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
        "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
      <head>
        <meta name="robots" content="noindex, nofollow" />
        <meta name="keywords" content"="HTML_Progress, PEAR, progress meter" />
        <meta name="description" content"="HTML_Progress " />
        <meta name="author" content="Laurent Laville" />
        <title>Code listing 2.2: a software installation </title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      </head>
      <frameset cols="300, *">
        <frame  name="files" src="listing-2.2.1.php" />
        <frame  name="meter" src="listing-2.2.2.php" scrolling="no" />
        <noframes>
          <body>
            <p>Your browser does not support frames.</p>
          </body>
        </noframes>
      </frameset>
    </html>
Here is the main page: a frameset which contains the two frames : Left (see code listing 2.2.1) and Right (see code listing 2.2.2). Code listing 2.2.1: a package selection

    <?php   // listing-2.2.1.php
    require_once 'HTML/QuickForm.php';

    $form =& new HTML_QuickForm('installer', 'post', $_SERVER['PHP_SELF'], 'meter');

    $form->addElement('header', null, 'Choose PEAR packages to download');

    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'Archive_Tar', null, 'Archive_Tar');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'Config', null, 'Config');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_QuickForm', null, 'HTML_QuickForm');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_CSS', null, 'HTML_CSS');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_Page', null, 'HTML_Page');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_Template_Sigma', null, 'HTML_Template_Sigma');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'Log', null, 'Log');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'MDB', null, 'MDB');
    $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'PHPUnit', null, 'PHPUnit');
    $form->addGroup($checkbox, 'packages', 'Packages:', '<br />');

    $form->addElement('submit', 'submit', 'Download');

    if ($form->validate()) {

        include_once 'listing-2.2.2.php';

        $packages = $form->exportValue('packages');
        $percent = 0;

        echo '<p><font face="Courier">';
        foreach ($packages as $pkg => $bool) {

            $msg = str_pad("Downloading package: $pkg", max(50,21+strlen($pkg)+4), '.');
            print $msg;
            /* Here you have to the job : download the package  */
            sleep(1);    // but as it's a tutorial we do nothing else than wait ...

            print " OK<br/>\n";

            $percent += intval(round(100 / count($packages)));
            $progress->setValue($percent);
            $progress->display();
        }
        echo '</font></p>';

        if ($percent < 100) {
            $progress->setValue(100);
            $progress->display();
        }

    } else {
        $form->display();
    }
    ?>
The form that allows to select what package to download, was built with help of PEAR::HTML_QuickForm package. If you don't know it, i suggest you to read the QuickForm Manual on PEAR website. Let's consider now the important lines in this script: Line 4, the form target is the right frame (meter: see line 17 of code listing 2.2). That will allows results of lines 23 thru 47 to be display in the good place. Line 21, the form is validate. Next (line 25) we extract data to know your package-selection. On lines 29 to 41, we find the master process: download simulation. If we have a real download operation, it should replace the sleep function at line 34. Lines 31 and 32 prepare the result of operation which is given at line 36. Line 38 we compute the next value of the progress bar. We make changes at line 39 and refresh the progress bar at line 40. Code listing 2.2.2: slave-progress pattern

    <?php   // listing-2.2.2.php
    require_once 'HTML/Progress.php';

    $progress = new HTML_Progress();

    $ui = & $progress->getUI();
    $ui->setCellCount(20);
    $ui->setBorderAttributes('width=1 color=#000000');
    $ui->setCellAttributes(array(
            'active-color' => '#970038',
            'inactive-color' => '#FFDDAA',
            'width' => 20,
            'height' => 20
    ));
    ?>
    <!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
    <style type="text/css">
    <!--
    <?php echo $progress->getStyle(); ?>

    body {
        background-color: #FFFFFF;
        color: #000000;
        font-family: Verdana, Arial;
    }
    // -->
    </style>
    <script type="text/javascript">
    <!--
    <?php echo $progress->getScript(); ?>
    //-->
    </script>
    </head>
    <body>

    <?php echo $progress->toHtml(); ?>

    </body>
    </html>
There are not so many changes on this script since Your first Progress Meter. You may notice at least four important differences. No need to slow progress bar animation with HTML_Progress::setAnimSpeed The progress bar has 20 cells long rather than 10 (line 7) We use W3C doctype lines 16 to 20 to avoid IE box model break rules, because we have choosen to display a progress bar with a border (line 8). The cells got a new layout (lines 9 to 14) ## Use a Progress callback Sometimes you can't immediately determine the length of a long-running task. Goal of this example is to display a progress meter in indeterminate mode (while you determines the length of the task), and then switch back in determinate mode to finish the works. Code listing 2.3: master-progress pattern

    <?php
    require_once 'HTML/Progress.php';

    function myProgressHandler($progressValue, &$bar)
    {
        static $c;

        if (!isset($c)) {
            $c = 0;
        }

        $bar->sleep();  // wait 0.5 second

        if ($bar->isIndeterminate()) {

            if ($progressValue == 100) {
                $c++;
                echo "myProgressHandler -> loop #$c <br/>\n";
            }

            /* switch back from indeterminate to determinate mode
               after 3 full loops */
             */
            if ($c == 3) {
                $bar->setIndeterminate(false);
                $bar->setValue(0);
                $bar->setString(null); // re-show percent info
            }
        }
    }

    $progress = new HTML_Progress();
    $ui = & $progress->getUI();
    $ui->setProgressAttributes(array(
        'background-color' => '#e0e0e0'
    ));
    $ui->setStringAttributes(array(
        'color'  => '#996',
        'background-color' => '#CCCC99'
    ));
    $ui->setCellAttributes(array(
        'active-color' => '#996'
    ));

    $progress->setAnimSpeed(500);
    $progress->setIncrement(10);
    $progress->setStringPainted(true);     // get space for the string
    $progress->setString("");              // but don't paint it
    $progress->setIndeterminate(true);     // Progress start in indeterminate mode
    $progress->setProgressHandler('myProgressHandler');
    ?>
    <html>
    <head>
    <title>Listing 2.3 </title>
    <style type="text/css">
    <!--
    body {
        background-color: #CCCC99;
        color: #996;
        font-family: Verdana, Arial;
    }

    <?php echo $progress->getStyle(); ?>
    // -->
    </style>
    <script type="text/javascript">
    <!--
    <?php echo $progress->getScript(); ?>
    //-->
    </script>
    </head>
    <body>

    <?php
    echo $progress->toHtml();
    $progress->run();
    ?>

    </body>
    </html>
The user callback 'myProgressHandler' defined on lines 4 thru 30, present the user-task. We informs HTML_Progress at line 50 to use this user callback. The progress meter will run in indeterminate mode for 3 full loops (equivalent to 300%). This rule is given at line 24. Process go back in determinate mode at line 25. Next (lines 26 and 27) we finish the works with a standard behavior.
Prev | Up | Next
Your first Progress Meter | Getting Started | Advanced Error Handling
Documentation generated on Sun, 12 Sep 2004 20:22:40 +0200 by phpDocumentor 1.3.0RC3