cvs diff: Diffing .
cvs diff: Diffing database
cvs diff: Diffing includes
Index: includes/tablesort.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/tablesort.inc,v
retrieving revision 1.36
diff -u -r1.36 tablesort.inc
--- includes/tablesort.inc	25 Aug 2005 21:14:16 -0000	1.36
+++ includes/tablesort.inc	31 Aug 2005 23:01:45 -0000
@@ -20,6 +20,32 @@
 }
 
 /**
+ * Set-up required attributes for Ajax tablesort and return whether we are
+ * currently handling an Ajax request.
+ */
+function tablesort_ajax($header, &$attributes) {
+  // Tables with an id can be sorted through Ajax
+  if (isset($attributes['id'])) {
+    // Determine if there are any sortable columns.
+    $tablesort = false;
+    foreach ($header as $item) {
+      if (is_array($item) && isset($item['field'])) {
+        $tablesort = true;
+        break;
+      }
+    }
+    // Mark the table if needed
+    if ($tablesort) {
+      drupal_add_js('misc/tablesort.js');
+      $attributes['class'] = trim($attributes['class'] .' tablesort');
+      // Are we currently handling an Ajax request for this table?
+      return $_GET['tablesort'] == $attributes['id'];
+    }
+  }
+  return FALSE;
+}
+
+/**
  * Fetch pager link arguments.
  *
  * When producing a sortable table that presents paged data, pass the output
@@ -87,7 +113,7 @@
       $image = '';
     }
     $cell['data'] = l($cell['data'] . $image, $_GET['q'], array('title' => $title), 'sort='. $ts['sort'] .'&order='. urlencode($cell['data']). $ts['query_string'], NULL, FALSE, TRUE);
-
+    $cell['class'] = trim($cell['class'] .' tablesort');
     unset($cell['field'], $cell['sort']);
   }
   return $cell;
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.256
diff -u -r1.256 theme.inc
--- includes/theme.inc	28 Aug 2005 15:29:34 -0000	1.256
+++ includes/theme.inc	31 Aug 2005 23:01:49 -0000
@@ -692,15 +692,20 @@
  *
  * @param $attributes
  *   An array of HTML attributes to apply to the table tag.
+ * @param $ajax
+ *   Whether this table should be sorted using Ajax. If set to TRUE, you must
+ *   pass a valid $attributes['id'].
  * @return
  *   An HTML string representing the table.
  */
 function theme_table($header, $rows, $attributes = NULL) {
-
+  // Initialize Ajax tablesort
+  $shortcircuit = tablesort_ajax($header, $attributes);
   $output = '<table'. drupal_attributes($attributes) .">\n";
 
   // Format the table header:
   if (count($header)) {
+    // Note: tablesort_init() may modify $attributes
     $ts = tablesort_init($header);
     $output .= ' <tr>';
     foreach ($header as $cell) {
@@ -751,6 +756,13 @@
   }
 
   $output .= "</table>\n";
+
+  // Print table directly if doing an Ajax request for this table
+  if ($shortcircuit) {
+    print $output;
+    exit;
+  }
+
   return $output;
 }
 
cvs diff: Diffing misc
Index: misc/drupal.css
===================================================================
RCS file: /cvs/drupal/drupal/misc/drupal.css,v
retrieving revision 1.116
diff -u -r1.116 drupal.css
--- misc/drupal.css	31 Aug 2005 21:17:26 -0000	1.116
+++ misc/drupal.css	31 Aug 2005 23:01:51 -0000
@@ -570,6 +570,7 @@
   background: #0072b9;
   color: #fff;
 }
+
 /* Animated throbber */
 html.js input.form-autocomplete {
   background: url('throbber.gif') no-repeat 100% 2px;
@@ -577,6 +578,12 @@
 html.js input.throbbing {
   background-position: 100% -18px;
 }
+html.js th.tablesort {
+  padding-right: 18px;
+}
+html.js th.throbbing {
+  background: url('throbber.gif') no-repeat 100% -18px;
+}
 
 /*
 ** Progressbar styles
Index: misc/tablesort.js
===================================================================
RCS file: misc/tablesort.js
diff -N misc/tablesort.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ misc/tablesort.js	31 Aug 2005 23:01:51 -0000
@@ -0,0 +1,76 @@
+// $Id$
+
+if (isJsEnabled()) {
+  addLoadEvent(tablesortAutoAttach);
+}
+
+/**
+ * Attach the tablesort behaviour to specially marked tables.
+ */
+function tablesortAutoAttach() {
+  var tables = document.getElementsByTagName('table');
+  var header, table;
+  // Find specially marked tables
+  for (var i = 0; table = tables[i]; i++) {
+    if (!hasClass(table, 'tablesort')) {
+      continue;
+    }
+    var ts = new tablesort(table);
+    // Find all the header cells
+    headers = table.getElementsByTagName('th');
+    if (headers.length == 0) {
+      continue;
+    }
+    for (var j = 0; header = headers[j]; j++) {
+      // Find the first link
+      var links = header.getElementsByTagName('a');
+      if (links.length == 0) {
+        continue;
+      }
+      var link = links[0];
+      // Install onclick override
+      link.onclick = function() {
+        ts.doSort(this);
+        this.blur();
+        this.onclick = function() {
+          return false;
+        }
+        return false;
+      }
+    }
+  }
+}
+
+/**
+ * A tablesort object tied to a particular <table>.
+ */
+function tablesort(table) {
+  var ts = this;
+  this.table = table;
+}
+
+/**
+ * Sort the table by a new column
+ */
+tablesort.prototype.doSort = function (link) {
+  var header = link.parentNode;
+  this.uri = link.href + '&tablesort=' + escape(this.table.id);
+  addClass(header, 'throbbing');
+  HTTPGet(this.uri, this.receiveSort, this);  
+}
+
+/**
+ * HTTP callback function. Replaces the entire table with the new one.
+ */
+tablesort.prototype.receiveSort = function(string, xmlhttp, ts) {
+  if (xmlhttp.status != 200) {
+    return alert('An HTTP error '+ xmlhttp.status +' occured.\n'+ ts.uri);
+  }
+  // Create DOM node for new table
+  var div = document.createElement('div');
+  div.innerHTML = string;
+  // Replace old table
+  ts.table.parentNode.replaceChild(div, ts.table);
+  // Re-attach behaviour
+  tablesortAutoAttach();
+}
cvs diff: Diffing modules
Index: modules/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment.module,v
retrieving revision 1.368
diff -u -r1.368 comment.module
--- modules/comment.module	30 Aug 2005 15:22:29 -0000	1.368
+++ modules/comment.module	31 Aug 2005 23:01:57 -0000
@@ -1036,7 +1036,7 @@
     $rows[] = array(array('data' => t('No comments available.'), 'colspan' => '6'));
   }
 
-  return theme('table', $header, $rows);
+  return theme('table', $header, $rows, array('id' => 'comment-admin-overview'));
 }
 
 /**
Index: modules/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum.module,v
retrieving revision 1.266
diff -u -r1.266 forum.module
--- modules/forum.module	30 Aug 2005 15:22:29 -0000	1.266
+++ modules/forum.module	31 Aug 2005 23:01:58 -0000
@@ -953,7 +953,7 @@
     }
   }
 
-  $output .= theme('table', $forum_topic_list_header, $rows);
+  $output .= theme('table', $forum_topic_list_header, $rows, array('id' => 'forum-topic-list'));
 
   return $output;
 }
Index: modules/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node.module,v
retrieving revision 1.526
diff -u -r1.526 node.module
--- modules/node.module	30 Aug 2005 15:22:29 -0000	1.526
+++ modules/node.module	31 Aug 2005 23:02:03 -0000
@@ -920,6 +920,14 @@
   $output .= form_group(t('Show only items where'), $form);
 
   // Build query
+  $header = array(NULL,
+                  array('data' => t('Title'), 'field' => 'n.title'),
+                  array('data' => t('Type'), 'field' => 'n.type'),
+                  array('data' => t('Author'), 'field' => 'u.name'),
+                  array('data' => t('Status'), 'field' => 'n.status'),
+                  array('data' => t('Last Updated'), 'field' => 'n.changed', 'sort' => 'desc'),
+                  t('Operations'));
+
   $where = $args = array();
   $join = '';
   foreach ($session as $filter) {
@@ -936,7 +944,7 @@
     $join .= $filters[$key]['join'];
   }
   $where = count($where) ? 'WHERE '. implode(' AND ', $where) : '';
-  $result = pager_query('SELECT n.*, u.name, u.uid FROM {node} n '. $join .' INNER JOIN {users} u ON n.uid = u.uid '. $where .' ORDER BY n.changed DESC', 50, 0, NULL, $args);
+  $result = pager_query('SELECT n.*, u.name, u.uid FROM {node} n '. $join .' INNER JOIN {users} u ON n.uid = u.uid '. $where . tablesort_sql($header), 50, 0, NULL, $args);
 
   // Make sure the update controls are disabled if we don't have any rows to select from.
   $disabled = !db_num_rows($result);
@@ -953,8 +961,6 @@
   $output .= '</div>';
 
   // Overview table:
-  $header = array(NULL, t('Title'), t('Type'), t('Author'), t('Status'), t('Operations'));
-
   $destination = drupal_get_destination();
   while ($node = db_fetch_object($result)) {
     $rows[] = array(form_checkbox(NULL, 'nodes]['. $node->nid, 1, 0),
@@ -962,6 +968,7 @@
                     node_get_name($node),
                     theme('username', $node),
                     ($node->status ? t('published') : t('not published')),
+                    format_date($node->created, 'small'),
                     l(t('edit'), 'node/'. $node->nid .'/edit', array(), $destination));
   }
 
@@ -973,7 +980,7 @@
     $rows[] = array(array('data' => t('No posts available.'), 'colspan' => '6'));
   }
 
-  $output .= theme('table', $header, $rows);
+  $output .= theme('table', $header, $rows, array('id' => 'node-admin-nodes'));
   return form($output, 'post', url('admin/node/action'));
 }
 
Index: modules/path.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/path.module,v
retrieving revision 1.62
diff -u -r1.62 path.module
--- modules/path.module	25 Aug 2005 21:14:16 -0000	1.62
+++ modules/path.module	31 Aug 2005 23:02:04 -0000
@@ -277,7 +277,7 @@
     $rows[] = array(array('data' => t('No URL aliases available.'), 'colspan' => '4'));
   }
 
-  return theme('table', $header, $rows);
+  return theme('table', $header, $rows, array('id' => 'path-overview'));
 }
 
 /**
Index: modules/statistics.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics.module,v
retrieving revision 1.204
diff -u -r1.204 statistics.module
--- modules/statistics.module	25 Aug 2005 21:14:17 -0000	1.204
+++ modules/statistics.module	31 Aug 2005 23:02:07 -0000
@@ -182,7 +182,7 @@
     }
 
     drupal_set_title(check_plain($node->title));
-    return theme('table', $header, $rows);
+    return theme('table', $header, $rows, array('id' => 'statistics-node-tracker'));
   }
   else {
     drupal_not_found();
@@ -210,7 +210,7 @@
     }
 
     drupal_set_title($account->name);
-    return theme('table', $header, $rows);
+    return theme('table', $header, $rows, array('id' => 'statistics-user-tracker'));
   }
   else {
     drupal_not_found();
@@ -243,7 +243,7 @@
     $rows[] = array(array('data' => $pager, 'colspan' => '4'));
   }
 
-  return theme('table', $header, $rows);
+  return theme('table', $header, $rows, array('id' => 'statistics-recent-hits'));
 }
 
 /**
@@ -271,7 +271,7 @@
   }
 
   drupal_set_title(t('Top pages in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
-  return theme('table', $header, $rows);
+  return theme('table', $header, $rows, array('id' => 'statistics-top-pages'));
 }
 
 /**
@@ -301,7 +301,7 @@
   }
 
   drupal_set_title(t('Top visitors in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
-  return theme('table', $header, $rows);
+  return theme('table', $header, $rows, array('id' => 'statistics-top-visitors'));
 }
 
 /**
@@ -328,7 +328,7 @@
     $rows[] = array(array('data' => $pager, 'colspan' => '3'));
   }
 
-  return theme('table', $header, $rows);
+  return theme('table', $header, $rows, array('id' => 'statistics-top-referrers'));
 }
 
 /**
Index: modules/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user.module,v
retrieving revision 1.502
diff -u -r1.502 user.module
--- modules/user.module	25 Aug 2005 21:14:17 -0000	1.502
+++ modules/user.module	31 Aug 2005 23:02:12 -0000
@@ -1734,7 +1734,7 @@
   if (!empty($pager)) {
     $rows[] = array(array('data' => $pager, 'colspan' => '5'));
   }
-  return theme('table', $header, $rows);
+  return theme('table', $header, $rows, array('id' => 'user-admin-account'));
 }
 
 function user_configure() {
Index: modules/watchdog.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/watchdog.module,v
retrieving revision 1.126
diff -u -r1.126 watchdog.module
--- modules/watchdog.module	25 Aug 2005 21:14:17 -0000	1.126
+++ modules/watchdog.module	31 Aug 2005 23:02:13 -0000
@@ -123,7 +123,7 @@
   }
 
   $output  = '<div class="container-inline">'. form($form) .'</div>';
-  $output .= theme('table', $header, $rows);
+  $output .= theme('table', $header, $rows, array('id' => 'watchdog-overview'));
 
   return $output;
 }
