Animated Progress Bars Using MooTools: dwProgressBar
Written by David Walsh on Monday, July 7, 2008
Click here to learn what has changed to make your code framework-compatible.

I love progress bars. It’s important that I know roughly what percentage of a task is complete. I’ve created a highly customizable MooTools progress bar class that animates to the desired percentage.
The Moo-Generated XHTML
<div id="this.options.boxID">
<div id="this.options.percentageID"></div>
</div>
<div id="this.options.displayID">{x}%</div>
This DIV structure is extremely simple and can be controlled completely by CSS.
The CSS
/* these selector names are based on what you provide to the class */
/* example 1 */
#box { border:1px solid #ccc; width:200px; height:20px; }
#perc { background:#ccc; height:20px; }
/* example 2 */
#box2 { background:url(progress-bar-back.gif) right center no-repeat; width:200px; height:20px; float:left; }
#perc2 { background:url(progress-bar.gif) right center no-repeat; height:20px; }
#text { font-family:tahoma, arial, sans-serif; font-size:11px; color:#000; float:left; padding:3px 0 0 10px; }
You’ll declare styles for the three generated XHTML elements. You’ll like use background colors and background images. You will also want to define a width value for the outside box.
The MooTools JavaScript: dwProgressBar
//class is in
var dwProgressBar = new Class({
//implements
Implements: [Options],
//options
options: {
container: $$('body')[0],
boxID:'',
percentageID:'',
displayID:'',
startPercentage: 0,
displayText: false,
speed:10
},
//initialization
initialize: function(options) {
//set options
this.setOptions(options);
//create elements
this.createElements();
},
//creates the box and percentage elements
createElements: function() {
var box = new Element('div', { id:this.options.boxID });
var perc = new Element('div', { id:this.options.percentageID, 'style':'width:0px;' });
perc.inject(box);
box.inject(this.options.container);
if(this.options.displayText) {
var text = new Element('div', { id:this.options.displayID });
text.inject(this.options.container);
}
this.set(this.options.startPercentage);
},
//calculates width in pixels from percentage
calculate: function(percentage) {
return ($(this.options.boxID).getStyle('width').replace('px','') * (percentage / 100)).toInt();
},
//animates the change in percentage
animate: function(to) {
$(this.options.percentageID).set('morph', { duration: this.options.speed, link:'cancel' }).morph({width:this.calculate(to.toInt())});
if(this.options.displayText) {
$(this.options.displayID).set('text', to.toInt() + '%');
}
},
//sets the percentage from its current state to desired percentage
set: function(to) {
this.animate(to);
}
});
The class accepts the following options:
- container: element that the entire progress bar gets placed in
- boxID: the IDof the progress bar’s containing DIV
- percentageID: the ID of the progress bar’s animated/sliding DIV
- displayID: the ID of the progress bar’s “{x} %” text DIV
- startPercentage: the percentage at which you’d like the progress bar to start at (defaults to 0)
- displayText: Boolean. Do you want the progress bar to show the percentage in text format too?
- speed: speed of the animation to the given percentage
MooTools Usage
//once the DOM is ready
window.addEvent('domready', function() {
/* create the progress bar for example 1 */
pb = new dwProgressBar({
container: $('put-bar-here'),
startPercentage: 25,
speed:1000,
boxID: 'box',
percentageID: 'perc'
});
/* create the progress bar for example 2 */
pb2 = new dwProgressBar({
container: $('put-bar-here2'),
startPercentage: 10,
speed:1000,
boxID: 'box2',
percentageID: 'perc2',
displayID: 'text',
displayText: true
});
/* move the first progress bar to 55% */
pb.set(55);
/* move the second progress bar to 89% */
pb2.set(89);
});
All you need to do is create an instance of the dwProgressBar and pass your desired options. It’s quick and easy. To move the progress bar, all you need to do is call the “set()” method, passing it the desired percentage.
Practical Uses
You could use this progress bar for:
- An image preloading script
- Form completion tracking
- Internal goal tracking applications
- Anything you want!
I’ve made the progress bar as flexible as possible by allowing the developer to format each generated DIV using CSS.
Also, please feel free to make suggestions for the class. I may implement them in the future!
Epic Discussion
Be Heard!
I want to hear what you have to say! Share your comments and questions below.
Looks definitely great & I’ll be sharing this with WebResourcesDepot readers in a very short time.
Thanks.
Good job! I will adapt it quickly for jquery
Cool!
thats a great job
Great! I’ll use it as soon as possible.
Great Resource! You’ve been showcased on RichardCastera.com
Great Codes! I’ll use it as soon as possible.
I really like this but have little clue how to put this into my page, what would be good (you might roll your eyes at this suggestion), would be to provide a simple field where you enter your webpage and it scans the code and just spits out a new version with everything added in.
I’m completely naff at coding so even though our layout is clean I don’t know where to c&p stuff, the XHTML? where does that go, in the header??
Added this to my delicious, thank you very much.
May be using this :)
hi, nice script but it doesn’t work with the 1.11 libary! have you a idee to customize the script for the 1.11?
@Christian: The problem is likely due to the fact that Moo 1.1 didn’t use the “set()” functionality. You’ll need to go back and look at the 1.1 docs.
Nice job!
I would recommend some enhancements, instead of ID’s I would recommend using classnames. So multiple instances can be created. The elements can be stored inside the class. I also used a template for displaying and added message-support. Not such a big difference, but I thought I should share ;).
/*
Class: dwProgress bar
Author: David Walsh / Edited by Storeman
Website: http://davidwalsh.name
Version: 1.1b
Date: 27/01/2009
Built For: MooTools 1.2.1
*/
//class is in
var dwProgressBar = new Class({
box: null,
perc: null,
display:null,
msg: null,
//implements
Implements: [Options],
//options
options: {
container: $$(‘body’)[0],
boxClass:”,
percentageClass:”,
displayClass:”,
startPercentage: 0,
displayText: false,
speed:10,
template: ‘{x}% {msg}’
},
//initialization
initialize: function(options) {
//set options
this.setOptions(options);
//create elements
this.createElements();
},
//creates the box and percentage elements
createElements: function() {
this.box = new Element(‘div’, { class:this.options.boxClass });
this.perc = new Element(‘div’, { class:this.options.percentageClass, ‘style’:'width:0px;’ });
this.perc.inject( this.box );
this.box.inject(this.options.container);
if(this.options.displayText) {
this.display = new Element(‘div’, { class:this.options.displayClass });
this.display.inject(this.options.container);
}
this.set(this.options.startPercentage);
},
//calculates width in pixels from percentage
calculate: function(percentage) {
return (this.box.getStyle(‘width’).toInt() * (percentage / 100)).toInt();
},
//animates the change in percentage
animate: function(to) {
this.perc.set(‘morph’, { duration: this.options.speed, link:’cancel’ }).morph({width:this.calculate(to.toInt())});
if(this.options.displayText) {
text = this.options.template.replace(‘{x}’, to.toInt() ).replace(‘{msg}’, this.msg );
this.display.set(‘text’, text );
}
},
//sets the percentage from its current state to desired percentage
set: function(to, msg) {
if( !msg ) this.msg = ”;
else this.msg = msg;
this.animate(to);
}
});
I’m sorry for posting again, I’m using it with Zend Framework (Zend_Progressbar)
PHP – The Action:
public function demoAction(){
$this->_helper->viewRenderer->setNoRender(true);
$this->view->layout()->disableLayout( true );
$pb = new Zend_ProgressBar( new Zend_ProgressBar_Adapter_JsPush(array(
)) );
for( $i=0; $i<10; $i++){
$pb->next( 10, ‘Ronde ‘ . $i );
sleep(1);
}
}
PHP – The View:
<?php ob_start(); ?>
<h2>Progressbar – demo</h2>
<div id=”pbContainer”>
</div>
<iframe src=”<?=$this->url( array_merge($this->params, array(‘action’=>’demo’) ) )?>” style=”left:-100px; top:-100px; width:1px; height:1px; position:absolute”>
</iframe>
<?php
$this->layout()->mainContent = ob_get_clean();
$this->layout()->setLayout(‘default’);
$this->layout()->menu = $this->layout()->render(‘adminmenu’);
$this->headScript()->appendFile( $this->url->js . ‘/progressbar.js’ );
$this->headScript()->captureStart()?>
var pb;
window.addEvent(‘domready’, function(){
pb = new dwProgressBar({
container: $(‘pbContainer’),
boxClass: ‘progress_box’,
percentageClass: ‘progress_percentage’,
displayClass: ‘progress_display’,
startPercentage: 0,
speed: 1000,
displayText: true
});
});
function Zend_ProgressBar_Update(data){
pb.set( data.percent, data.text );
}
<?php $this->headScript()->captureEnd();
Some stuff I just personal, but it’ll get everyone started, note that the view belongs to another action!
In your class, in function createElements, I added :
if ($(“text”)) $(“text”).dispose();
Because when you have a succession of progressBars, the last text is not cleared and you have multiple XHTML elements with the same id brrrr.
With something like this, the css stay on the road and DOM is respected.
Hey David,
what’s the licence of these progress bar? Can I use it for commercial websites?
Thanks in advance.
MIT. Use it however and wherever you’d like.
Hello,
Thought you might be interested to see a website where your component is used or maybe give it a review or something. I made a forex prices and trend analysis tool that you can see at http://www.forex-prices.com/
Have a nice day, Ruslan
Hi,
Is there any way to create a nice looking percentage bar to preload all images / content on a HTML page, and then show that page once everything is cached?
You seem to know what you’re talking about, whereas I don’t
:-)
I’m trying to pass the output of this php variable $progress to your script and not having any luck. Any ideas?
Great sample code and as David said you can use it wherever you want . Cool
Excellent job. Easy to use. I was wracking my brains what to do on my initial load of my webapp. Your progress bar fitted in without any problems. Using Mootools 1.2.1 and jQuery.
Cheers
Pete…
I added a text header that I called ‘pretext’ which appears above the progress bar:
So the options object looks like this:
options: {
container: $$(‘body’)[0],
boxID:”,
percentageID:”,
displayID:”,
textID:”,
startPercentage: 0,
displayText: false,
speed:10,
pretext:”"
}
CreateElements looks like this:
//creates the box and percentage elements
createElements: function() {
var tbox = new Element(‘div’, { id: this.options.textID, ‘style’:'display:inline;float:left’ });
tbox.innerHTML = this.options.pretext;
var box = new Element(‘div’, { id:this.options.boxID });
var perc = new Element(‘div’, { id:this.options.percentageID, ‘style’:'width:0px’ });
perc.inject(box);
tbox.inject(this.options.container);
box.inject(this.options.container);
if(this.options.displayText) {
var text = new Element(‘span’, { id:this.options.displayID });
text.inject(this.options.container);
}
this.set(this.options.startPercentage);
},
Note that I added the ‘tbox’ Element
I like your component but I don’t like MooTools. It is so unintuitive. The ‘inject’ method is from some upside down world – possibly the Mr Men.
Cheers
Pete…
How do I get this script to preload images?
I apologize if this was answered before.
Can anyone help me implement the preloader for a webpage. Thanks in advance.
Very good job :)
i like it :)
I think i’m going to use into my blog too
Thanks for sharing