? .DS_Store
? phpinfo.php
? popups-193311-45_0.patch
? popups-193311-50.patch
? misc/popupapi.js
? modules/popuppage
? modules/system/popup-template.tpl.php
? sites/default/files
? sites/default/settings.php
Index: index.php
===================================================================
RCS file: /cvs/drupal/drupal/index.php,v
retrieving revision 1.94
diff -u -p -r1.94 index.php
--- index.php	26 Dec 2007 08:46:48 -0000	1.94
+++ index.php	20 Mar 2008 00:58:37 -0000
@@ -32,8 +32,7 @@ if (is_int($return)) {
   }
 }
 elseif (isset($return)) {
-  // Print any value (including an empty string) except NULL or undefined:
-  print theme('page', $return);
+  print render('page', $return);
 }
 
 drupal_page_footer();
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.206
diff -u -p -r1.206 bootstrap.inc
--- includes/bootstrap.inc	10 Jan 2008 22:47:17 -0000	1.206
+++ includes/bootstrap.inc	20 Mar 2008 00:58:37 -0000
@@ -271,7 +271,7 @@ function drupal_unset_globals() {
  * session name correctly.
  */
 function conf_init() {
-  global $base_url, $base_path, $base_root;
+  global $base_url, $base_path, $base_root, $render_mode, $request_mode;
 
   // Export the following settings.php variables to the global namespace
   global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access;
@@ -337,6 +337,10 @@ function conf_init() {
     ini_set('session.cookie_domain', $cookie_domain);
   }
   session_name('SESS'. md5($session_name));
+    
+  // TODO - add comments to describe what these globals control.
+  $render_mode = isset($_SERVER['HTTP_X_DRUPAL_RENDER_MODE']) ? $_SERVER['HTTP_X_DRUPAL_RENDER_MODE'] : 'xhtml/plain';
+  $request_mode = isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? $_SERVER['HTTP_X_REQUESTED_WITH'] : 'standard';  
 }
 
 /**
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.760
diff -u -p -r1.760 common.inc
--- includes/common.inc	17 Mar 2008 17:01:05 -0000	1.760
+++ includes/common.inc	20 Mar 2008 00:58:40 -0000
@@ -293,14 +293,14 @@ function drupal_get_destination() {
  *   supported.
  * @see drupal_get_destination()
  */
-function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
-
+// TODO - update comments to reflect breaking drupal_goto into two functions.
+function drupal_get_goto_url($path = '', $query = NULL, $fragment = NULL) {
   if (isset($_REQUEST['destination'])) {
     extract(parse_url(urldecode($_REQUEST['destination'])));
   }
   else if (isset($_REQUEST['edit']['destination'])) {
     extract(parse_url(urldecode($_REQUEST['edit']['destination'])));
-  }
+  } 
 
   $url = url($path, array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE));
   // Remove newlines from the URL to avoid header injection attacks.
@@ -311,19 +311,25 @@ function drupal_goto($path = '', $query 
   if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
     module_invoke_all('exit', $url);
   }
+  return $url;
+}
 
+function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
+  $url = drupal_get_goto_url($path, $query, $fragment);
+  
   // Even though session_write_close() is registered as a shutdown function, we
   // need all session data written to the database before redirecting.
   session_write_close();
-
+   
   header('Location: '. $url, TRUE, $http_response_code);
-
+  
   // The "Location" header sends a redirect status code to the HTTP daemon. In
   // some cases this can be wrong, so we make sure none of the code below the
   // drupal_goto() call gets executed upon redirection.
   exit();
 }
 
+
 /**
  * Generates a site off-line message.
  */
@@ -2629,6 +2635,44 @@ function drupal_alter($type, &$data) {
   }
 }
 
+/**
+ * Abstract the Drupal rendering system.
+ * Allow renderers other than the theme system to produce content output.
+ * Example of use: render('page', $content);
+ * 
+ * @param 
+ *   Array starting with the element being rendered (ex: 'page'),
+ *   followed by the content arguments. 
+ *
+ * @return 
+ *   Rendered content.
+ */
+function render() {
+  global $render_mode;
+  $args = func_get_args();
+  
+//  TODO - cache the renderer dispatch table.
+//  static $renderers;
+//  if (!$renderers) {
+//    // look in the cache
+//    //$renderers = cache_get('renderers');
+//    if (!$renderers) {
+//      $renderers = module_invoke_all('renderers'); // Build the renderer dispatch table
+//      cache_set('renderers', $renderers);
+//    }
+//  }
+
+  $renderers = module_invoke_all('renderers'); // Build the renderer dispatch table
+  $renderer = $renderers[$render_mode];
+  if ($renderer) {
+    return call_user_func_array($renderer, $args);  
+  }
+  else {
+    drupal_set_message(t('Attempting to use an unsupported render mode %render_mode.', array('%render_mode' => $render_mode)), 'error');
+    $args = func_get_args();
+    return call_user_func_array('theme', $args);
+  }
+}
 
 /**
  * Renders HTML given a structured array tree.
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.268
diff -u -p -r1.268 form.inc
--- includes/form.inc	15 Mar 2008 11:02:47 -0000	1.268
+++ includes/form.inc	20 Mar 2008 00:58:42 -0000
@@ -433,7 +433,9 @@ function drupal_process_form($form_id, &
       // however, we'll skip this and let the calling function examine
       // the resulting $form_state bundle itself.
       if (!$form['#programmed'] && empty($form_state['rebuild']) && empty($form_state['storage'])) {
-        drupal_redirect_form($form, $form_state['redirect']);
+        global $request_mode;
+        // TODO - more comments here, and update the above comments.
+        module_invoke_all('after_process_form', $request_mode, $form, $form_state);
       }
     }
   }
@@ -606,8 +608,13 @@ function drupal_render_form($form_id, &$
  * @param $redirect
  *   An optional value containing the destination path to redirect
  *   to if none is specified by the form.
+ * @param $do_goto
+ *   Boolean flag.  
+ *   If true, call to drupal_goto to do the redirect.
+ *   If false, return the url of the redirect, but don't go there.  This allows
+ *   for alternal flows of control, such as AJAX or webservices.
  */
-function drupal_redirect_form($form, $redirect = NULL) {
+function drupal_redirect_form($form, $redirect = NULL, $do_goto = TRUE) {
   $goto = NULL;
   if (isset($redirect)) {
     $goto = $redirect;
@@ -615,17 +622,31 @@ function drupal_redirect_form($form, $re
   if ($goto !== FALSE && isset($form['#redirect'])) {
     $goto = $form['#redirect'];
   }
-  if (!isset($goto) || ($goto !== FALSE)) {
-    if (isset($goto)) {
-      if (is_array($goto)) {
-        call_user_func_array('drupal_goto', $goto);
+  if (!isset($goto) || ($goto !== FALSE)) { 
+    // If $do_goto is set, call drupal_goto and do the redirect & exit.        
+    if ($do_goto) {
+      if (isset($goto)) {
+        if (is_array($goto)) {
+          call_user_func_array('drupal_goto', $goto);
+        }
+        else {
+          drupal_goto($goto);
+        }
       }
-      else {
-        drupal_goto($goto);
+      drupal_goto($_GET['q']);
+    }
+    else { // If $do_goto is false, just calculate and return the next url.
+      if (isset($goto)) {
+        if (is_array($goto)) {
+          return call_user_func_array('drupal_get_goto_url', $goto);
+        }
+        else {
+          return drupal_get_goto_url($goto);
+        }
       }
+      return drupal_get_goto_url($_GET['q']);
     }
-    drupal_goto($_GET['q']);
-  }
+  }  
 }
 
 /**
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.266
diff -u -p -r1.266 menu.inc
--- includes/menu.inc	19 Mar 2008 07:38:29 -0000	1.266
+++ includes/menu.inc	20 Mar 2008 00:58:43 -0000
@@ -1167,6 +1167,7 @@ function menu_get_active_help() {
       // Add "more help" link on admin pages if the module provides a
       // standalone help page.
       if ($arg[0] == "admin" && module_exists('help') && module_invoke($name, 'help', 'admin/help#'. $arg[2], $empty_arg) && $help) {
+        drupal_add_popups();
         $output .= theme("more_help_link", url('admin/help/'. $arg[2]));
       }
     }
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.417
diff -u -p -r1.417 theme.inc
--- includes/theme.inc	20 Feb 2008 13:39:29 -0000	1.417
+++ includes/theme.inc	20 Mar 2008 00:58:44 -0000
@@ -1449,7 +1449,7 @@ function theme_item_list($items = array(
  * Returns code that emits the 'more help'-link.
  */
 function theme_more_help_link($url) {
-  return '<div class="more-help-link">'. t('[<a href="@link">more help...</a>]', array('@link' => check_url($url))) .'</div>';
+  return '<div class="more-help-link">'. t('[<a class="popup more-help" href="@link">more help...</a>]', array('@link' => check_url($url))) .'</div>';
 }
 
 /**
Index: misc/tableheader.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/tableheader.js,v
retrieving revision 1.16
diff -u -p -r1.16 tableheader.js
--- misc/tableheader.js	30 Jan 2008 10:17:39 -0000	1.16
+++ misc/tableheader.js	20 Mar 2008 00:58:44 -0000
@@ -12,6 +12,11 @@ Drupal.behaviors.tableHeader = function 
     return;
   }
 
+  // If there are no sticky tables in this context, just return.
+  if (!$('table.sticky-enabled', context).size()) {
+    return;
+  }
+
   // Keep track of all cloned table headers.
   var headers = [];
 
@@ -37,6 +42,7 @@ Drupal.behaviors.tableHeader = function 
 
   // Track positioning and visibility.
   function tracker(e) {
+      console.log("tracking");
     // Save positioning data.
     var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
     if (e.viewHeight != viewHeight) {
@@ -74,6 +80,7 @@ Drupal.behaviors.tableHeader = function 
 
   // Track scrolling.
   Drupal.tableHeaderOnScroll = function() {
+    console.log("scrolling: " + headers);
     $(headers).each(function () {
       tracker(this);
     });
Index: modules/block/block.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v
retrieving revision 1.14
diff -u -p -r1.14 block.admin.inc
--- modules/block/block.admin.inc	22 Dec 2007 23:24:24 -0000	1.14
+++ modules/block/block.admin.inc	20 Mar 2008 00:58:44 -0000
@@ -30,6 +30,7 @@ function block_admin_display_form(&$form
 
   // Add CSS
   drupal_add_css(drupal_get_path('module', 'block') .'/block.css', 'module', 'all', FALSE);
+  drupal_add_popups();
 
   // If non-default theme configuration has been selected, set the custom theme.
   $custom_theme = isset($theme) ? $theme : variable_get('theme_default', 'garland');
@@ -76,7 +77,7 @@ function block_admin_display_form(&$form
     }
     $form[$key]['configure'] = array('#value' => l(t('configure'), 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta']));
     if ($block['module'] == 'block') {
-      $form[$key]['delete'] = array('#value' => l(t('delete'), 'admin/build/block/delete/'. $block['delta']));
+      $form[$key]['delete'] = array('#value' => l(t('delete'), 'admin/build/block/delete/'. $block['delta'], array('attributes'=>array('class'=>'popup-form'))));
     }
   }
 
Index: modules/filter/filter.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v
retrieving revision 1.10
diff -u -p -r1.10 filter.admin.inc
--- modules/filter/filter.admin.inc	19 Feb 2008 14:07:21 -0000	1.10
+++ modules/filter/filter.admin.inc	20 Mar 2008 00:58:45 -0000
@@ -159,7 +159,8 @@ function filter_admin_format_form(&$form
 
     // Composition tips (guidelines)
     $tips = _filter_tips($format->format, FALSE);
-    $extra = '<p>'. l(t('More information about formatting options'), 'filter/tips') .'</p>';
+    drupal_add_popups();
+    $extra = '<p>'. l(t('More information about formatting options'), 'filter/tips', array('attributes'=>array('class'=>'popup'))) .'</p>';
     $tiplist = theme('filter_tips', $tips, FALSE, $extra);
     if (!$tiplist) {
       $tiplist = '<p>'. t('No guidelines available.') .'</p>';
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.207
diff -u -p -r1.207 filter.module
--- modules/filter/filter.module	13 Mar 2008 21:26:08 -0000	1.207
+++ modules/filter/filter.module	20 Mar 2008 00:58:46 -0000
@@ -477,6 +477,7 @@ function filter_form($value = FILTER_FOR
   $value = filter_resolve_format($value);
   $formats = filter_formats();
 
+  drupal_add_popups();
   $extra = theme('filter_tips_more_info');
 
   if (count($formats) > 1) {
@@ -581,7 +582,7 @@ function _filter_tips($format, $long = F
  * @ingroup themeable
  */
 function theme_filter_tips_more_info() {
-  return '<p>'. l(t('More information about formatting options'), 'filter/tips') .'</p>';
+  return '<p>'. l(t('More information about formatting options'), 'filter/tips', array('attributes'=>array('class'=>'popup'))) .'</p>';
 }
 
 /**
Index: modules/help/help.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/help/help.admin.inc,v
retrieving revision 1.5
diff -u -p -r1.5 help.admin.inc
--- modules/help/help.admin.inc	25 Nov 2007 11:11:17 -0000	1.5
+++ modules/help/help.admin.inc	20 Mar 2008 00:58:46 -0000
@@ -23,7 +23,7 @@ function help_page($name) {
   $output = '';
   if (module_hook($name, 'help')) {
     $module = drupal_parse_info_file(drupal_get_path('module', $name) .'/'. $name .'.info');
-    drupal_set_title($module['name']);
+    drupal_set_title(t('Help: '). $module['name']);
 
     $temp = module_invoke($name, 'help', "admin/help#$name", drupal_help_arg());
     if (empty($temp)) {
Index: modules/menu/menu.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v
retrieving revision 1.29
diff -u -p -r1.29 menu.admin.inc
--- modules/menu/menu.admin.inc	23 Feb 2008 08:13:09 -0000	1.29
+++ modules/menu/menu.admin.inc	20 Mar 2008 00:58:46 -0000
@@ -61,6 +61,7 @@ function menu_overview_form(&$form_state
  */
 function _menu_overview_tree_form($tree) {
   static $form = array('#tree' => TRUE);
+  drupal_add_popups();
   foreach ($tree as $data) {
     $title = '';
     $item = $data['link'];
@@ -97,11 +98,11 @@ function _menu_overview_tree_form($tree)
       $operations['edit'] = l(t('edit'), 'admin/build/menu/item/'. $item['mlid'] .'/edit');
       // Only items created by the menu module can be deleted.
       if ($item['module'] == 'menu' || $item['updated'] == 1) {
-        $operations['delete'] = l(t('delete'), 'admin/build/menu/item/'. $item['mlid'] .'/delete');
+        $operations['delete'] = l(t('delete'), 'admin/build/menu/item/'. $item['mlid'] .'/delete', array('attributes'=>array('class'=>'popup-form')));
       }
       // Set the reset column.
       elseif ($item['module'] == 'system' && $item['customized']) {
-        $operations['reset'] = l(t('reset'), 'admin/build/menu/item/'. $item['mlid'] .'/reset');
+        $operations['reset'] = l(t('reset'), 'admin/build/menu/item/'. $item['mlid'] .'/reset', array('attributes'=>array('class'=>'popup-form')));
       }
 
       $form[$mlid]['operations'] = array();
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.50
diff -u -p -r1.50 content_types.inc
--- modules/node/content_types.inc	27 Jan 2008 18:03:05 -0000	1.50
+++ modules/node/content_types.inc	20 Mar 2008 00:58:46 -0000
@@ -10,6 +10,7 @@
  * Displays the content type admin overview page.
  */
 function node_overview_types() {
+  drupal_add_popups();
   $types = node_get_types();
   $names = node_get_types('names');
   $header = array(t('Name'), t('Type'), t('Description'), array('data' => t('Operations'), 'colspan' => '2'));
@@ -29,7 +30,7 @@ function node_overview_types() {
 
       // Set the delete column.
       if ($type->custom) {
-        $row[] = array('data' => l(t('delete'), 'admin/content/node-type/'. $type_url_str .'/delete'));
+        $row[] = array('data' => l(t('delete'), 'admin/content/node-type/'. $type_url_str .'/delete', array('attributes'=>array('class'=>'popup-form'))));
       }
       else {
         $row[] = array('data' => '');
Index: modules/path/path.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/path/path.admin.inc,v
retrieving revision 1.7
diff -u -p -r1.7 path.admin.inc
--- modules/path/path.admin.inc	8 Jan 2008 10:35:42 -0000	1.7
+++ modules/path/path.admin.inc	20 Mar 2008 00:58:46 -0000
@@ -41,7 +41,12 @@ function path_admin_overview($keys = NUL
   $rows = array();
   $destination = drupal_get_destination();
   while ($data = db_fetch_object($result)) {
-    $row = array(check_plain($data->dst), check_plain($data->src), l(t('edit'), "admin/build/path/edit/$data->pid", array('query' => $destination)), l(t('delete'), "admin/build/path/delete/$data->pid", array('query' => $destination)));
+    $row = array(
+      check_plain($data->dst), 
+      check_plain($data->src), 
+      l(t('edit'), "admin/build/path/edit/$data->pid", array('query' => $destination)), 
+      l(t('delete'), "admin/build/path/delete/$data->pid", array('query' => $destination, 'attributes'=>array('class'=>'popup-form')))
+    );
     if ($multilanguage) {
       $row[4] = $row[3];
       $row[3] = $row[2];
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.65
diff -u -p -r1.65 system.admin.inc
--- modules/system/system.admin.inc	13 Mar 2008 21:26:09 -0000	1.65
+++ modules/system/system.admin.inc	20 Mar 2008 00:58:48 -0000
@@ -116,6 +116,31 @@ function system_admin_by_module() {
 }
 
 /**
+ * Todo
+ *
+ * @return unknown
+ */
+function system_popup_settings() {
+  drupal_set_title("Popups Settings");
+  $form = array();
+
+  $form['popuppage_title_selector'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Title Selector'),
+    '#default_value' => variable_get('popuppage_title_selector', 'div.left-corner > h2:eq(0)'),
+    '#description' => t("jQuery selector to define the page's title on your Admin theme."),
+  );
+  $form['popuppage_content_selector'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Content Selector'),
+    '#default_value' => variable_get('popuppage_content_selector', 'div.left-corner > div.clear-block:last'),
+    '#description' => t('jQuery selector to define the page\'s content area on your Admin theme.'),
+  );  
+   
+  return system_settings_form($form);
+}
+
+/**
  * Menu callback; displays a module's settings page.
  */
 function system_settings_overview() {
Index: modules/system/system.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.css,v
retrieving revision 1.48
diff -u -p -r1.48 system.css
--- modules/system/system.css	9 Jan 2008 09:56:39 -0000	1.48
+++ modules/system/system.css	20 Mar 2008 00:58:48 -0000
@@ -542,3 +542,80 @@ span.password-confirm {
 span.password-confirm span {
   font-weight: normal;
 }
+
+/*
+** Popups Dialog box styles
+*/
+
+#popups-overlay {
+  position: absolute;
+/*  width: 100%;
+  height: 100%; */
+  background: black;
+  z-index: 9;  
+  top: 0;
+}
+#popups-loading {
+  z-index: 10;  
+  opacity: 0.75;
+  position: relative;
+}  
+#popups-loading div{
+  position: absolute;  
+}
+#popups {
+  border: 2px solid #EDF5FA;
+  background: white;
+  position: absolute;
+  opacity: 1.0;
+  z-index: 10;  
+  color: black;
+  padding: 0.5em;
+  width: 600px;
+  overflow: auto;
+}
+#popups-title {
+  /*background: #222;
+    color: white;
+  */
+  border-bottom: 1px solid #b4d7f0;
+  background-color: #d4e7f3;
+  color: #455067;
+  font-weight: bold;
+  padding: 0.25em;
+  margin-bottom: 0.25em;
+}
+#popups-title div.title {
+  float:left;
+}
+#popups-title #popups-close {
+  float:right;
+  line-height: 0pt;
+  margin-top: 2px; /* Trying for vertical centering */
+}
+#popups-title #popups-close a {
+    color: red;  
+}
+#popups-title div.clear {
+  clear: both;
+}
+#popups input {
+  margin: 0.1em;
+}
+#popups input[type="text"]:focus, #popups input[type="password"]:focus, #popups textarea:focus {
+	background-color: #FFA;
+	outline: thin solid grey;
+}
+#popups div.messages {
+  background: transparent;
+  border: none;
+  padding: 0;
+  margin: 0;
+}
+
+a.popups-processed:after {
+  content: "[\2020]";
+  vertical-align: super;
+  font-size: smaller; 
+}
+
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.593
diff -u -p -r1.593 system.module
--- modules/system/system.module	11 Mar 2008 08:13:14 -0000	1.593
+++ modules/system/system.module	20 Mar 2008 00:58:49 -0000
@@ -149,6 +149,11 @@ function system_theme() {
       'arguments' => array('image_path' => NULL),
     ),
     'system_compact_link' => array(),
+    'popup_template' => array(
+      'template' => 'popup-template',
+    ),
+    'popup_save_dialog' => array(),
+    
   ));
 }
 
@@ -515,6 +520,20 @@ function system_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'system.admin.inc',
   );
+  
+  // Popups:
+  $items['admin/settings/popuppage'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_popup_settings'),
+    'title' => 'AJAX Popups',
+    'description' => 'Configure the AJAX Popup behavior.',
+    'file' => 'system.admin.inc',
+  );
+  $items['popuppage/save_dialog'] = array(
+    'page callback' => 'theme',
+    'page arguments' => array('popup_save_dialog'),
+    'access callback' => TRUE,
+  );
   return $items;
 }
 
@@ -1887,6 +1906,77 @@ function system_check_http_request() {
 }
 
 /**
+ * Implements hook_renderers.
+ * Provide default system renderers.
+ */
+function system_renderers() {
+  return array(
+    'xhtml/plain' => 'system_render_default',
+    'json/popup' => 'system_render_json_popup'
+  );
+}
+
+/**
+ * Defualt Drupal renderer.
+ * Use the theme system to render to xhtml, for consumption by browsers.
+ *
+ * @return 
+ *   Themed content.
+ */
+function system_render_default() { 
+  $args = func_get_args();
+  return call_user_func_array('theme', $args);
+}
+
+/**
+ * Render the page as JSON, for consumption by AJAX calls.
+ * Optimized for AJAX popups.
+ *
+ * @return 
+ *   JSON object with metadata and themed page content.
+ */
+function system_render_json_popup() {
+  $args = func_get_args();
+  $hook = array_shift($args);
+  switch ($hook) {
+    case 'page': // render('page', $content);
+      return drupal_json(array(
+        'status' => 'ok',
+        'title' => drupal_get_title(),
+        'messages' => theme('status_messages'),
+        'path' => $_GET['q'],
+        'content' => $args[0],
+      ));
+    default: 
+      return drupal_json(array(
+        'status' => 'error',
+        'messages' => "No way to render '$hook' in mode 'json/popup'",
+      ));
+  }
+}
+
+/**
+ * Implements hook_after_process_form
+ */
+function system_after_process_form($request_mode, $form, $form_state) {
+  switch ($request_mode) {
+    case 'XMLHttpRequest':
+      // Request comes from jQuery AJAX call. 
+      // Return status, next page url and form state as JSON.
+      $url = drupal_redirect_form($form, $form_state['redirect'], FALSE);
+      print drupal_json(array(
+        'status' => 'redirect',
+        'path' => $url,
+        'form_state' => $form_state,
+      ));
+      exit;      
+    case 'standard':
+      // Default Drupal behavior, redirect to the next page.
+      drupal_redirect_form($form, $form_state['redirect']);
+  }
+}
+
+/**
  * Format the Powered by Drupal text.
  *
  * @ingroup themeable
Index: modules/user/user.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v
retrieving revision 1.19
diff -u -p -r1.19 user.admin.inc
--- modules/user/user.admin.inc	20 Feb 2008 13:46:43 -0000	1.19
+++ modules/user/user.admin.inc	20 Mar 2008 00:58:50 -0000
@@ -901,9 +901,16 @@ function user_admin_access() {
   $header = array(array('data' => t('Access type'), 'field' => 'status'), array('data' => t('Rule type'), 'field' => 'type'), array('data' => t('Mask'), 'field' => 'mask'), array('data' => t('Operations'), 'colspan' => 2));
   $result = db_query("SELECT aid, type, status, mask FROM {access}". tablesort_sql($header));
   $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host'));
+  drupal_add_popups();
   $rows = array();
   while ($rule = db_fetch_object($result)) {
-    $rows[] = array($rule->status ? t('allow') : t('deny'), $access_types[$rule->type], $rule->mask, l(t('edit'), 'admin/user/rules/edit/'. $rule->aid), l(t('delete'), 'admin/user/rules/delete/'. $rule->aid));
+    $rows[] = array(
+      $rule->status ? t('allow') : t('deny'), 
+      $access_types[$rule->type], 
+      $rule->mask, 
+      l(t('edit'), 'admin/user/rules/edit/'. $rule->aid), 
+      l(t('delete'), 'admin/user/rules/delete/'. $rule->aid, array('attributes'=>array('class'=>'popup-form')))
+    );
   }
   if (empty($rows)) {
     $rows[] = array(array('data' => '<em>'. t('There are currently no access rules.') .'</em>', 'colspan' => 5));
