Animated Progress Bars Using MooTools: dwProgressBar

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!


Comments

  1. Umut

    Looks definitely great & I’ll be sharing this with WebResourcesDepot readers in a very short time.

    Thanks.

  2. Tom

    Good job! I will adapt it quickly for jquery

  3. Tarek Mahmud Apu

    Cool!
    thats a great job

  4. Gio

    Great! I’ll use it as soon as possible.

  5. Richard

    Great Resource! You’ve been showcased on RichardCastera.com

  6. Sunil Shrestha

    Great Codes! I’ll use it as soon as possible.

  7. Pieter

    Added this to my delicious, thank you very much.
    May be using this :)

  8. Christian

    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?

  9. david

    @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.

  10. Storeman

    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);
    }

    });

  11. Storeman

    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!

  12. Kaoul

    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.

  13. Max

    Hey David,

    what’s the licence of these progress bar? Can I use it for commercial websites?

    Thanks in advance.

  14. david

    MIT. Use it however and wherever you’d like.

  15. Ruslan Abuzant

    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

  16. owen

    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
    :-)

  17. BobMac

    I’m trying to pass the output of this php variable $progress to your script and not having any luck. Any ideas?

  18. Csaba

    Great sample code and as David said you can use it wherever you want . Cool

  19. Peter Januarius

    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…

  20. Peter Januarius

    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…

  21. Ty

    How do I get this script to preload images?

  22. Greg

    I apologize if this was answered before.
    Can anyone help me implement the preloader for a webpage. Thanks in advance.

  23. Creation sites web

    Very good job :)
    i like it :)

  24. Blog astuces web

    I think i’m going to use into my blog too
    Thanks for sharing

  25. Francois

    I was looking for a progressbar script and I landed on your website. Nice website! Think I am adding it to my bookmarks. But before I do this… ;-)

    Can you please explain how you render these GoogleWebfonts anti aliasing? I have not found a solution to this.

    Thanx in advance!

  26. Oscar

    Great job, it works perfectly.

    Thank you! :-)

  27. Davor Popovic

    and what I need to write in body to get this work??
    I cope paste The MooTools JavaScript: dwProgressBar and copy paste css and MooTools Usage, put all this before head tag, also put the images, link to jquery and its not work for me?? Also can this go to another page when the countdown ends?


Be Heard!

Share your thoughts without being a jerk! And wrap your code in <code> tags, f00!

Name*:
Email*:
Website: