Application
    development
         is the
    union
         of
 creativity & logic.

A Simple Progress Bar in Drupal Using CSS

[Drupal and Web Development]

I recently responded to a Drupal forum question about adding a simple, visual progress bar to a website. While there are plenty of libraries for sophisticated graphing, since the user had a simple problem I proposed a simple solution based on just a little HTML and CSS.

The user wanted the value of the progress bar to be based on a number stored in his Drupal custom content type. So, I had him create a new theme file named “node-project.tpl.php" and add code to pull out the value and create a two DIV set. The outer DIV is the progress bar container, and the inner DIV displays the progress value.

Since you can’t directly program CSS, the solution uses an in-line style element. While normally you strive to avoid using these, in this case we are limiting its use to controlling only the width of the inner DIV; we will control all over attributes in the CSS, where they belong.

Note that the PHP code includes checks of the progress value. Since the progress is intended to be a percent, it must be a valid number must be between 0 and 100. It also invokes the round() function to ensure it uses a whole number.

<?php
$style = 'display: none;';
$progress = $node->field_progress[0]['value'];
if( is_numeric($progress) && $progress > 0 && $progress <= 100 ) {
  $style = "width: ".round($progress)."%; display: block";
}
?>

Below that, add the HTML with the embedded results of the above variables:

<div id="progress-wrapper">
  <div id="progress-value" style="<?php print $style; ?>"></div>
<div>

Now the solution needs some CSS to make it look like a progress bar. Start with a basic style - just a black border with a gray filling:

<style>
#progress-wrapper {
  border: 1px solid #000000;
  background-color: transparent;
  width: 100px;
  height: 16px;
}
#progress-value {
  background-color: #acacac;
  height: 16px;
}
</style>

Progress (25%)

If you want something fancier, use a gradient image and softer colors:

<style>
#progress-wrapper {
  border: 1px solid #e4e4e4;
  background-color: transparent;
  width: 100px;
  height: 16px;
}
#progress-value {
  background: #ebebeb url(images/progress_bar.gif) repeat-x;
  height: 16px;
}
</style>

Progress (25%)

Have a simple problem? Use a simple solution.

Oh, nice!! This progress bar looks real slick :]

I know exactly where I want to put this, I've got an old drupal site that I can really spice up with this thing

Thank you

I hope it works well for you.

Where do you put the code?

Hi:

I'm using Drupal 6 and your code looks useful for me...however, I don't know where I should put this code in my module...I've not done CSS stuff in Drupal yet...

thanks,
Mona

TPL and CSS Files

Hi Mona,

There are two different places where you put the code.

The first two code samples are put into whatever .tpl file is relevant - this is likely node.tpl.php, or a derivative such as node-project.tpl.php. Note that the "progress" value is just an example used in the code - this can come from a CCK field, or be computed in any number of ways; you'll need to apply your own logic to get or compute the value used for the progress.

The 2nd code goes into your site's CSS. Most themes have a default "style.css" file that you can put it into. The first code sample you can copy-and-paste as-is and it will look like the first example. For the 2nd example, you can copy-and-paste the CSS put you'll also need to grab the gradient file. If you wish, you are welcome to take the one off my site:

http://www.enterana.com/sites/default/files/images/progress_bar.gif

Just make sure that wherever you save the file matches the path in the CSS.

Good luck!

Thanks!

Thanks Steve!

I just realized that this isn't quite what I needed...I think this is to display a status. What I need is more a moving progress bar that will start and end while my module is doing something.

Adjust the width on the fly

This technique can be further modified to act as a dynamic progress meter. Just adjust the "width" value on the fly as the progress proceeds.

Here is a simple example implementing the AJAX Fileuploader library, which includes a callback function for the progress of a file upload. Note that this is Drupal-agnostic - the technique can be used with any function that returns a numeric % of progress.

var uploader = new qq.FileUploader({
  element: document.getElementById('file-uploader'),
  action: '/server/upload',
  onProgress: function(id, fileName, loaded, total){
    // Check that the total is a valid number between 0 and 100
    if(!isNaN(total) && total > 0 && total <= 100 ) {
      var width = total.toString + '%';
      $('#progress-value').css{'width': width});
    }
  },
});

Every time the "onProgress" function is called, it supplies a "total" value which is used to set the width of the progress meter.

inputting the percentage

I am just starting out in Drupal, so this could just be a sign of my naivety. I think that I have all the code in place including the project content type, the node-project.tpl.php and the css snippets in the style.css of my theme. The problem that I am coming up against though is that I can not find the text field where I can input the progress percentage in the project content type. Do I need to also create a new field that connects with the php in node-project.tpl.php?

Field must exist or be computed

In my example, we added a custom field to the Content type and the user can simply enter a value as desired. However, a custom module could create any kind of computed value in lieu of a hard-coded field if your needs require that instead. The point is just that the $node object have some kind of value that is used in the progress bar.

Number of tickets sold

Thanks for your tutorial.How do I apply this to display the number of particular product sold. Example if I want to display below a "concert or event" product type the number of tickets sold so far?
Thanks
Bmanuel

Use any number that can be expressed as a percent

The technique relies on computing a % value (0 - 100) which is simply used as the "width" property of the progress bar.

So, if you want to use this for the Number of Tickets sold, you would need to compute that as a percent of the Number of Available Tickets. This percent value is what you would output to the "width" property.

quick thanks!

Thanks mate! from Australia!

Cheers,

Arthur