diff --git a/css/webform.css b/css/webform.css
index 036d199..802119c 100644
--- a/css/webform.css
+++ b/css/webform.css
@@ -28,3 +28,44 @@
 .webform-container-inline div.ajax-progress-bar div {
   display: inherit;
 }
+.webform-progressbar {
+  width: 90%;
+  margin: 0 auto;
+  text-align: center;
+}
+.webform-progressbar-inner {
+  height: 1em;
+  background-color: #74C421;
+  height: 3px;
+}
+.webform-progressbar-outer {
+  position: relative;
+  border: 1px solid #356900;
+  width: 100%;
+  height: 3px;
+  margin: 0.35em -1px 2em;
+  background-color: white;
+}
+.webform-progressbar-page {
+  position: absolute;
+  width: 7px;
+  height: 7px;
+  margin: -6px -4px;
+  border: 1px solid #356900;
+  background-color: white;
+  border-radius: 5px;
+}
+.webform-progressbar-page.completed {
+  background-color: #74C421;
+}
+.webform-progressbar-page.current {
+  background-color: #74C421;
+}
+.webform-progressbar-page .webform-progressbar-page-number {
+  display: none;
+}
+.webform-progressbar-page .webform-progressbar-page-label {
+  position: relative;
+  top: 10px;
+  margin: 0 -10em;
+}
diff --git a/includes/webform.admin.inc b/includes/webform.admin.inc
index 223d5c6..aa3179f 100644
--- a/includes/webform.admin.inc
+++ b/includes/webform.admin.inc
@@ -93,6 +93,38 @@
     '#access' => webform_email_html_capable(),
   );
 
+  $form['progressbar'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Progress bar'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $form['progressbar']['webform_progressbar_style']  = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Progress bar style'),
+    '#options' => array(
+      'progressbar_bar' => t('Show progress bar'),
+      'progressbar_page_number' => t('Show page number as number of completed (i.e. Page 1 of 10)'),
+      'progressbar_percent' => t('Show percentage completed (i.e. 10%)'),
+      'progressbar_pagebreak_labels' => t('Show page labels from page break components'),
+      'progressbar_include_confirmation' => t('Include confirmation page in progress bar'),
+    ),
+    '#default_value' => $progress_bar_style,
+    '#description' => t('Choose how the progress bar should be displayed for multi-page forms.'),
+  );
+  $form['progressbar']['webform_progressbar_label_first'] = array(
+    '#type' => 'textfield',
+    '#title' => t('First page label'),
+    '#default_value' => webform_variable_get('webform_progressbar_label_first'),
+    '#maxlength' => 255,
+  );
+  $form['progressbar']['webform_progressbar_label_confirmation'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Confirmation page label'),
+    '#default_value' => webform_variable_get('webform_progressbar_label_confirmation'),
+    '#maxlength' => 255,
+  );
+
   $form['advanced'] = array(
     '#type' => 'fieldset',
     '#title' => t('Advanced options'),
@@ -197,6 +229,9 @@
   // Change the name of the node type variable and clean it up.
   $form_state['values']['webform_node_types'] = array_keys(array_filter($form_state['values']['node_types']));
   unset($form_state['values']['node_types']);
+
+  // Trim out empty options in the progress bar options.
+  $form_state['values']['webform_progressbar_style'] = array_keys(array_filter($form_state['values']['webform_progressbar_style']));
 }
 
 /**
diff --git a/includes/webform.pages.inc b/includes/webform.pages.inc
index fb13868..450f70a 100644
--- a/includes/webform.pages.inc
+++ b/includes/webform.pages.inc
@@ -169,6 +169,7 @@
     '#weight' => -3,
     '#description' => t('These permissions affect which roles can submit this webform. It does not prevent access to the webform page. If needing to prevent access to the webform page entirely, use a content access module such as <a href="http://drupal.org/project/taxonomy_access">Taxonomy Access</a> or <a href="http://drupal.org/project/node_privacy_byrole">Node Privacy by Role</a>.'),
     '#access' => variable_get('webform_submission_access_control', 1),
+    '#weight' => 10,
   );
   $user_roles = user_roles();
   foreach ($user_roles as $rid => $rname) {
@@ -186,13 +187,67 @@
   );
   /* End per-role submission control */
 
+  /* Start progress bar settings form */
+  $form['progressbar'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Progress bar'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#weight' => 15,
+  );
+  $progress_bar_style = array_filter(array(
+    $node->webform['progressbar_page_number'] ? 'progressbar_page_number' : NULL,
+    $node->webform['progressbar_percent'] ? 'progressbar_percent' : NULL,
+    $node->webform['progressbar_bar'] ? 'progressbar_bar' : NULL,
+    $node->webform['progressbar_pagebreak_labels'] ? 'progressbar_pagebreak_labels' : NULL,
+    $node->webform['progressbar_include_confirmation'] ? 'progressbar_include_confirmation' : NULL,
+  ));
+  $form['progressbar']['webform_progressbar_style']  = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Progress bar style'),
+    '#options' => array(
+      'progressbar_bar' => t('Show progress bar'),
+      'progressbar_page_number' => t('Show page number as number of completed (i.e. Page 1 of 10)'),
+      'progressbar_percent' => t('Show percentage completed (i.e. 10%)'),
+      'progressbar_pagebreak_labels' => t('Show page labels from page break components'),
+      'progressbar_include_confirmation' => t('Include confirmation page in progress bar'),
+    ),
+    '#default_value' => $progress_bar_style,
+    '#description' => t('Choose how the progress bar should be displayed for multi-page forms.'),
+  );
+  $form['progressbar']['progressbar_label_first'] = array(
+    '#type' => 'textfield',
+    '#title' => t('First page label'),
+    '#default_value' => $node->webform['progressbar_label_first'],
+    '#maxlength' => 255,
+    '#description' => t('The first page label in the progress bar. Subseqent pages are titled by their page break label.'),
+    '#states' => array(
+      'visible' => array(
+        ':input[name="webform_progressbar_style[progressbar_pagebreak_labels]"]' => array('checked' => TRUE),
+      ),
+    ),
+  );
+  $form['progressbar']['progressbar_label_confirmation'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Confirmation page label'),
+    '#default_value' => $node->webform['progressbar_label_confirmation'],
+    '#maxlength' => 255,
+    '#states' => array(
+      'visible' => array(
+        ':input[name="webform_progressbar_style[progressbar_pagebreak_labels]"]' => array('checked' => TRUE),
+        ':input[name="webform_progressbar_style[progressbar_include_confirmation]"]' => array('checked' => TRUE),
+      ),
+    ),
+  );
+  /* End progress Bar settings form */
+
   /* Start advanced settings form */
   $form['advanced'] = array(
     '#type' => 'fieldset',
     '#title' => t('Advanced settings'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
-    '#weight' => -1,
+    '#weight' => 20,
   );
   $form['advanced']['block'] = array(
     '#type' => 'checkbox',
@@ -221,7 +276,7 @@
   );
   $form['advanced']['submit_notice'] = array(
     '#type' => 'checkbox',
-    '#title' => t('Show the notification about previous submissions.'),
+    '#title' => t('Show the notification about previous submissions'),
     '#default_value' => $node->webform['submit_notice'],
     '#description' => t('Show the previous submissions notification that appears when users have previously submitted this form.'),
   );
@@ -334,6 +389,16 @@
     $node->webform['total_submit_interval'] = $form_state['values']['total_submit_interval'];
   }
 
+  // Set the progress bar preferences.
+  $progress_bar_settings = array_filter($form_state['values']['webform_progressbar_style']);
+  $node->webform['progressbar_page_number'] = in_array('progressbar_page_number', $progress_bar_settings);
+  $node->webform['progressbar_percent'] = in_array('progressbar_percent', $progress_bar_settings);
+  $node->webform['progressbar_bar'] = in_array('progressbar_bar', $progress_bar_settings);
+  $node->webform['progressbar_pagebreak_labels'] = in_array('progressbar_pagebreak_labels', $progress_bar_settings);
+  $node->webform['progressbar_include_confirmation'] = in_array('progressbar_include_confirmation', $progress_bar_settings);
+  $node->webform['progressbar_label_first'] = $form_state['values']['progressbar_label_first'];
+  $node->webform['progressbar_label_confirmation'] = $form_state['values']['progressbar_label_confirmation'];
+
   // Set submit notice.
   $node->webform['submit_notice'] = $form_state['values']['submit_notice'];
 
diff --git a/templates/webform-confirmation.tpl.php b/templates/webform-confirmation.tpl.php
index 75965d8..25365fb 100644
--- a/templates/webform-confirmation.tpl.php
+++ b/templates/webform-confirmation.tpl.php
@@ -11,10 +11,14 @@
  *
  * Available variables:
  * - $node: The node object for this webform.
- * - $confirmation_message: The confirmation message input by the webform author.
+ * - $progressbar: The progress bar 100% filled (if configured). This may not
+ *   print out anything if a progress bar is not enabled for this node.
+ * - $confirmation_message: The confirmation message input by the webform
+ *   author.
  * - $sid: The unique submission ID of this submission.
  */
 ?>
+<?php print $progressbar; ?>
 
 <div class="webform-confirmation">
   <?php if ($confirmation_message): ?>
diff --git a/templates/webform-form.tpl.php b/templates/webform-form.tpl.php
index d839083..7edc895 100644
--- a/templates/webform-form.tpl.php
+++ b/templates/webform-form.tpl.php
@@ -18,6 +18,9 @@
  */
 ?>
 <?php
+  //Print out the progress bar at the top of the page
+  print drupal_render($form['progressbar']);
+
   // Print out the main part of the form.
   // Feel free to break this up and move the pieces within the array.
   print drupal_render($form['submitted']);
diff --git a/templates/webform-progressbar.tpl.php b/templates/webform-progressbar.tpl.php
new file mode 100644
index 0000000..43b124d
--- /dev/null
+++ b/templates/webform-progressbar.tpl.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @file
+ * Display the progress bar for multipage forms
+ *
+ * Available variables:
+ * - $node: The webform node.
+ * - $progressbar_page_number: TRUE if the actual page number should be
+ *   displayed.
+ * - $progressbar_percent: TRUE if the percentage complete should be displayed.
+ * - $progressbar_bar: TRUE if the bar should be displayed.
+ * - $progressbar_pagebreak_labels: TRUE if the page break labels shoud be
+ *   displayed.
+
+ * - $page_num: The current page number.
+ * - $page_count: The total number of pages in this form.
+ * - $page_labels: The labels for the pages. This typically includes a label for
+ *   the starting page (index 0), each page in the form based on page break
+ *   labels, and then the confirmation page (index number of pages + 1).
+ * - $percent: The percentage complete.
+ */
+?>
+<div class="webform-progressbar">
+  <?php if ($progressbar_bar): ?>
+    <div class="webform-progressbar-outer">
+      <div class="webform-progressbar-inner" style="width: <?php print number_format($percent, 0); ?>%">&nbsp;</div>
+      <?php for ($n = 1; $n <= $page_count; $n++): ?>
+        <span class="webform-progressbar-page<?php if ($n < $page_num) { print ' completed'; }; ?><?php if ($n == $page_num) { print ' current'; }; ?>" style="left: <?php print number_format(($n - 1) / ($page_count - 1), 4) * 100; ?>%">
+          <span class="webform-progressbar-page-number"><?php print $n; ?></span>
+          <?php if ($progressbar_pagebreak_labels): ?>
+          <span class="webform-progressbar-page-label">
+            <?php print check_plain($page_labels[$n - 1]); ?>
+          </span>
+          <?php endif; ?>
+        </span>
+      <?php endfor; ?>
+    </div>
+  <?php endif; ?>
+
+
+  <?php if ($progressbar_page_number): ?>
+    <div class="webform-progressbar-number">
+      <?php print t('Page @start of @end', array('@start' => $page_num, '@end' => $page_count)); ?>
+      <?php if ($progressbar_percent): ?>
+        <span class="webform-progressbar-number">
+          (<?php print number_format($percent, 0); ?>%)
+        </span>
+      <?php endif; ?>
+    </div>
+  <?php endif; ?>
+
+  <?php if (!$progressbar_page_number && $progressbar_percent): ?>
+    <div class="webform-progressbar-number">
+      <?php print number_format($percent, 0); ?>%
+    </div>
+  <?php endif; ?>
+</div>
diff --git a/webform.install b/webform.install
index 3627125..ccfe517 100644
--- a/webform.install
+++ b/webform.install
@@ -109,6 +109,51 @@
         'not null' => TRUE,
         'default' => -1,
       ),
+      'progressbar_bar' => array(
+        'description' => 'Boolean value indicating if the bar should be shown as part of the progress bar.',
+        'type' => 'int',
+        'size' => 'tiny',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'progressbar_page_number' => array(
+        'description' => 'Boolean value indicating if the page number should be shown as part of the progress bar.',
+        'type' => 'int',
+        'size' => 'tiny',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'progressbar_percent' => array(
+        'description' => 'Boolean value indicating if the percentage complete should be shown as part of the progress bar.',
+        'type' => 'int',
+        'size' => 'tiny',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'progressbar_pagebreak_labels' => array(
+        'description' => 'Boolean value indicating if the pagebreak labels should be included as part of the progress bar.',
+        'type' => 'int',
+        'size' => 'tiny',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'progressbar_include_confirmation' => array(
+        'description' => 'Boolean value indicating if the confirmation page should count as a page in the progress bar.',
+        'type' => 'int',
+        'size' => 'tiny',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'progressbar_label_first' => array(
+        'description' => 'Label for the first page of the progress bar.',
+        'type' => 'varchar',
+        'length' => 255,
+      ),
+      'progressbar_label_confirmation' => array(
+        'description' => 'Label for the last page of the progress bar.',
+        'type' => 'varchar',
+        'length' => 255,
+      ),
     ),
     'primary key' => array('nid'),
   );
@@ -1422,3 +1467,42 @@
   );
   db_change_field('webform_component', 'mandatory', 'required', $spec);
 }
+
+/**
+ * Add progress bar display on and off fields to the webform table.
+ */
+function webform_update_7409() {
+  if (!db_field_exists('webform', 'progressbar_bar')) {
+    $int_schema = array(
+      'type' => 'int',
+      'size' => 'tiny',
+      'not null' => TRUE,
+      'default' => 0,
+    );
+    $varchar_schema = array(
+      'type' => 'varchar',
+      'length' => 255,
+    );
+
+    $int_schema['description'] = 'Boolean value indicating if the bar should be shown as part of the progress bar.';
+    db_add_field('webform', 'progressbar_bar', $int_schema);
+
+    $int_schema['description'] = 'Boolean value indicating if the page number should be shown as part of the progress bar.';
+    db_add_field('webform', 'progressbar_page_number', $int_schema);
+
+    $int_schema['description'] = 'Boolean value indicating if the percentage complete should be shown as part of the progress bar.';
+    db_add_field('webform', 'progressbar_percent', $int_schema);
+
+    $int_schema['description'] = 'Boolean value indicating if the pagebreak labels should be included as part of the progress bar.';
+    db_add_field('webform', 'progressbar_pagebreak_labels', $int_schema);
+
+    $int_schema['description'] = 'Boolean value indicating if the confirmation page should count as a page in the progress bar.';
+    db_add_field('webform', 'progressbar_include_confirmation', $int_schema);
+
+    $varchar_schema['description'] = 'Label for the first page of the progress bar.';
+    db_add_field('webform', 'progressbar_label_first', $varchar_schema);
+
+    $varchar_schema['description'] = 'Label for the last page of the progress bar.';
+    db_add_field('webform', 'progressbar_label_confirmation', $varchar_schema);
+  }
+}
diff --git a/webform.module b/webform.module
index 3344166..e7e8fee 100644
--- a/webform.module
+++ b/webform.module
@@ -649,6 +649,10 @@
     'webform_inline_radio_label' => array(
       'render element' => 'element',
     ),
+    'webform_progressbar' => array(
+      'variables' => array('node' => NULL, 'page_num' => NULL, 'page_count' => NULL, 'page_labels' => array()),
+      'template' => 'templates/webform-progressbar',
+    ),
     'webform_mail_message' => array(
       'variables' => array('node' => NULL, 'submission' => NULL, 'email' => NULL),
       'template' => 'templates/webform-mail',
@@ -1438,6 +1442,7 @@
  * Default settings for a newly created webform node.
  */
 function webform_node_defaults() {
+  $progress_bar_defaults = webform_variable_get('webform_progressbar_style');
   $defaults = array(
     'confirmation' => '',
     'confirmation_format' => NULL,
@@ -1452,6 +1457,13 @@
     'submit_interval' => '-1',
     'total_submit_limit' => '-1',
     'total_submit_interval' => '-1',
+    'progressbar_page_number' => in_array('progressbar_page_number', $progress_bar_defaults) ? '1' : '0',
+    'progressbar_percent' => in_array('progressbar_percent', $progress_bar_defaults) ? '1' : '0',
+    'progressbar_bar' => in_array('progressbar_bar', $progress_bar_defaults) ? '1' : '0',
+    'progressbar_pagebreak_labels' => in_array('progressbar_pagebreak_labels', $progress_bar_defaults) ? '1' : '0',
+    'progressbar_include_confirmation' => in_array('progressbar_include_confirmation', $progress_bar_defaults) ? '1' : '0',
+    'progressbar_label_first' => webform_variable_get('webform_progressbar_label_first'),
+    'progressbar_label_confirmation' => webform_variable_get('webform_progressbar_label_confirmation'),
     'status' => '1',
     'record_exists' => FALSE,
     'roles' => array('1', '2'),
@@ -2148,6 +2160,17 @@
       foreach ($form_state['values']['submitted'] as $cid => $data) {
         $input_values[$cid] = is_array($data) ? $data : array($data);
       }
+    }
+
+    if ($page_count > 1) {
+      $form['progressbar'] = array(
+        '#theme' => 'webform_progressbar',
+        '#node' => $node,
+        '#page_num' => $page_num,
+        '#page_count' => $page_count + ($node->webform['progressbar_include_confirmation'] ? 1 : 0),
+        '#page_labels' => webform_page_labels($node),
+        '#weight' => -100
+      );
     }
 
     // Recursively add components to the form. The unfiltered version of the
@@ -3002,6 +3025,33 @@
 
   // Strip out empty tags added by WYSIWYG editors if needed.
   $vars['confirmation_message'] = strlen(trim(strip_tags($confirmation))) ? $confirmation : '';
+
+  // Progress bar.
+  $vars['progressbar'] = '';
+  if ($vars['node']->webform['progressbar_include_confirmation']) {
+    $page_labels = webform_page_labels($vars['node']);
+    $vars['progressbar'] = theme('webform_progressbar', array(
+      'node' => $vars['node'],
+      'page_num' => count($page_labels),
+      'page_count' => count($page_labels),
+      'page_labels' => $page_labels,
+    ));
+  }
+}
+
+/**
+ * Prepare for theming of the webform progressbar.
+ */
+function template_preprocess_webform_progressbar(&$vars) {
+  // Add CSS used by the progress bar.
+  drupal_add_css(drupal_get_path('module', 'webform') . '/css/webform.css');
+
+  $vars['progressbar_page_number'] = $vars['node']->webform['progressbar_page_number'];
+  $vars['progressbar_percent'] = $vars['node']->webform['progressbar_percent'];
+  $vars['progressbar_bar'] = $vars['node']->webform['progressbar_bar'];
+  $vars['progressbar_pagebreak_labels'] = $vars['node']->webform['progressbar_pagebreak_labels'];
+  $vars['progressbar_include_confirmation'] = $vars['node']->webform['progressbar_include_confirmation'];
+  $vars['percent'] = ($vars['page_num'] - 1) / ($vars['page_count'] - 1) * 100;
 }
 
 /**
@@ -3342,7 +3392,6 @@
   return filter_xss($string, $allowed_tags);
 }
 
-
 /**
  * Utility function to ensure that a webform record exists in the database.
  *
@@ -3413,7 +3462,31 @@
 }
 
 /**
- * Retreive a Drupal variable with the appropriate default value.
+ * Find the label of a given page based on page breaks.
+ *
+ * @param $webform
+ *   The webform node.
+ * @return array
+ *   An array of all page labels, indexed by page number.
+ */
+function webform_page_labels($node) {
+  $page_count = 1;
+  $page_labels = array();
+  $page_labels[0] = t($node->webform['progressbar_label_first']);
+  foreach ($node->webform['components'] as $component) {
+    if ($component['type'] == 'pagebreak') {
+      $page_labels[$page_count] = $component['name'];
+      $page_count++;
+    }
+  }
+  if ($node->webform['progressbar_include_confirmation']) {
+    $page_labels[] = t($node->webform['progressbar_label_confirmation']);
+  }
+  return $page_labels;
+}
+
+/**
+ * Retrieve a Drupal variable with the appropriate default value.
  */
 function webform_variable_get($variable) {
   switch ($variable) {
@@ -3441,6 +3514,15 @@
     case 'webform_csv_delimiter':
       $result = variable_get('webform_csv_delimiter', '\t');
       break;
+    case 'webform_progressbar_style':
+      $result = variable_get('webform_progressbar_style', array('progressbar_bar', 'progressbar_pagebreak_labels', 'progressbar_include_confirmation'));
+      break;
+    case 'webform_progressbar_label_first':
+      $result = variable_get('webform_progressbar_label_first', t('Start'));
+      break;
+    case 'webform_progressbar_label_confirmation':
+      $result = variable_get('webform_progressbar_label_confirmation', t('Complete'));
+      break;
   }
   return $result;
 }