Create a Progress Bar With Javascript

Create a Progress Bar With Javascript

The Progress Bar is one of the latest components to be added to the excellent library of UI widgets and interaction helpers built on top of jQuery. It was introduced in the latest version of the library, which at the time of writing is 1.7.

The progress bar is currently only determinate, which means when we update it, we have to tell it explicitly what its value is, and we must know beforehand when the process it is used to measure completes. This widget is not currently the best choice for a process which will take an indeterminate length of time to complete.
It’s a very simple widget with a small API that exposes a limited number of properties and methods, but it can still be highly effective and is great for providing visual feedback to visitors on the percentage of a process is left before it is complete.

Getting Started

We’ll need a copy of the current version of jQuery UI, which can be obtained from the download builder at http://jqueryui.com/download. Once we’ve downloaded it, we’ll need to unpack it so that the existing directory structure is preserved. We should create a new directory on our computer called jQuery UI and then inside this create another new folder called jqueryui1.7. The archive should then be unpacked to the jqueryui1.7 folder.

The archive will contain everything we need to get started; minified and uncompressed versions of all of the library files, some theme files (the default theme is the aptly-named smoothness), and even the latest version of the underlying jQuery library.

The Progress bar relies on a number of files in order to function; these are listed below in the order in which they should be added to our page:

  • ui.core.css
  • ui.theme.css
  • ui.progressbar.css
  • jquery[currentversion].js
  • ui.core.js
  • ui.progressbar.js

The first three files are part of the extensive CSS framework and are used to give the progress bar its distinct appearance. We don’t need to stick with this theme in a real-world implementation; we have many options for customization including a huge number of pre-configured themes available directly from Themeroller, a custom theme we can design ourselves using Themeroller, or even a custom theme we create manually by overriding rules defined in the default stylesheets. We won’t be doing any of those things in this tutorial however, but we can make use of some of the classes provided by the framework.

The Underlying Page

Very little underlying mark-up is needed by this widget; all we need, in addition to the library resources listed above, is a simple container element. In your text editor, create the following page shell with the required resources and container element:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="jqueryui1.7/development-bundle/themes/smoothness/ui.core.css">
    <link rel="stylesheet" type="text/css" href="jqueryui1.7/development-bundle/themes/smoothness/ui.theme.css">
    <link rel="stylesheet" type="text/css" href="jqueryui1.7/development-bundle/themes/smoothness/ui.progressbar.css">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>jQuery UI Progress Bar</title>
  </head>
  <body>
    <div id="container"></div>
    <script type="text/javascript" src="jqueryui1.7/development-bundle/jquery-1.3.2.js"></script>
    <script type="text/javascript" src="jqueryui1.7/development-bundle/ui/ui.core.js"></script>
    <script type="text/javascript" src="jqueryui1.7/development-bundle/ui/ui.progressbar.js"></script>
    <script type="text/javascript">

    </script>
  </body>
</html>

Save this as progressBar.html in the root jQuery UI directory. We put the stylesheets right at the start of the file and the scripts right at the end; this is for performance reasons as pages load the content quicker when they aren’t trying to load JavaScript at the same time. This is a well documented performance practice that is best adhered to. We’ve left an empty script tag at the bottom of the page; let’s add some code there next:

$(function() {

  //call progress bar constructor
  $("#container").progressbar();
});

In order to initialize the default progress bar, all we do is call its constructor method, progressbar, on the container element that the widget is to be rendered into. When you run this page in your browser, you should see that the progress bar has been created and automatically fills the width of its container, which in this case is the body of the page:

Setting the Value of the progress bar

The progress bar’s value will be set to zero by default, which is why it appears empty in the previous screenshot. To fill the progress bar, we need to set the value property; change the constructor function so that it appears as follows:

//call progress bar constructor
$("#container").progressbar({ value: 50 });

The value property determines the percentage of the progress bar that is filled, giving great visual feedback to the visitor on how much of the task is left to complete. The progress bar should now be half filled, as in the following screenshot:

Getting the Value of the Progress Bar

Getting the current value of the widget is as easy as it was to set it; we can use one of its methods to return the current value property. After the initial constructor, add the following code:
//set mouseover for progress bar

$("#container").mouseover(function() {

  //display the current value
  $("<p>").attr("id", "percentage").text($("#container").progressbar("option", "value") + "% complete").appendTo("body");
});

//set mouseout for progress bar
$("#container").mouseout(function() {

  //hide value
  $("#percentage").remove();
});

We’ve added two simple anonymous functions which are triggered on the mouseover and mouseout events fired by the progress bar (note that these are standard DOM events not custom progress bar events). All we do in the first function is create a new paragraph with the current value of the progress bar as its innerText and append it to the page.

The value is retrieved using the option method. The argument passed to the method is the name of the property we’d like to retrieve. The second function simply removes the message again. The message is shown in the following screenshot:

Properties, Events and Methods

The value property, or option, is currently the only configurable property of the progress bar; in this example we set it when the widget is initialized by passing it in as the property of a configuration object. To set this property after the widget has been initialized we would use the option method. To use this method in setter mode, we need to pass in a second parameter specifying the new value, like this:

progressbar("option", "value", 75)

You may be wondering why I said ‘a second parameter’ when clearly there are three arguments in the above line of code. Even though we’re using the option method, we’re not actually calling it directly. Instead we’re calling the constructor method again, but telling it that we’d like to call the option method. The widget will call the method internally, passing in the two parameters (“value” and 75) that we pass to the constructor after the method name.

The progress bar exposes a single event, the change event, which provides a mechanism for us to hook into so that we can respond to changes in its value. This is a custom event so we can detect and react to it in two different ways. We can define an anonymous function as the value of the change property in a configuration object, like we did with the value property, or we can use jQuery’s bind method to specify the anonymous function to execute. A subtle difference between the two is that the code specified using the bind method will be executed first.
The progress bar API exposes five methods, which are listed below:

  • destroy
  • disable
  • enable
  • option
  • value

All of these methods are used in exactly the same way as the option method that we’ve looked at; by calling the constructor method specifying the name of the method and any parameters that we’d like to pass in. Most of these should be pretty self-explanatory.

Using the Progress Bar

This example so far has been very basic, for those of you that may not have used jQuery UI at all before. Let’s step things up a little and put together something approaching the sort of thing we might like to do in a proper implementation. This example will be basic as well, but it should give a much better idea of how the widget can be made to work for us. Our finished page will appear something like this:

Make a start with the following underlying page in a new file in your text editor:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="jqueryui1.7/development-bundle/themes/smoothness/ui.core.css">
    <link rel="stylesheet" type="text/css" href="jqueryui1.7/development-bundle/themes/smoothness/ui.theme.css">
    <link rel="stylesheet" type="text/css" href="jqueryui1.7/development-bundle/themes/smoothness/ui.progressbar.css">
    <link rel="stylesheet" type="text/css" href="regForm.css">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>jQuery UI Progress Bar</title>
  </head>
  <body>
    <div class="form-container ui-helper-clearfix ui-corner-all">
      <h1>Registration Form</h1>
      <p>Progress:</p>
      <div id="progress"></div><label id="amount">0%</label>
        <form action="serverScript.php">
          <div id="panel1" class="form-panel">
            <h2>Personal Details</h2>
              <fieldset class="ui-corner-all">
	<label>Name:</label><input type="text">
	<label>D.O.B:</label><input type="text">
	<label>Choose password:</label><input type="password">
	<label>Confirm password:</label><input type="password">
              </fieldset>
            </div>
            <div id="panel2" class="form-panel ui-helper-hidden">
              <h2>Contact Details</h2>
              <fieldset class="ui-corner-all">
                <label>Email:</label><input type="text">
	<label>Telephone:</label><input type="text">
	<label>Address:</label><textarea rows="3" cols="25"></textarea>
              </fieldset>
            </div>
            <div id="thanks" class="form-panel ui-helper-hidden">
              <h2>Registration Complete</h2>
              <fieldset class="ui-corner-all">
  	<p>Thanks for registering!</p>
              </fieldset>
            </div>
            <button id="next">Next ></button><button id="back" disabled="disabled">< Back</button>
          </form>
        </div>
        <script type="text/javascript" src="jqueryui1.7/development-bundle/jquery-1.3.2.js"></script>
        <script type="text/javascript" src="jqueryui1.7/development-bundle/ui/ui.core.js"></script>
        <script type="text/javascript" src="jqueryui1.7/development-bundle/ui/ui.progressbar.js"></script>
        <script type="text/javascript">

Save this as regForm.html in the jQuery UI folder. At the top of the page we link to the CSS framework; this is primarily to add the required styling for the progress bar, but we can also make use of some of the classes it provides on our own elements. We also add a custom stylesheet that we’ll create soon.

The body of the page contains a few layout elements and some text nodes, but the main elements are the container for the progress bar and the form. The form is separated into several different sections using div and fieldset elements. The reason for this is so that we can hide part of the form to make it appear as if it spans several pages.

We’ve added a paragraph and a label next to the progress bar, we’ll position these so that they appear inside the progress bar. The paragraph contains a simple text string. The label will be used to show the current progress value.

The outer container is given several class names; the first is so that we can apply some custom styling to the element, but the second two are to target different features of the CSS framework. The ui-helper-clearfix class is used to automatically clear floated elements and is a great way of reducing the clutter of additional and unnecessary div elements.

The ui-corner-all class is used to give the container element (as well as the progress bar itself which has them automatically, and our fieldset elements) rounded corners using several proprietary style rules. These are only supported by gecko and webkit based browsers, but in the nature of progressive enhancement it is perfectly acceptable to use them. Progressive enhancement dictates that we can provide enhanced styling on our web pages for browsers that are capable of displaying it. Other browsers will just have a square-cornered container.

We use another class from the CSS framework within the form; several panels need to be hidden when the page first loads, we can therefore make use of the ui-helper-hidden class to ensure that they are set to display:none, when we want to show them, all we have to do is remove this class name.

At the bottom of the body (for performance reasons; this really does work by the way!) we link to the required JavaScript resources from the library. The very last script element is empty and waiting for the code that will bring the form and the progress bar to life. Let’s add that next:

$(function() {

  //call progress bar constructor
  $("#progress").progressbar({ change: function() {

    //update amount label when value changes
    $("#amount").text($("#progress").progressbar("option", "value") + "%");
  } });

  //set click handler for next button
  $("#next").click(function(e) {

  //stop form submission
  e.preventDefault();

  //look at each panel
  $(".form-panel").each(function() {

    //if it's not the first panel enable the back button
    ($(this).attr("id") != "panel1") ? null : $("#back").attr("disabled", "");

	//if the panel is visible fade it out
	($(this).hasClass("ui-helper-hidden")) ? null : $(this).fadeOut("fast", function() {

	  //add hidden class and show the next panel
	  $(this).addClass("ui-helper-hidden").next().fadeIn("fast", function() {

	    //if it's the last panel disable the next button
    	    ($(this).attr("id") != "thanks") ? null : $("#next").attr("disabled", "disabled");

	    //remove hidden class from new panel
	    $(this).removeClass("ui-helper-hidden");

	    //update progress bar
	    $("#progress").progressbar("option", "value", $("#progress").progressbar("option", "value") + 50);
	  });
      });
    });
  });

});

Within the outer document.ready short-cut we have the constructor function for the progress bar; we pass the constructor a literal configuration object containing a single property. This is the change property and allows us to supply an anonymous function to execute each time the custom change event is detected. We can use this event to update the label that we’re going to position inside the progress bar.

Each time the event is fired we’ll grab the current value of the progress bar using the option method and set the value as the text of the label. The event is fired after the change takes place, so the value we obtain will always be the new value.

Next we have a click handler for the next> button; when this button is clicked it will result in the current ‘page’ of the form changing, via a series of animations, and the value of the progress bar updating. We also need to do a few other things. The default behavior of a button inside a form is to submit the form, which we don’t want to do at this stage so the first thing our click handler does is prevent the form being submitted using the preventDefault() JavaScript function. This is called on the event object, which is automatically passed to the anonymous function.

We then look through each of the separate panels in the form to determine the current panel; the first thing we do is check that the current panel is not the first panel and if it isn’t, we enable the back button which is disabled by default. Only one panel will be displayed at one time, so we find the panel that doesn’t have the ui-helper-hidden class and fade it out. We specify an anonymous callback function to execute once the fade finishes.

Within this second function we select the next element and show it; if the next element is the final panel, which has an id of thanks, we disable the next> button. Although we don’t worry about actual submission of the form in this example, this is where we could send the data gathered from the form to the server. We remove the ui-helper-hidden class as the panel is now visible.

Finally we use the option method once again, this time in setter mode, to set the new value of the progress bar. The new value, that we pass to the method as the second parameter is simply the current value plus 50, as there are just 2 parts of the form. This last part will then trigger the function which updates the label.

Next we need to add a very similar click handler for the

//set click handler for back button
$("#back").click(function(e) {

  //stop form submission
  e.preventDefault();

  //look at each panel
  $(".form-panel").each(function() {

    //if it's not the last panel enable the next button
    ($(this).attr("id") != "thanks") ? null : $("#next").attr("disabled", "");

    //if the panel is visible fade it out
    ($(this).hasClass("ui-helper-hidden")) ? null : $(this).fadeOut("fast", function() {

      //add hidden class and show the next panel
      $(this).addClass("ui-helper-hidden").prev().fadeIn("fast", function() {

        //if it's the first panel disable the back button
    	  ($(this).attr("id") != "panel1") ? null : $("#back").attr("disabled", "disabled");

	  //remove hidden class from new panel
	  $(this).removeClass("ui-helper-hidden");

	  //update progress bar
	  $("#progress").progressbar("option", "value", $("#progress").progressbar("option", "value") - 50);
      });
    });
  });
});

This is now all of the code that we’ll need, all we have to do now is add some basic CSS to lay the example out; in a new file in your text editor add the following code:

h1, h2 { font-family:Georgia; font-size:140%; margin-top:0; }
h2 { font-size:100%; margin:20px 0 10px; text-align:left; }
.form-container {
  width:400px; margin:0 auto; position:relative; font-family:Verdana;
  font-size:80%; padding:20px; background-color:#e0e3e2;
  border:3px solid #abadac;
}
.form-panel { width:400px; height:241px; }
.form-panel fieldset {
  width:397px; height:170px; margin:0 auto; padding:22px 0 0;
  border:1px solid #abadac; background-color:#ffffff;
}
.form-panel label {
  width:146px; display:block; float:left; text-align:right;
  padding-top:2px; margin-right:10px;
}
.form-panel input, .form-panel textarea {
  float:left; width:200px; margin-bottom:13px;
}
.form-container button { float:right; }
p {
  margin:0; font-size:75%; position:absolute; left:30px; top:60px;
  font-weight:bold;
}
#amount {
  position:absolute; right:30px; top:60px; font-size:80%;
  font-weight:bold;
}
#thanks { text-align:center; }
#thanks p {
  margin-top:48px; font-size:160%; position:relative; left:0; top:0;
}

Save this as regForm.css in the same folder as the HTML file. We should now have a working page with a wired up progress bar. When we run the page we should find that we can navigate through each panel of the form, and the progress bar will update itself accordingly:

Summary

In this article we looked at the extremely useful progress bar, which we can use as a visual aid to tell visitors how much longer a specified process is going to take to complete percentage-wise. It provides an attractive and useful presentation of the information, in a way that should be easily understood by our visitors.

We looked at the property and event that are exposed by its API and we looked at one of the methods that we can call to make the progress bar do something. The example that we ended with should run perfectly in all the major browsers, although it does look a little messy in good ol’ IE (which would be very easy to fix were we inclined to do so).

  • Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.


Add Comment

Discussion 87 Comments

Comment Page 1 of 21 2
  1. Lawrence77 says:

    I love progress bar always…. :)

    I already used that in all my projects! ;)

    • Lawrence77 says:

      But I dont know this JQuery Progressbar! :(
      Thanks for teaching me such a wonderful thing!

      I use progressBars in my programming Examples Like (C#.NET, VB.NET, ,)

      • Concerned Reader says:

        @lawrence77 – you love to hear yourself talk, don’t you…

        At least make some legitimate comments occasionally, please!! Especially if you insist on stalking everything the Envato network puts out. Your cheesy ass comments liter every post on every site.

        How about reading the articles, and actually putting some of the techniques to use instead of drooling over them and kissing up to every author. Lord knows your site could certainly use the work!!

      • Lawrence77 says:

        @Concerned Reader
        Thanks for your big advice!
        I talked myself huh, i missed such lines in the comment so i added it later!

        We had a rights to comment here, If Envato comes and says Stop comments, then I stop my comments here!

        I love commenting thats all, thats one of my bad habit!

        Sorry to all, if I made a mistake here!

        I apologize!

      • Turtle Guy says:

        I like turtles

      • ABraham says:

        Although I agree with @concerned reader to an extent i don’t why you decided to hide your name.? Abit cowardly if your going to rant on someone..

    • elkaz says:

      Lawrence is the most annoying user on nettuts. Always needs to be the first poster or tag off the first, and never has anything useful to say. And yes I’m aware this post isn’t useful either, but I felt I needed to rant about him and reveal him for the troll he is.

    • lawrence77 says:

      thanks for your advice guys!
      I hope I hurted all ur hearts and irritating you all!
      If i hurting u all hard means please apologize me! thanks!

      So i leave here!
      bye! :(

    • I’ve created something very similar on my website, thanks

      Found it useful.

  2. iPad says:

    Excelent work!

  3. organicit says:

    Nice Job Dan,

    Clean and practical

    I am going to stash this one away for a rainy day

  4. zik says:

    Thanks for sharing !

  5. Ross says:

    I want to see a tutorial that shows upload progress bars….

  6. JayBird says:

    700%??

    need the facility to stop users pressing “next” more than once

    http://mark-beech.co.uk/700.gif

  7. Diego SA says:

    Dude, this is awesome!

    But I’d really like to learn how to make a download progress bar working inside a webpage. I mean, instead of showing the download window browser, make appear a download progress bar inside of a webpage showing how many percents are complete.
    It’d be great!

  8. Patternhead says:

    Nice tut, like the concept and the execution

  9. Philo says:

    Nice Tutorial Dan! :)

  10. net.tutsplus is a excellent site which provide us with great tutorials thank you Dan Wellman for this Create a Progress Bar With Javascript tutorial

  11. Diego says:

    great tutorial man, jquery the 1st

  12. Abderrahmane T. J. says:

    Pretty and good Idea ^^

  13. Shi Chuan says:

    Recently I tried out jQuery because of WordPress. This is incredibly useful!

  14. Michael says:

    Thanks for the tutorials, I was looking for something like this with one of my admin systems with multipage forms.

  15. I keep getting:
    AccessDeniedAccess Denied0E02373875998DE1KvfnVQ3KuYKNtG+L+Un9htZi3QJc0A3Oelz+YV5m8oIWCFbnICCzDu8Mvru02G4s
    When i try to submit the example

    • rafaelrrp says:

      I keep getting:
      AccessDeniedAccess Denied0E02373875998DE1KvfnVQ3KuYKNtG+L+Un9htZi3QJc0A3Oelz+YV5m8oIWCFbnICCzDu8Mvru02G4s
      When i try to submit the example

      [2]

      • Dan Wellman says:
        Author

        You get this on the live demo right? I think if you click the next button before the page has finished loading this happens. I assume this is something to do with how the example is hosted…

  16. Jay says:

    When I tried the demo, when I submitted my info on the first page, the progress bar started going up exponentially. Not sure what happened…

  17. Mehedi says:

    I am thinking to use it on my next project. gr8!

  18. Great stuff, it all works splendid for me ;)

  19. Dan Wellman says:
    Author

    Thanks for reading everyone, and thanks for the intensive UAT :D

  20. wdalhaj says:

    Thanks!Waiting for more..

  21. Kasper says:

    Heya,

    I’d just like to know with this because I am a bit unsure does this form submit itself when entering the last frame? Or is there anything to do so it can do so?

    Rgards

    • Kasper says:

      Oh and just a suggestion it could be awsomely cool with jquery autogrow on the textfield field for comments ;D

  22. Jeff Dion says:

    Nice effect and visual result, but i’m a bit confused, how it degrades if javascript is turned off or if the user want to use the back button. Accessibility is one of my first concern when i design a website, so, even if this solution is great, i think i’ll stick to the old school method.

  23. faouzi says:

    comment faire le function verif() dans le e-mail

  24. Ben Sky says:

    Nice turorial, very in depth, bookmarked for reference. Thanks alot.

  25. Module23 says:

    Nice work, thanks for sharing!

  26. Ian says:

    i like it, it’s wonderfull source code

  27. David Moreen says:

    This is exactly what I have been looking for, for my projects. Thanks so much!

  28. bassralph says:

    this is great. i will apply this to my site.. and
    by the way how will i get the information based from the form.
    before display the thanks for registering.

    it will display the information collected in the forms..

    thanks in advance.

  29. เพชร says:

    I’ll use this with my next project.

  30. Joe says:

    Im now desperate to create a new project to use this in!

  31. Itransition says:

    Javascript progress bar… I’d better construct awesome flash-based progress bar. This allows to add background images as you wish. But the best trick is to combine your example with the flash :)

  32. Mamun says:

    Nice! What a good share!

  33. A.R Zico says:

    Great job. I’ll try it.

  34. amit says:

    i’m gonna use this in my project………..well done

  35. Babu says:

    Hi,
    I want to use this Progressbar with upload files.

    http://valums.com/wp-content/uploads/ajax-upload/demo-jquery.htm

    How can i Use this Progressbar with above upload control.

    Can anyone help me.

    Thanks,
    Babu

  36. nadim says:

    thanks .i will try my project

  37. Jeff says:

    Many thanks, you led me to the solution I was looking for!

    Jeff

  38. Jeff says:

    Many thanks, you led me to a better solution than I was headed for!

    Jeff

  39. bhavin says:

    hey man thanks for your this help god can blesh you
    all my wishes with you

    bye take care

  40. Many thanks, great tutorial.
    i’m gonna use this in my application.

  41. Rich says:

    Where does the output go? My action=”serverScript.php” does not get any information.

    Is there an easy way to post the output to a PHP script?
    Example: Have users go through a quiz without reloading the page, and then click submit at the end which loads a PHP script with the data posted to it?

  42. Pinky says:

    this is what i was looking for..thanks

  43. abdul says:

    Thanks, nice work

  44. Michael L says:

    It’s a detailed tutorial but it is more on client side. How about a progress bar that calls a backend script? The one that can be used for uploading large images or videos (without using flash of course).

  45. Carlos says:

    I was reading the comments and was wandering if anyone knew the best solution for submitting the form. I have it working fine and customized but I am unable to have it submit to my email once it is filled out. Any assistance would be greatly appreciated.

  46. victor says:

    wow thanks for such a great example. Needed this for a final presentation today

  47. Mark says:

    This is a nice tutorial. I am going to use your code in a Rails 3 application. Do you have any suggestions to update the progress bar with an event call not tied to users’ actions. For example, I have a long process that which has a function that calculates to amount completed. I want to update the progress bar with the amount completed by call the javascript and refreshing the div?

    Thanks,

    Mark

  48. Tanner says:

    With HTML5, this could be done much easier with the meter or progress element. But still, great tut!

  49. guy bashan says:

    Great post! Thanks for the good work!

Comment Page 1 of 21 2

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.