HTML_Progress
[ class tree: HTML_Progress ] [ index: HTML_Progress ] [ all elements ]
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:

  1. your task is master and the progress meter is slave (never use a progress callback)
  2. your task is slave and the progress meter is master (use a progress callback)

Table of Contents

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

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE html
  3. PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
  4. "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
  5.  
  6. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  7. <head>
  8. <meta name="robots" content="noindex, nofollow" />
  9. <meta name="keywords" content"="HTML_Progress, PEAR, progress meter" />
  10. <meta name="description" content"="HTML_Progress " />
  11. <meta name="author" content="Laurent Laville" />
  12. <title>Code listing 2.2: a software installation </title>
  13. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  14. </head>
  15. <frameset cols="300, *">
  16. <frame name="files" src="listing-2.2.1.php" />
  17. <frame name="meter" src="listing-2.2.2.php" scrolling="no" />
  18. <noframes>
  19. <body>
  20. <p>Your browser does not support frames.</p>
  21. </body>
  22. </noframes>
  23. </frameset>
  24. </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

  1. <?php // listing-2.2.1.php
  2. require_once 'HTML/QuickForm.php';
  3.  
  4. $form =& new HTML_QuickForm('installer', 'post', $_SERVER['PHP_SELF'], 'meter');
  5.  
  6. $form->addElement('header', null, 'Choose PEAR packages to download');
  7.  
  8. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'Archive_Tar', null, 'Archive_Tar');
  9. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'Config', null, 'Config');
  10. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_QuickForm', null, 'HTML_QuickForm');
  11. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_CSS', null, 'HTML_CSS');
  12. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_Page', null, 'HTML_Page');
  13. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'HTML_Template_Sigma', null, 'HTML_Template_Sigma');
  14. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'Log', null, 'Log');
  15. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'MDB', null, 'MDB');
  16. $checkbox[] = &HTML_QuickForm::createElement('checkbox', 'PHPUnit', null, 'PHPUnit');
  17. $form->addGroup($checkbox, 'packages', 'Packages:', '<br />');
  18.  
  19. $form->addElement('submit', 'submit', 'Download');
  20.  
  21. if ($form->validate()) {
  22.  
  23. include_once 'listing-2.2.2.php';
  24.  
  25. $packages = $form->exportValue('packages');
  26. $percent = 0;
  27.  
  28. echo '<p><font face="Courier">';
  29. foreach ($packages as $pkg => $bool) {
  30.  
  31. $msg = str_pad("Downloading package: $pkg", max(50,21+strlen($pkg)+4), '.');
  32. print $msg;
  33. /* Here you have to the job : download the package */
  34. sleep(1); // but as it's a tutorial we do nothing else than wait ...
  35.  
  36. print " OK<br/>\n";
  37.  
  38. $percent += intval(round(100 / count($packages)));
  39. $progress->setValue($percent);
  40. $progress->display();
  41. }
  42. echo '</font></p>';
  43.  
  44. if ($percent < 100) {
  45. $progress->setValue(100);
  46. $progress->display();
  47. }
  48.  
  49. } else {
  50. $form->display();
  51. }
  52. ?>

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

  1. <?php // listing-2.2.2.php
  2. require_once 'HTML/Progress.php';
  3.  
  4. $progress = new HTML_Progress();
  5.  
  6. $ui = & $progress->getUI();
  7. $ui->setCellCount(20);
  8. $ui->setBorderAttributes('width=1 color=#000000');
  9. $ui->setCellAttributes(array(
  10. 'active-color' => '#970038',
  11. 'inactive-color' => '#FFDDAA',
  12. 'width' => 20,
  13. 'height' => 20
  14. ));
  15. ?>
  16. <!DOCTYPE html
  17. PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  18. "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  19.  
  20. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  21. <head>
  22. <style type="text/css">
  23. <!--
  24. <?php echo $progress->getStyle(); ?>
  25.  
  26. body {
  27. background-color: #FFFFFF;
  28. color: #000000;
  29. font-family: Verdana, Arial;
  30. }
  31. // -->
  32. </style>
  33. <script type="text/javascript">
  34. <!--
  35. <?php echo $progress->getScript(); ?>
  36. //-->
  37. </script>
  38. </head>
  39. <body>
  40.  
  41. <?php echo $progress->toHtml(); ?>
  42.  
  43. </body>
  44. </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

  1. <?php
  2. require_once 'HTML/Progress.php';
  3.  
  4. function myProgressHandler($progressValue, &$bar)
  5. {
  6. static $c;
  7. if (!isset($c)) {
  8. $c = 0;
  9. }
  10.  
  11. $bar->sleep(); // wait 0.5 second
  12.  
  13. if ($bar->isIndeterminate()) {
  14.  
  15. if ($progressValue == 100) {
  16. $c++;
  17. echo "myProgressHandler -> loop #$c <br/>\n";
  18. }
  19.  
  20. /* switch back from indeterminate to determinate mode
  21. after 3 full loops */
  22. */
  23. if ($c == 3) {
  24. $bar->setIndeterminate(false);
  25. $bar->setValue(0);
  26. $bar->setString(null); // re-show percent info
  27. }
  28. }
  29. }
  30.  
  31. $progress = new HTML_Progress();
  32. $ui = & $progress->getUI();
  33. $ui->setProgressAttributes(array(
  34. 'background-color' => '#e0e0e0'
  35. ));
  36. $ui->setStringAttributes(array(
  37. 'color' => '#996',
  38. 'background-color' => '#CCCC99'
  39. ));
  40. $ui->setCellAttributes(array(
  41. 'active-color' => '#996'
  42. ));
  43.  
  44. $progress->setAnimSpeed(500);
  45. $progress->setIncrement(10);
  46. $progress->setStringPainted(true); // get space for the string
  47. $progress->setString(""); // but don't paint it
  48. $progress->setIndeterminate(true); // Progress start in indeterminate mode
  49. $progress->setProgressHandler('myProgressHandler');
  50. ?>
  51. <html>
  52. <head>
  53. <title>Listing 2.3 </title>
  54. <style type="text/css">
  55. <!--
  56. body {
  57. background-color: #CCCC99;
  58. color: #996;
  59. font-family: Verdana, Arial;
  60. }
  61.  
  62. <?php echo $progress->getStyle(); ?>
  63. // -->
  64. </style>
  65. <script type="text/javascript">
  66. <!--
  67. <?php echo $progress->getScript(); ?>
  68. //-->
  69. </script>
  70. </head>
  71. <body>
  72.  
  73. <?php
  74. echo $progress->toHtml();
  75. $progress->run();
  76. ?>
  77.  
  78. </body>
  79. </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