diff --git a/includes/jcarousel_style_plugin.inc b/includes/jcarousel_style_plugin.inc
index 53dcbc9..44b73f7 100644
--- a/includes/jcarousel_style_plugin.inc
+++ b/includes/jcarousel_style_plugin.inc
@@ -23,6 +23,7 @@ class jcarousel_style_plugin extends views_plugin_style {
     $options['start'] = array('default' => '1');
     $options['easing'] = array('default' => NULL);
     $options['vertical'] = array('default' => FALSE);
+    $options['navigation'] = array('default' => '');
     return $options;
   }
 
@@ -88,6 +89,17 @@ class jcarousel_style_plugin extends views_plugin_style {
       '#field_suffix' => ' ' . t('seconds'),
       '#description' => t('Specifies how many seconds to periodically auto-scroll the content. If set to 0 (default) then autoscrolling is turned off.'),
     );
+    $form['navigation'] = array(
+      '#type' => 'select',
+      '#title' => t('Enable navigation'),
+      '#options' => array(
+        '' => t('None'),
+        'before' => t('Before'),
+        'after' => t('After'),
+      ),
+      '#default_value' => $this->options['navigation'],
+      '#description' => t('Enable a clickable navigation list to jump straight to a given page.'),
+    );
 
     $form['advanced'] = array(
       '#type' => 'fieldset',
diff --git a/jcarousel.module b/jcarousel.module
index a01fd98..0164dbf 100644
--- a/jcarousel.module
+++ b/jcarousel.module
@@ -308,7 +308,7 @@ function jcarousel_skins() {
 
 /**
  * Creates a jCarousel element on the page.
- * 
+ *
  * @param $items
  *   The items to appear in the carousel.
  * @param $options
diff --git a/js/jcarousel.js b/js/jcarousel.js
index 7778ea8..aa1e042 100644
--- a/js/jcarousel.js
+++ b/js/jcarousel.js
@@ -41,6 +41,52 @@ Drupal.behaviors.jcarousel.attach = function(context, settings) {
       }
     }
 
+    if (options.navigation) {
+      options.setupCallback = function(carousel) {
+        $(carousel.list)[options.navigation](function() {
+          // This only works for a positive starting point.  Also, .first is 1-based
+          // while .last is a count, so we need to reset the .first number to be
+          // 0-based to make the math work.
+          var pageSize = carousel.last - (carousel.first - 1);
+          var navigation = $('<ul class="jcarousel-navigation">');
+          var i;
+          var numPages;
+
+          for (i = 1, numPages = Math.ceil($('li', carousel.list).length / pageSize); i <= numPages; i++) {
+            navigation.append('<li><a href="javascript:void()">' + i + '</a></li>');
+          }
+          navigation.find('a').bind('click', function() {
+            // The number in the field is going to be one higher than the page
+            // number we want to scroll to, since that will be 0-based. But we
+            // need to scroll to the first item in that page, which means we
+            // need to add one more to the value to get the item to scroll to
+            // in order to get to that particular page.  Weird but true.
+            var target = $(this);
+            var scrollTo = ($.jcarousel.intval(target.text()) - 1) * pageSize + 1;
+            target.addClass('active').parents('ul').find('a').not(target).removeClass('active');
+            carousel.scroll(scrollTo);
+            return false;
+          });
+
+          // Make the first page active by default.
+          navigation.find('a:first').addClass('active');
+
+          return navigation;
+        });
+      };
+
+      options.itemVisibleInCallback = {
+          onAfterAnimation: function (carousel, item, idx, state) {
+            var actual_idx = carousel.index(idx),
+                navigation = $(item).parents('.jcarousel-container').find('.jcarousel-navigation');
+
+            $('li,a', navigation).removeClass('active');
+            $('a:contains(' + actual_idx + ')').addClass('active');
+          }
+      };
+      
+    }
+
     // Change next and previous buttons to links for accessibility.
     if (!options.hasOwnProperty('buttonNextHTML') && !options.hasOwnProperty('buttonPrevHTML')) {
       options.buttonNextHTML = '<a href="javascript:void(0)"></a>';
@@ -73,7 +119,7 @@ Drupal.jcarousel.ajaxLoadCallback = function(jcarousel, state) {
   });
 
   // Copied from ajax_view.js:
-  var viewData = { 'js': 1, 'first': jcarousel.first - 1, 'last': jcarousel.last };
+  var viewData = {'js': 1, 'first': jcarousel.first - 1, 'last': jcarousel.last};
   // Construct an object using the settings defaults and then overriding
   // with data specific to the link.
   $.extend(
@@ -88,7 +134,7 @@ Drupal.jcarousel.ajaxLoadCallback = function(jcarousel, state) {
     success: function(response) {
       Drupal.jcarousel.ajaxResponseCallback(jcarousel, target, response)
     },
-    error: function(xhr) { Drupal.jcarousel.ajaxErrorCallback(xhr, ajaxPath); },
+    error: function(xhr) {Drupal.jcarousel.ajaxErrorCallback(xhr, ajaxPath);},
     dataType: 'json'
   });
 
diff --git a/skins/default/jcarousel-default.css b/skins/default/jcarousel-default.css
index 9166f5f..3bd03ef 100644
--- a/skins/default/jcarousel-default.css
+++ b/skins/default/jcarousel-default.css
@@ -152,3 +152,7 @@
   background-position: -96px -96px;
 }
 
+.jcarousel-skin-default .jcarousel-pager li {
+  display: inline;
+  margin-right: 2px;
+}
diff --git a/skins/tango/jcarousel-tango.css b/skins/tango/jcarousel-tango.css
index ab4c3d6..437ed44 100644
--- a/skins/tango/jcarousel-tango.css
+++ b/skins/tango/jcarousel-tango.css
@@ -155,3 +155,7 @@
   background-position: -96px -96px;
 }
 
+.jcarousel-skin-tango .jcarousel-pager li {
+  display: inline;
+  margin-right: 2px;
+}
