Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.343
diff -u -p -r1.343 form.inc
--- includes/form.inc	20 Jun 2009 15:17:38 -0000	1.343
+++ includes/form.inc	30 Jun 2009 22:11:02 -0000
@@ -2125,6 +2125,35 @@ function form_process_checkboxes($elemen
 }
 
 /**
+ * Assist in adding JavaScript accordions to pages.
+ *
+ * @param $form
+ *   A form to check for a accordion property, which if present will trigger
+ *   the addition of the accordion JavaScript and CSS files to the form.
+ * @return
+ *   The processed form.
+ */
+function form_add_accordion($form) {
+  $accordion = isset($form['#accordion']) ? $form['#accordion'] : FALSE;
+  if (!$accordion) {
+    return $form;
+  }
+  $table = $accordion['table'];
+  $links = $accordion['links'];
+  // Add the accordion JavaScript to the page before the module JavaScript to
+  // ensure that accordion behaviors are registered before any module uses it.
+  $form['#attached_js']['misc/accordion.js'] = array('weight' => -1);
+  $form['#attached_js'][] = 'misc/ahah.js';
+  $form['#attached_js'][] = 'misc/jquery.form.js';
+  $form['#attached_js'][] = 'misc/progress.js';
+  $settings['accordion'][$table] = $links;
+  $form['#attached_js'][] = array('data' => $settings, 'type' => 'setting');
+  $form['#attached_css'][] = 'misc/accordion.css';
+
+  return $form;
+}
+
+/**
  * Format a table with radio buttons or checkboxes.
  *
  * @param $element
Index: misc/accordion-rtl.css
===================================================================
RCS file: misc/accordion-rtl.css
diff -N misc/accordion-rtl.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ misc/accordion-rtl.css	30 Jun 2009 21:51:40 -0000
@@ -0,0 +1,11 @@
+/* $Id$ */
+
+div.accordion-options div.option {
+  float: right;
+  padding-right: 0;
+  padding-left: 20px;
+}
+
+div.accordion-throbber {
+  float: right;
+}
Index: misc/accordion.css
===================================================================
RCS file: misc/accordion.css
diff -N misc/accordion.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ misc/accordion.css	30 Jun 2009 21:51:40 -0000
@@ -0,0 +1,39 @@
+/* $Id$ */
+
+div.accordion-options {
+  display: none;
+}
+
+tr.show div.accordion-options, tr.active div.accordion-options {
+  display: block;
+}
+
+div.accordion-form {
+  display: none;
+}
+
+tr.accordion-row {
+  background-color: #fff7c9;
+}
+
+div.accordion-form {
+  max-height: 400px;
+  overflow: auto;
+}
+
+div.accordion-options div.option {
+  float: left; /* LTR */
+  padding-right: 20px; /* LTR */
+}
+
+div.option.active a {
+  color: #000000;
+}
+
+div.accordion-throbber {
+  width: 15px;
+  height: 15px;
+  margin: 2px;
+  background: transparent url(throbber.gif) no-repeat 0px -18px;
+  float: left; /* LTR */
+}
Index: misc/accordion.js
===================================================================
RCS file: misc/accordion.js
diff -N misc/accordion.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ misc/accordion.js	30 Jun 2009 22:10:24 -0000
@@ -0,0 +1,231 @@
+(function ($) {
+
+/**
+ * Attaches the accordion behavior for the flooded state screens.
+ */
+Drupal.behaviors.accordion = {
+  attach: function (context, settings) {
+    $('body', context).click(function (event) {
+      var target = event.target;
+      accordionHideRows(target);
+    });
+
+    var table;
+    for (table in settings.accordion) {
+      var link = settings.accordion[table];
+
+      $('table' + table + ':not(.accordion-processed)', context).each(function () {
+        Drupal.accordions.prepare(this, link);
+      }).addClass('accordion-processed');
+
+      // Bind the ajaxSubmit behavior to all accordion-loaded forms.
+      $('table' + table + ' form:not(.accordion-processed)').each(function () {
+        $(this).submit(function () {
+          $(this).children('div').append('<div class="accordion-throbber"/>');
+          var options = {
+            success: function (response) {
+              var messages = Drupal.parseJson(response.messages);
+              messages = typeof messages == 'object' ? messages.data : '';
+              var ajaxResponse = $('#ajaxform-response').html(messages);
+              ajaxResponse.find('a').click(function() {
+                $(this).closest('tr.accordion-row').remove();
+                var tr = $(this).closest('tr.accordion-row').get(0).previousSibling;
+                $(tr).removeClass('active').find('div.accordion-options div.option').removeClass('active');
+                return false;
+              });
+              ajaxResponse.siblings().remove();
+            },
+            dataType: 'json'
+          };
+          $(this).ajaxSubmit(options);
+          $(this).find(':input').attr('disabled', 'disabled');
+          return false;
+        });
+        $(this).find('a.cancel-link').click(function() {
+          var tr = $(this).closest('tr.accordion-row').get(0).previousSibling;
+          $(this).closest('tr.accordion-row').remove();
+          $(tr).removeClass('active').find('div.accordion-options div.option').removeClass('active');
+          return false;
+        });
+      }).addClass('accordion-processed');
+    }
+  }
+}
+
+Drupal.accordions = Drupal.accordions || {};
+
+// Setting up the inital behaviours.
+Drupal.accordions.prepare = function (el, link) {
+  $(el).find('tr')
+  .hover(function () {
+    $(this).addClass('show');
+  }, function () {
+    $(this).removeClass('show');
+  })
+  .find(link).addClass('accordion-options').each(function () {
+    var i = 0;
+    var idArray = this.id.split('-');
+    var entityType = idArray[0];
+    var hid = idArray[2];
+    $(this).find('div.option a').each(function () {
+      this.tabIndex = i++;
+      this.hid = hid;
+      this.entityType = entityType;
+      $(this).bind('click', function () {
+        accordionHideRows(this);
+        var table = $(this).closest('table');
+        var link = Drupal.settings.accordion['#' + table.attr('id')];
+        return accordionClick(this, link);
+      });
+    });
+  }).addClass('accordion-options');
+}
+
+Drupal.accordions.tab = function (el) {
+  this.element = el;
+  var myId = el.id.split('-');
+  this.entityType = el.entityType;
+  this.entityOp = myId[1];
+  this.entityId = myId[2];
+  this.tabIndex = el.tabIndex;
+  this.hid = el.hid;
+
+  var tab = this;
+  this.options = {
+    success: function (response) {
+      return tab.success(response);
+    },
+    complete: function (response) {
+      return tab.complete();
+    }
+  };
+}
+
+// AJAX callback.
+Drupal.accordions.tab.prototype.success = function (response) {
+  var result = Drupal.parseJson(response.data);
+  var javaScript = Drupal.parseJson(response.javaScript);
+  var css = Drupal.parseJson(response.css);
+  result = typeof result == 'object' ? result.data : '';
+  javaScript = typeof javaScript == 'object' ? javaScript.data : '';
+  css = typeof css == 'object' ? css.data : '';
+  $(javaScript).filter(function() {
+    var alreadyAdded = false;
+    var src = $(this).attr('src');
+    if (typeof src == 'string' && src.length) {
+      $('script').each(function() {
+        if ($(this).attr('src') == src) {
+          alreadyAdded = true;
+        }
+      });
+    }
+    return !alreadyAdded;
+  }).each(function() {
+    $(this).insertAfter('script:last');
+  });
+  $(css).filter(function() {
+    var alreadyAdded = false;
+    var href = $(this).attr('src');
+    if (typeof href == 'string' && href.length) {
+      $('link').each(function() {
+        if ($(this).attr('type') == 'text/css' && $(this).attr('href') == href) {
+          alreadyAdded = true;
+        }
+      });
+    }
+    return !alreadyAdded;
+  }).each(function() {
+    $(this).insertAfter('link[type=text/css]:last');
+  });
+  this.container.html(Drupal.theme('accordionResponse', this, result));
+  $('#tab-content-' + this.hid + '-' + this.tabIndex).slideDown('slow');
+  Drupal.attachBehaviors(this.container);
+}
+
+// Function to call on completed ajax call.
+Drupal.accordions.tab.prototype.complete = function () {
+  // Stop the progress bar.
+  this.stopProgress();
+}
+
+Drupal.accordions.tab.prototype.stopProgress = function () {
+  if (this.progress.element) {
+    $(this.progress.element).remove();
+  }
+  $(this.element).removeClass('progress-disabled').attr('disabled', false);
+}
+
+Drupal.accordions.tab.prototype.startProgress = function () {
+  var progressBar = new Drupal.progressBar('accordion-progress-' + this.element.id, null, null, null);
+  progressBar.setProgress(-1, Drupal.t('Loading...'));
+  this.progress = {};
+  this.progress.element = $(progressBar.element).addClass('accordion-progress accordion-progress-bar');
+  this.container.prepend(this.progress.element);
+}
+
+var accordionClick = function (a, link) {
+  var hid = $(a).attr('hid');
+  var entityType = $(a).attr('entityType');
+  var tabIndex = $(a).attr('tabIndex');
+  if (!$('#accordion-container-' + hid).size()) {
+    var newContainer = $('<tr></tr>').attr('id', 'accordion-container-' + hid).addClass('accordion-row');
+    newContainer.append('<td colspan="7"></td>').insertAfter($('#' + entityType + '-accordion-' + hid).parents('tr'));
+  }
+  // Only make the ajax request if the form is not already there.
+  if (!$('#tab-content-' + hid + '-' + tabIndex).size()) {
+    // Set clicked tab to active.
+    $(a).parents('div.option').siblings().removeClass('active');
+    $(a).parents('div.option').addClass('active');
+
+    // Set this row to active.
+    $(a).closest('tr').addClass('active');
+
+    if ($('#accordion-container-' + hid).find('.accordion-form form').size()) {
+      $('#accordion-container-' + hid).find('.accordion-form').remove();
+    }
+
+    var tab = new Drupal.accordions.tab(a);
+    $('tr.accordion-row:not(#accordion-container-' + hid + ')').remove();
+
+    tab.container = $('#accordion-container-' + hid).children('td');
+
+    tab.startProgress();
+    // Construct the ajax path to retrieve the content, depending on type.
+    var qtAjaxPath = Drupal.settings.basePath + (location.href.indexOf('?q=') != -1 ? '?q=' : '') + 'edit/inline/' + tab.entityType + '/' + tab.entityOp + '/' + tab.entityId;
+
+    $.ajax({
+      url: qtAjaxPath,
+      type: 'GET',
+      data: null,
+      success: tab.options.success,
+      complete: tab.options.complete,
+      dataType: 'json'
+    });
+  }
+  return false;
+}
+
+var accordionHideRows = function (target) {
+  $('tr.accordion-row').filter(function () {
+    var row = this;
+    var exempt = false;
+    // The row(s) that were clicked on are exempt.
+    $(target).parents('tr.accordion-row').each(function () {
+      if (row == this) {
+        exempt = true;
+      }
+    });
+    if (!exempt) {
+      $(this.previousSibling).removeClass('active').find('div.accordion-options div.option').removeClass('active');
+    }
+    return !exempt;
+  }).remove();
+}
+
+// Theme function for ajax response.
+Drupal.theme.prototype.accordionResponse = function (tab, result) {
+  var newContent = '<div id="ajaxform-response" class="message status"></div><div id="tab-content-' + tab.hid + '-' + tab.tabIndex + '" class="accordion-form">' + result + '</div>';
+  return newContent;
+};
+
+})(jQuery);
\ No newline at end of file
Index: modules/filter/filter.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.css,v
retrieving revision 1.1
diff -u -p -r1.1 filter.css
--- modules/filter/filter.css	30 Mar 2009 03:15:40 -0000	1.1
+++ modules/filter/filter.css	29 Jun 2009 20:05:50 -0000
@@ -3,18 +3,18 @@
 .text-format-wrapper .form-item {
   margin-bottom: 0;
 }
-.filter-wrapper {
+fieldset.filter-wrapper {
   border-top: 0;
   width: 95%;
   margin: 0;
   padding: 1.5em 0 1.5em;
 }
-.filter-wrapper .form-item {
+fieldset.filter-wrapper .form-item {
   float: left;
   margin: 0;
   padding: 0 0 0.5em 1.5em;
 }
-.filter-wrapper .form-item label {
+fieldset.filter-wrapper .form-item label {
   display: inline;
 }
 .filter-help {
Index: modules/node/node.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.admin.inc,v
retrieving revision 1.54
diff -u -p -r1.54 node.admin.inc
--- modules/node/node.admin.inc	5 Jun 2009 05:28:28 -0000	1.54
+++ modules/node/node.admin.inc	30 Jun 2009 21:51:41 -0000
@@ -428,6 +428,12 @@ function node_admin_content($form_state)
   $form = node_filter_form();
 
   $form['#theme'] = 'node_filter_form';
+
+  $form['#accordion'] = array(
+    'table' => '#node-admin-nodes-table',
+    'links' => '.node-operations',
+  );
+
   $form['admin'] = node_admin_nodes();
 
   return $form;
@@ -489,8 +495,10 @@ function node_admin_nodes() {
 
   $languages = language_list();
   $destination = drupal_get_destination();
+  $i = 0;
   $nodes = array();
   while ($node = db_fetch_object($result)) {
+    $i++;
     $nodes[$node->nid] = '';
     $options = empty($node->language) ? array() : array('language' => $languages[$node->language]);
     $form['title'][$node->nid] = array('#markup' => l($node->title, 'node/' . $node->nid, $options) . ' ' . theme('mark', node_mark($node->nid, $node->changed)));
@@ -501,7 +509,12 @@ function node_admin_nodes() {
     if ($multilanguage) {
       $form['language'][$node->nid] = array('#markup' => empty($node->language) ? t('Language neutral') : t($languages[$node->language]->name));
     }
-    $form['operations'][$node->nid] = array('#markup' => l(t('edit'), 'node/' . $node->nid . '/edit', array('query' => $destination)));
+    $form['operations'][$node->nid] = array('#prefix' => '<div class="node-operations" id="node-accordion-' . $i . '">', '#suffix' => '</div>');
+    $form['operations'][$node->nid]['edit'] = array(
+      '#markup' => l(t('edit'), 'node/' . $node->nid . '/edit', array('query' => $destination, 'attributes' => array('id' => 'node-edit-' . $node->nid))),
+      '#prefix' => '<div class="option">',
+      '#suffix' => '</div>',
+    );
   }
   $form['nodes'] = array(
     '#type' => 'checkboxes',
@@ -590,7 +603,7 @@ function theme_node_admin_nodes($form) {
     );
   }
 
-  $output .= theme('table', $header, $rows);
+  $output .= theme('table', $header, $rows, array('id' => 'node-admin-nodes-table'));
 
   if ($form['pager']['#markup']) {
     $output .= drupal_render($form['pager']);
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1073
diff -u -p -r1.1073 node.module
--- modules/node/node.module	24 Jun 2009 18:16:38 -0000	1.1073
+++ modules/node/node.module	29 Jun 2009 19:51:03 -0000
@@ -3180,3 +3180,18 @@ function node_requirements($phase) {
   );
   return $requirements;
 }
+
+/**
+ * Implement hook_inline_edit_callback().
+ */
+function node_inline_edit_callback($op, $nid) {
+  $node = node_load($nid);
+  if (empty($node) || empty($node->nid) || empty($nid)) {
+    return;
+  }
+  $output = '';
+  if ($op == 'edit') {
+    $output = drupal_render(drupal_get_form($node->type . '_node_form', $node));
+  }
+  return $output;
+}
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.158
diff -u -p -r1.158 system.admin.inc
--- modules/system/system.admin.inc	19 Jun 2009 20:35:05 -0000	1.158
+++ modules/system/system.admin.inc	30 Jun 2009 03:48:36 -0000
@@ -2220,3 +2220,25 @@ function theme_system_themes_form($form)
   $output .= drupal_render_children($form);
   return $output;
 }
+
+
+function edit_inline($type, $op, $uid) {
+  $function = $type . '_inline_edit_callback';
+  if (drupal_function_exists($function)) {
+    $output = $function($op, $uid);
+  }
+
+  // Add a default message if no message was set.
+  $messages = drupal_get_messages(NULL, FALSE);
+  if (empty($messages)) {
+    drupal_set_message(t('The changes have been saved.'));
+  }
+
+  // Clear and retrieve any messages that may have been set.
+  $messages = theme('status_messages');
+  $javascript = drupal_get_js();
+  $css = drupal_get_css();
+
+  // Output the data.
+  drupal_json(array('status' => 0, 'data' => $output, 'messages' => $messages, 'javaScript' => $javascript, 'css' => $css));
+}
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.715
diff -u -p -r1.715 system.module
--- modules/system/system.module	23 Jun 2009 12:11:19 -0000	1.715
+++ modules/system/system.module	30 Jun 2009 21:51:42 -0000
@@ -250,6 +250,7 @@ function system_elements() {
   $type['form'] = array(
     '#method' => 'post',
     '#action' => request_uri(),
+    '#process' => array('form_add_accordion'),
     '#theme_wrapper' => 'form',
   );
 
@@ -779,6 +780,13 @@ function system_menu() {
     'access arguments' => array('administer site configuration'),
     'type' => MENU_CALLBACK,
   );
+  // Dispatcher for inline editing.
+  $items['edit/inline'] = array(
+    'title' => 'Edit stuff',
+    'page callback' => 'edit_inline',
+    'access arguments' => array('administer site configuration'),
+    'type' => MENU_CALLBACK,
+  );
   // Default page for batch operations.
   $items['batch'] = array(
     'page callback' => 'system_batch_page',
@@ -1679,7 +1687,7 @@ function confirm_form($form, $question, 
     $fragment = isset($path['fragment']) ? $path['fragment'] : NULL;
     $path = isset($path['path']) ? $path['path'] : NULL;
   }
-  $cancel = l($no ? $no : t('Cancel'), $path, array('query' => $query, 'fragment' => $fragment));
+  $cancel = l($no ? $no : t('Cancel'), $path, array('query' => $query, 'fragment' => $fragment, 'attributes' => array('class' => 'cancel-link')));
 
   drupal_set_title($question, PASS_THROUGH);
 
Index: modules/user/user.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v
retrieving revision 1.58
diff -u -p -r1.58 user.admin.inc
--- modules/user/user.admin.inc	15 Jun 2009 09:49:58 -0000	1.58
+++ modules/user/user.admin.inc	30 Jun 2009 21:51:42 -0000
@@ -126,7 +126,6 @@ function user_filter_form_submit($form, 
  * @see user_admin_account_submit()
  */
 function user_admin_account() {
-
   $header = array(
     array(),
     array('data' => t('Username'), 'field' => 'u.name'),
@@ -153,6 +152,11 @@ function user_admin_account() {
     ->setCountQuery($count_query);
   $result = $query->execute();
 
+  $form['#accordion'] = array(
+    'table' => '#user-admin-account-table',
+    'links' => '.user-operations',
+  );
+
   $form['options'] = array(
     '#type' => 'fieldset',
     '#title' => t('Update options'),
@@ -178,7 +182,7 @@ function user_admin_account() {
   $status = array(t('blocked'), t('active'));
   $roles = user_roles(TRUE);
   $accounts = array();
-  foreach ($result as $account) {
+  foreach ($result as $i => $account) {
     $accounts[$account->uid] = '';
     $form['name'][$account->uid] = array('#markup' => theme('username', $account));
     $form['status'][$account->uid] =  array('#markup' => $status[$account->status]);
@@ -191,7 +195,9 @@ function user_admin_account() {
     $form['roles'][$account->uid][0] = array('#markup' => theme('item_list', $users_roles));
     $form['member_for'][$account->uid] = array('#markup' => format_interval(REQUEST_TIME - $account->created));
     $form['last_access'][$account->uid] =  array('#markup' => $account->access ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $account->access))) : t('never'));
-    $form['operations'][$account->uid] = array('#markup' => l(t('edit'), "user/$account->uid/edit", array('query' => $destination)));
+    $form['operations'][$account->uid] = array('#prefix' => '<div class="user-operations" id="user-accordion-' . $i . '">', '#suffix' => '</div>');
+    $form['operations'][$account->uid]['edit'] = array('#markup' => l(t('edit'), "user/$account->uid/edit", array('query' => $destination, 'attributes' => array('id' => 'user-edit-'. $account->uid))), '#prefix' => '<div class="option">', '#suffix' => '</div>');
+    $form['operations'][$account->uid]['cancel'] = array('#markup' => l(t('cancel'), "user/$account->uid/cancel", array('query' => $destination, 'attributes' => array('id' => 'user-cancel-'. $account->uid))), '#prefix' => '<div class="option">', '#suffix' => '</div>');
   }
   $form['accounts'] = array(
     '#type' => 'checkboxes',
@@ -824,7 +830,7 @@ function theme_user_admin_account($form)
     t('Roles'),
     array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
     array('data' => t('Last access'), 'field' => 'u.access'),
-    t('Operations')
+    t('User operations'),
   );
 
   $output = drupal_render($form['options']);
@@ -845,7 +851,7 @@ function theme_user_admin_account($form)
     $rows[] = array(array('data' => t('No users available.'), 'colspan' => '7'));
   }
 
-  $output .= theme('table', $header, $rows);
+  $output .= theme('table', $header, $rows, array('id' => 'user-admin-account-table'));
   if ($form['pager']['#markup']) {
     $output .= drupal_render($form['pager']);
   }
@@ -944,4 +950,4 @@ function user_modules_installed($modules
       }
     }
   }
-}
+}
\ No newline at end of file
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.1002
diff -u -p -r1.1002 user.module
--- modules/user/user.module	22 Jun 2009 09:10:07 -0000	1.1002
+++ modules/user/user.module	30 Jun 2009 04:02:13 -0000
@@ -2933,3 +2933,20 @@ function _user_forms(&$edit, $account, $
   return empty($groups) ? FALSE : $groups;
 }
 
+/**
+ * Implement hook_inline_edit_callback().
+ */
+function user_inline_edit_callback($op, $uid) {
+  $user = user_load($uid);
+  if (empty($user) || empty($user->uid) || empty($uid)) {
+    return;
+  }
+  $output = '';
+  if ($op == 'edit' && drupal_function_exists('user_edit')) {
+    $output = drupal_render(user_edit($user, 'account'));
+  }
+  elseif ($op == 'cancel') {
+    $output = drupal_render(drupal_get_form('user_cancel_confirm_form', $user));
+  }
+  return $output;
+}
