? ajax-pager-comments.diff
? sites/default/files
? sites/default/settings.php
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.808
diff -u -p -r1.808 common.inc
--- includes/common.inc	12 Oct 2008 19:03:04 -0000	1.808
+++ includes/common.inc	14 Oct 2008 16:08:52 -0000
@@ -2358,6 +2358,26 @@ function drupal_json($var = NULL) {
 }
 
 /**
+ * Handle a request for JSON data.
+ *
+ * @param $id
+ *   A unique ID for the request.
+ * @param $output
+ *   Output to render.
+ */
+function drupal_handle_json_request($id, $output) {
+  if (isset($_REQUEST['json_request']) && $_REQUEST['json_request'] == $id) {
+    $response = array(
+      'status' => TRUE,
+      'content' => $output,
+    );
+    drupal_json($response);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
  * Wrapper around urlencode() which avoids Apache quirks.
  *
  * Should be used when placing arbitrary data in an URL. Note that Drupal paths
@@ -2989,6 +3009,9 @@ function drupal_common_theme() {
       'arguments' => array('size' => 1),
     ),
     // from pager.inc
+    'pager_wrapper' => array(
+      'arguments' => array('contents' => '', 'id' => NULL),
+    ),
     'pager' => array(
       'arguments' => array('tags' => array(), 'limit' => 10, 'element' => 0, 'parameters' => array()),
     ),
Index: includes/pager.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/pager.inc,v
retrieving revision 1.64
diff -u -p -r1.64 pager.inc
--- includes/pager.inc	12 Oct 2008 04:30:05 -0000	1.64
+++ includes/pager.inc	14 Oct 2008 16:08:53 -0000
@@ -91,6 +91,23 @@ function pager_get_querystring() {
 }
 
 /**
+ * Wrap the output of a pager query, including the pager element.
+ *
+ * @param $contents
+ *   The contents of a pager query.
+ * @param $id
+ *   The id by which the pager element will be identified. Used in requesting JSON output.
+ * @return
+ *   An HTML string.
+ *
+ * @ingroup themeable
+ */
+function theme_pager_wrapper($contents, $id) {
+  drupal_add_js('misc/pager.js');
+  return '<div id="' . $id . '" class="pager-contents">' . $contents . '</div>';
+}
+
+/**
  * Format a query pager.
  *
  * Menu callbacks that display paged query results should call theme('pager') to
Index: misc/drupal.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/drupal.js,v
retrieving revision 1.46
diff -u -p -r1.46 drupal.js
--- misc/drupal.js	12 Oct 2008 00:29:09 -0000	1.46
+++ misc/drupal.js	14 Oct 2008 16:08:54 -0000
@@ -246,6 +246,14 @@ Drupal.getSelection = function (element)
 };
 
 /**
+ * Scroll the window to an element's top offset position.
+ */
+Drupal.scrollTo = function (element) {
+  var offset = $(element).offset();
+  window.scrollTo(0, offset.top);
+}
+
+/**
  * Build an error message from ahah response.
  */
 Drupal.ahahError = function(xmlhttp, uri) {
Index: misc/pager.js
===================================================================
RCS file: misc/pager.js
diff -N misc/pager.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ misc/pager.js	14 Oct 2008 16:08:54 -0000
@@ -0,0 +1,40 @@
+/**
+ * Ajax behavior for pagers. 
+ */
+Drupal.behaviors.pager = function(context) {
+  $('div.pager-contents:not(.pager-processed)', context).each(function() {
+    var $target = $(this);
+    $target
+      .addClass('pager-processed')
+      // Process pager links.
+      .find('ul.pager > li > a')
+      .each(function () {
+        var ajaxPath = $(this).attr('href');
+        $(this)
+          .click(function () {
+            $(this).addClass('throbber');
+            $.ajax({
+              url: ajaxPath,
+              type: 'GET',
+              data: {'json_request': $target.attr('id')},
+              success: function(response) {
+                $(this).removeClass('throbbing');
+                if (response.status && response.content) {
+                  var $newContent = $(response.content);
+                  $target.replaceWith($newContent);
+                  Drupal.attachBehaviors($newContent.parent());
+                  Drupal.scrollTo($newContent.parent());
+                }
+              },
+              error: function() {
+                $(this).removeClass('throbber');
+                alert(Drupal.t("An error occurred at @path.", {'@path': ajaxPath}));
+              },
+              dataType: 'json'
+            });
+
+            return false;
+          });
+        });
+    });
+};
Index: misc/throbber-active.gif
===================================================================
RCS file: misc/throbber-active.gif
diff -N misc/throbber-active.gif
Binary files /dev/null and throbber-active.gif differ
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.658
diff -u -p -r1.658 comment.module
--- modules/comment/comment.module	13 Oct 2008 00:33:02 -0000	1.658
+++ modules/comment/comment.module	14 Oct 2008 16:08:59 -0000
@@ -1006,8 +1006,13 @@ function comment_render($node, $cid = 0)
       while ($divs-- > 0) {
         $comments .= '</div>';
       }
-      $output .= $comments;
-      $output .= theme('pager', NULL, $comments_per_page, 0);
+      $pager_id = 'comment-pager-' . $node->nid;
+      $comments .= theme('pager', NULL, $comments_per_page, 0);
+      $output .= theme('pager_wrapper', $comments, $pager_id);
+      // Enable JSON output, if requested.
+      if (drupal_handle_json_request($pager_id, $output)) {
+        return NULL;
+      }
     }
 
     // If enabled, show new comment form if it's not already being displayed.
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.988
diff -u -p -r1.988 node.module
--- modules/node/node.module	13 Oct 2008 00:33:03 -0000	1.988
+++ modules/node/node.module	14 Oct 2008 16:09:08 -0000
@@ -1147,7 +1147,13 @@ function node_show($node, $cid, $message
   $output = node_view($node, FALSE, TRUE);
 
   if (function_exists('comment_render') && $node->comment) {
-    $output .= comment_render($node, $cid);
+    $comments = comment_render($node, $cid);
+    if ($comments == NULL) {
+      return NULL;
+    }
+    else {
+      $output .= $comments;
+    }
   }
 
   // Update the history table, stating that this user viewed this node.
Index: modules/system/system-rtl.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system-rtl.css,v
retrieving revision 1.13
diff -u -p -r1.13 system-rtl.css
--- modules/system/system-rtl.css	25 Apr 2008 18:28:18 -0000	1.13
+++ modules/system/system-rtl.css	14 Oct 2008 16:09:08 -0000
@@ -66,6 +66,12 @@ html.js fieldset.collapsed legend a {
   background-position: 98% 50%;
 }
 
+html.js a.throbber,
+html.js span.throbber {
+  background-position: left center;
+  padding-left: 18px;
+}
+
 div.teaser-button-wrapper {
   float: left;
   padding-right: 0;
Index: modules/system/system.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.css,v
retrieving revision 1.51
diff -u -p -r1.51 system.css
--- modules/system/system.css	5 May 2008 21:10:48 -0000	1.51
+++ modules/system/system.css	14 Oct 2008 16:09:08 -0000
@@ -347,6 +347,13 @@ html.js fieldset.collapsible .fieldset-w
   overflow: auto;
 }
 
+/* Animated throbber for links and spans */
+html.js a.throbber,
+html.js span.throbber {
+  background: url(../../misc/throbber-active.gif) no-repeat right center;  /* LTR */
+  padding-right: 18px;  /* LTR */
+}
+
 /*
 ** Resizable text areas
 */
