Index: includes/batch.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/batch.inc,v
retrieving revision 1.42
diff -u -r1.42 batch.inc
--- includes/batch.inc	15 Oct 2009 16:18:44 -0000	1.42
+++ includes/batch.inc	17 Oct 2009 17:14:30 -0000
@@ -109,11 +109,20 @@
   $current_set = _batch_current_set();
   drupal_set_title($current_set['title'], PASS_THROUGH);
 
+  // Add ?id=x to the batch URL.
+  $url_options = $batch['url_options'];
+  if (isset($url_options['query'])) {
+    $url_options['query']['id'] = $batch['id'];
+  }
+  else {
+    $url_options['query'] = array('id' => $batch['id']);
+  }
+
   $js_setting = array(
     'batch' => array(
       'errorMessage' => $current_set['error_message'] . '<br />' . $batch['error_message'],
       'initMessage' => $current_set['init_message'],
-      'uri' => url($batch['url'], array('query' => array('id' => $batch['id']))),
+      'uri' => url($batch['url'], $url_options),
     ),
   );
   drupal_add_js($js_setting, 'setting');
@@ -189,7 +198,17 @@
     ob_end_clean();
   }
 
-  $url = url($batch['url'], array('query' => array('id' => $batch['id'], 'op' => $new_op)));
+  // Add ?id=x&op=y to the batch URL.
+  $url_options = $batch['url_options'];
+  if (isset($url_options['query'])) {
+    $url_options['query']['id'] = $batch['id'];
+    $url_options['query']['op'] = $new_op;
+  }
+  else {
+    $url_options['query'] = array('id' => $batch['id'], 'op' => $new_op);
+  }
+  
+  $url = url($batch['url'], $batch['url_options']);
   drupal_add_html_head('<meta http-equiv="Refresh" content="0; URL=' . $url . '">');
 
   return theme('progress_bar', array('percent' => $percentage, 'message' => $message));
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.386
diff -u -r1.386 form.inc
--- includes/form.inc	16 Oct 2009 19:20:34 -0000	1.386
+++ includes/form.inc	17 Oct 2009 17:15:15 -0000
@@ -3050,7 +3050,7 @@
     $process_info = array(
       'current_set' => 0,
       'progressive' => TRUE,
-      'url' => $url,
+      'url_options' => array(),
       'source_page' => $_GET['q'],
       'redirect' => $redirect,
       'theme' => $GLOBALS['theme_key'],
Index: misc/drupal.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/drupal.js,v
retrieving revision 1.58
diff -u -r1.58 drupal.js
--- misc/drupal.js	31 Aug 2009 05:51:07 -0000	1.58
+++ misc/drupal.js	17 Oct 2009 17:17:19 -0000
@@ -344,4 +344,11 @@
   }
 };
 
+ /**
+  * Check if the given variable is an object.
+  */
+ Drupal.isObject = function(something) {
+   return (something !== null && typeof something === 'object');
+ };
+
 })(jQuery);
Index: misc/tableheader.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/tableheader.js,v
retrieving revision 1.27
diff -u -r1.27 tableheader.js
--- misc/tableheader.js	20 Sep 2009 19:14:40 -0000	1.27
+++ misc/tableheader.js	17 Oct 2009 17:19:25 -0000
@@ -18,8 +18,9 @@
     var headers = [];
 
     $('table.sticky-enabled thead', context).once('tableheader', function () {
-      // Clone thead so it inherits original jQuery properties.
-      var headerClone = $(this).clone(true).insertBefore(this.parentNode).wrap('<table class="sticky-header"></table>').parent().css({
+      // Clone the table header so it inherits original jQuery properties. Hide
+      // the table to avoid a flash of the header clone upon page load.
+      var headerClone = $(this).clone(true).hide().insertBefore(this.parentNode).wrap('<table class="sticky-header"></table>').parent().css({
         position: 'fixed',
         top: '0px'
       });
@@ -32,6 +33,9 @@
       headerClone.table = table;
       // Finish initializing header positioning.
       tracker(headerClone);
+      // We hid the header to avoid it showing up erroneously on page load;
+      // we need to unhide it now so that it will show up when expected.
+      $(headerClone).children('thead').show();
 
       $(table).addClass('sticky-table');
     });
Index: modules/dashboard/dashboard.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.css,v
retrieving revision 1.2
diff -u -r1.2 dashboard.css
--- modules/dashboard/dashboard.css	18 Oct 2009 11:20:26 -0000	1.2
+++ modules/dashboard/dashboard.css	18 Oct 2009 13:38:34 -0000
@@ -64,9 +64,9 @@
   border: 0;
 }
 
-#dashboard .canvas-content input {
-  float: right;
-  margin: 0 0 0 10px;
+#dashboard .canvas-content a.button {
+  color: #5a5a5a;
+  text-decoration: none;
 }
 
 #dashboard .region {
Index: modules/dashboard/dashboard.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.js,v
retrieving revision 1.2
diff -u -r1.2 dashboard.js
--- modules/dashboard/dashboard.js	18 Oct 2009 11:20:26 -0000	1.2
+++ modules/dashboard/dashboard.js	18 Oct 2009 13:40:03 -0000
@@ -65,7 +65,7 @@
    * Helper for enterCustomizeMode; sets up drag-and-drop and close button.
    */
   setupDrawer: function () {
-    $('div.customize .canvas-content').prepend('<input type="button" class="form-submit" value="' + Drupal.t('Done') + '"></input>');
+    $('div.customize .canvas-content').prepend('<a class="button" href="">' + Drupal.t('Done') + '</a>');
     $('div.customize .canvas-content input').click(Drupal.behaviors.dashboard.exitCustomizeMode);
 
     // Initialize drag-and-drop.
Index: modules/locale/locale.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v
retrieving revision 1.48
diff -u -r1.48 locale.test
--- modules/locale/locale.test	17 Oct 2009 05:50:28 -0000	1.48
+++ modules/locale/locale.test	17 Oct 2009 17:22:02 -0000
@@ -237,7 +237,7 @@
     $this->clickLink(t('edit'));
     // We save the lid from the path.
     $matches = array();
-    preg_match('!admin/config/regional/translate/edit/(\d)+!', $this->getUrl(), $matches);
+    preg_match('!admin/config/regional/translate/edit/(\d+)!', $this->getUrl(), $matches);
     $lid = $matches[1];
     // No t() here, it's surely not translated yet.
     $this->assertText($name, t('name found on edit screen.'));
Index: modules/toolbar/toolbar.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.css,v
retrieving revision 1.6
diff -u -r1.6 toolbar.css
--- modules/toolbar/toolbar.css	18 Oct 2009 12:06:06 -0000	1.6
+++ modules/toolbar/toolbar.css	18 Oct 2009 13:42:33 -0000
@@ -36,7 +36,7 @@
   left: 0;
   right: 0;
   top: 0;
-  z-index: 100;
+  z-index: 600;
 }
 
 div#toolbar .collapsed {
Index: modules/toolbar/toolbar.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.js,v
retrieving revision 1.7
diff -u -r1.7 toolbar.js
--- modules/toolbar/toolbar.js	17 Oct 2009 00:51:53 -0000	1.7
+++ modules/toolbar/toolbar.js	17 Oct 2009 18:24:56 -0000
@@ -15,6 +15,16 @@
       Drupal.admin.toolbar.toggle();
       return false;
     });
+
+    // Set the most recently clicked item as active.
+    $('#toolbar a').once().click(function() {
+      $('#toolbar a').each(function() {
+        $(this).removeClass('active');
+      });
+      if ($(this).parents('div.toolbar-shortcuts').length) {
+        $(this).addClass('active');
+      }
+    });
   }
 };
 
Index: modules/toolbar/toolbar.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.module,v
retrieving revision 1.14
diff -u -r1.14 toolbar.module
--- modules/toolbar/toolbar.module	17 Oct 2009 00:51:53 -0000	1.14
+++ modules/toolbar/toolbar.module	17 Oct 2009 18:29:39 -0000
@@ -36,13 +36,30 @@
  * Add admin toolbar to the page_top region automatically.
  */
 function toolbar_page_build(&$page) {
-  if (user_access('access toolbar')) {
+  if (user_access('access toolbar') && toolbar_enabled()) {
     $page['page_top']['toolbar'] = toolbar_build();
     $page['page_top']['toolbar']['toolbar_drawer'] = isset($page['toolbar_drawer']) ? $page['toolbar_drawer'] : array();
   }
 }
 
 /**
+ * Enable or disable the toolbar, or find out the current status of the toolbar.
+ *
+ * @param $enabled
+ *   If given, will change the display mode of the toolbar to the given
+ *   boolean.
+ * @return
+ *   The current status of the toolbar, TRUE for enabled, FALSE for disabled.
+ */
+function toolbar_enabled($enabled = NULL) {
+  $setting = &drupal_static(__FUNCTION__, TRUE);
+  if (isset($enabled)) {
+    $setting = $enabled;
+  }
+  return $setting;
+}
+
+/**
  * Implement hook_preprocess_html().
  *
  * Add some page classes, so global page theming can adjust to the toolbar.
@@ -53,6 +70,10 @@
   }
 }
 
+function template_preprocess_toolbar(&$variables) {
+  $variables['classes_array'][] = 'clearfix';
+}
+
 /**
  * Build the admin menu as a structured array ready for drupal_render().
  */
@@ -180,3 +201,12 @@
   }
   return in_array($path, $active_paths);
 }
+
+/**
+ * Implement hook_overlay_child_initialize().
+ */
+function toolbar_overlay_child_initialize() {
+  // Disable admin toolbar, which is something child windows don't need and
+  // shouldn't have.
+  toolbar_enabled(FALSE);
+}
Index: modules/toolbar/toolbar.tpl.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.tpl.php,v
retrieving revision 1.5
diff -u -r1.5 toolbar.tpl.php
--- modules/toolbar/toolbar.tpl.php	17 Oct 2009 00:51:53 -0000	1.5
+++ modules/toolbar/toolbar.tpl.php	17 Oct 2009 18:31:07 -0000
@@ -6,15 +6,17 @@
  * Default template for admin toolbar.
  *
  * Available variables:
+ * - $classes: Classes for the toolbar div element. Can be
+ *   manipulated in preprocess functions via $variables['classes_array'].
  * - $toolbar['toolbar_user']: User account / logout links.
  * - $toolbar['toolbar_menu']: Top level management menu links.
  * - $toolbar['toolbar_drawer']: A place for extended toolbar content.
  *
  * @see template_preprocess()
- * @see template_preprocess_admin_toolbar()
+ * @see template_preprocess_toolbar()
  */
 ?>
-<div id="toolbar" class="clearfix">
+<div id="toolbar" class="<?php print $classes; ?>">
   <div class="toolbar-menu clearfix">
     <?php if ($toolbar['toolbar_drawer']):?>
       <span class="toggle toggle-active"><?php print t('Open'); ?></span>
Index: profiles/default/default.info
===================================================================
RCS file: /cvs/drupal/drupal/profiles/default/default.info,v
retrieving revision 1.6
diff -u -r1.6 default.info
--- profiles/default/default.info	17 Oct 2009 01:15:40 -0000	1.6
+++ profiles/default/default.info	17 Oct 2009 18:31:28 -0000
@@ -16,6 +16,7 @@
 dependencies[] = search
 dependencies[] = shortcut
 dependencies[] = toolbar
+dependencies[] = overlay
 dependencies[] = field_ui
 dependencies[] = file
 files[] = default.profile
Index: themes/garland/style.css
===================================================================
RCS file: /cvs/drupal/drupal/themes/garland/style.css,v
retrieving revision 1.66
diff -u -r1.66 style.css
--- themes/garland/style.css	17 Oct 2009 05:50:29 -0000	1.66
+++ themes/garland/style.css	17 Oct 2009 18:32:24 -0000
@@ -508,6 +508,15 @@
   font-size: 1.5em;
 }
 
+/* Don't display any header elements when within the overlay, and adjust the page height accordingly. */
+body.overlay #header * {
+  display: none;
+}
+
+body.overlay {
+  margin-top: -80px;
+}
+
 #wrapper #container #header h1 a:hover {
   text-decoration: none;
 }
Index: themes/seven/style.css
===================================================================
RCS file: /cvs/drupal/drupal/themes/seven/style.css,v
retrieving revision 1.20
diff -u -r1.20 style.css
--- themes/seven/style.css	18 Oct 2009 04:35:30 -0000	1.20
+++ themes/seven/style.css	18 Oct 2009 13:42:00 -0000
@@ -55,7 +55,7 @@
  */
 #branding {
   overflow: hidden;
-  padding: 20px 40px 0 40px;
+  padding: 20px 20px 0 20px;
   position: relative;
   background-color: #e0e0d8;
 }
@@ -115,7 +115,7 @@
  */
 div.messages {
   padding: 9px;
-  margin: 1em 0;
+  margin: 0.5em 0 0;
   color: #036;
   background: #bdf;
   border: 1px solid #ace;
@@ -158,9 +158,8 @@
 /**
  * Console.
  */
-#page .console {
-  border-top: 1px solid #ccc;
-  padding: 9px 0 10px;
+#console {
+  margin: 9px 0 10px;
 }
 
 /**
@@ -549,7 +548,7 @@
 }
 
 /* Buttons */
-input.form-submit {
+input.form-submit, a.button {
   cursor: pointer;
   padding: 4px 17px;
   color: #5a5a5a;
@@ -566,6 +565,11 @@
   font-size: 1.1em;
 }
 
+a.button:link, a.button:visited, a.button:hover, a.button:active {
+  text-decoration: none;
+  color: #5a5a5a;
+}
+
 div.node-form input#edit-submit,
 div.node-form input#edit-submit-1 {
   border: 1px solid #8eB7cd;
@@ -618,9 +622,14 @@
 
 ul.action-links {
   margin: 1em 0;
+  padding: 0 20px 0 20px;
   overflow: hidden;
 }
 
+#block-system-main ul.action-links {
+  padding: 0;
+}
+
 ul.action-links li {
   float: left;
   margin: 0 1em 0 0;
@@ -716,24 +725,40 @@
 }
 
 /* Overlay theming */
-body.overlay {
-  background: #fff;
+.overlay #branding {
+  background-color: #fff;
+  padding-top: 15px;
 }
 
-body.overlay #branding,
-body.overlay #page-title,
-body.overlay #page #left,
-body.overlay #page #footer {
+.overlay .primary,
+.overlay #branding h1.page-title,
+.overlay #page #left,
+.overlay #page #footer {
   display: none;
 }
 
-body.overlay #page {
+.overlay #page {
   margin: 0;
-  padding: 0;
 }
 
-body.overlay #block-system-main {
-  padding: 20px;
+.overlay #branding div.breadcrumb {
+  float: left;
+  position: relative;
+  z-index: 10;
+}
+
+.overlay ul.secondary {
+  background: transparent none;
+  margin: -2.4em 0 0;
+  padding: 3px 10px;
+}
+
+.overlay #content {
+  padding: 0 20px;
+}
+
+.overlay #block-system-main {
+  padding: 0;
 }
 
 /* Shortcut theming */
Index: modules/overlay/overlay-child.js
===================================================================
--- modules/overlay/overlay-child.js
+++ modules/overlay/overlay-child.js
@@ -0,0 +1,138 @@
+// $Id: child.js,v 1.1.4.3 2009/06/17 15:16:26 markuspetrux Exp $
+
+(function ($) {
+
+/**
+ * Overlay object for child windows.
+ */
+Drupal.overlayChild = Drupal.overlayChild || { processed: false, behaviors: {} };
+
+/**
+ * Attach the child dialog behavior to new content.
+ */
+Drupal.behaviors.overlayChild = {
+  attach: function (context, settings) {
+    var self = Drupal.overlayChild;
+    var settings = settings.overlayChild || {};
+
+    // Make sure this behavior is not processed more than once.
+    if (self.processed) {
+      return;
+    }
+    self.processed = true;
+
+    // If we cannot reach the parent window, then we have nothing else to do
+    // here.
+    if (!Drupal.isObject(parent.Drupal) || !Drupal.isObject(parent.Drupal.overlay)) {
+      return;
+    }
+
+    // If a form has been submitted successfully, then the server side script
+    // may have decided to tell us the parent window to close the popup dialog.
+    if (settings.closeOverlay) {
+      parent.Drupal.overlay.bindChild(window, true);
+      // Close the child window from a separate thread because the current
+      // one is busy processing Drupal behaviors.
+      setTimeout(function () {
+        // We need to store the parent variable locally because it will
+        // disappear as soon as we close the iframe.
+        var p = parent;
+        p.Drupal.overlay.close(settings.args, settings.statusMessages);
+        if (typeof settings.redirect == 'string') {
+          p.Drupal.overlay.redirect(settings.redirect);
+        }
+      }, 1);
+      return;
+    }
+
+    // Ok, now we can tell the parent window we're ready.
+    parent.Drupal.overlay.bindChild(window);
+
+    // Install onBeforeUnload callback, if module is present.
+    if (Drupal.isObject(Drupal.onBeforeUnload) && !Drupal.onBeforeUnload.callbackExists('overlayChild')) {
+      Drupal.onBeforeUnload.addCallback('overlayChild', function () {
+        // Tell the parent window we're unloading.
+        parent.Drupal.overlay.unbindChild(window);
+      });
+    }
+
+    // Attach child related behaviors to the iframe document.
+    self.attachBehaviors(context, settings);
+  }
+};
+
+/**
+ * Attach child related behaviors to the iframe document.
+ */
+Drupal.overlayChild.attachBehaviors = function (context, settings) {
+  $.each(this.behaviors, function () {
+    this(context, settings);
+  });
+};
+
+/**
+ * Scroll to the top of the page.
+ *
+ * This makes the overlay visible to users even if it is not as tall as the
+ * previously shown overlay was.
+ */
+Drupal.overlayChild.behaviors.scrollToTop = function (context, settings) {
+  window.scrollTo(0, 0);
+};
+
+/**
+ * Modify links and forms depending on their relation to the overlay.
+ *
+ * By default, forms and links are assumed to keep the flow in the overlay.
+ * Thus their action and href attributes respectively get a ?render=overlay
+ * suffix. Non-administrative links should however close the overlay and
+ * redirect the parent page to the given link. This would include links in a
+ * content listing, where administration options are mixed with links to the
+ * actual content to be shown on the site out of the overlay.
+ *
+ * @see Drupal.overlay.isAdminLink()
+ */
+Drupal.overlayChild.behaviors.parseLinks = function (context, settings) {
+  $('a:not(.overlay-exclude)', context).once('overlay').each(function () {
+    // Non-admin links should close the overlay and open in the main window.
+    if (!parent.Drupal.overlay.isAdminLink(this.href)) {
+      $(this).click(function () {
+        // We need to store the parent variable locally because it will
+        // disappear as soon as we close the iframe.
+        var parentWindow = parent;
+        if (parentWindow.Drupal.overlay.close(false)) {
+          parentWindow.Drupal.overlay.redirect($(this).attr('href'));
+        }
+        return false;
+      });
+      return;
+    }
+    else {
+      var href = $(this).attr('href');
+      if (href.indexOf('http') > 0 || href.indexOf('https') > 0) {
+        $(this).attr('target', '_new');
+      }
+      else {
+        $(this).click(function () {
+          var linkURL = parent.Drupal.overlay.addOverlayParam($(this).attr('href'));
+          parent.Drupal.overlay.load(linkURL);
+          return false;
+        });
+      }
+    }
+  });
+  $('form:not(.overlay-processed)', context).addClass('overlay-processed').each(function () {
+    // Obtain the action attribute of the form.
+    var action = $(this).attr('action');
+    if (action.indexOf('http') != 0 && action.indexOf('https') != 0) {
+      // Keep internal forms in the overlay.
+      action += (action.indexOf('?') > -1 ? '&' : '?') + 'render=overlay';
+      $(this).attr('action', action);
+    }
+    else {
+      $(this).attr('target', '_new');
+    }
+  });
+};
+
+})(jQuery);
Index: modules/overlay/overlay-parent.css
===================================================================
--- modules/overlay/overlay-parent.css
+++ modules/overlay/overlay-parent.css
@@ -0,0 +1,122 @@
+/* $Id$ */
+
+/**
+ * ui-dialog overlay.
+ */
+.ui-widget-overlay {
+  background-color: #000;
+  opacity: 0.7;
+  filter: alpha(opacity=80);
+  background-image: none;
+}
+
+/**
+ * jQuery UI Dialog classes.
+ */
+.overlay {
+  padding-right: 26px;
+}
+
+.overlay.ui-widget-content, .overlay .ui-widget-header {
+  background: none;
+  border: none;
+}
+
+.overlay .ui-dialog-titlebar {
+  white-space: nowrap;
+  padding: 0 20px;
+}
+
+.overlay .ui-dialog-title {
+  font-family: Verdana,sans-serif;
+  margin: 0;
+  padding: 0.3em 0;
+  color: #fff;
+  font-size: 20px;
+}
+.overlay .ui-dialog-title:active,
+.overlay .ui-dialog-title:focus {
+  outline: 0;
+}
+.overlay .ui-dialog-titlebar-close,
+.overlay .ui-dialog-titlebar-close:hover {
+  display: block;
+  right: -25px;
+  top: 100%;
+  margin: 0;
+  border: none;
+  padding: 0;
+  width: 26px;
+  height: 36px;
+  background: transparent url(images/close.png) no-repeat;
+  -moz-border-radius-topleft: 0;
+}
+.overlay .ui-dialog-titlebar-close span {
+  display: none;
+}
+.overlay .ui-dialog-content {
+  color: #292929;
+  background-color: #f8f8f8;
+}
+
+/**
+ * Overlay content and shadows.
+ */
+.overlay #overlay-container {
+  margin: 0;
+  padding: 0;
+  overflow: visible;
+  background: #fff url(images/loading.gif) no-repeat 50% 50%;
+  -webkit-box-shadow: 8px 8px 8px rgba(0,0,0,.5);
+  -moz-box-shadow: 8px 8px 8px rgba(0,0,0,.5);
+  box-shadow: 8px 8px 8px rgba(0,0,0,.5);
+}
+.overlay #overlay-element {
+  overflow: hidden;
+}
+
+/**
+ * Tabs on the overlay.
+ */
+.overlay .ui-dialog-titlebar ul {
+  position: absolute;
+  right: 20px;
+  bottom: 0;
+  margin: 0;
+  line-height: 27px;
+  text-transform: uppercase;
+}
+.overlay .ui-dialog-titlebar ul li {
+  display: inline-block;
+  list-style: none;
+  margin: 0 0 0 -3px;
+  padding: 0;
+}
+.overlay .ui-dialog-titlebar ul li a,
+.overlay .ui-dialog-titlebar ul li a:active,
+.overlay .ui-dialog-titlebar ul li a:visited,
+.overlay .ui-dialog-titlebar ul li a:hover {
+  background-color: #a6a7a2;
+  -moz-border-radius: 8px 8px 0 0;
+  -webkit-border-top-left-radius: 8px;
+  -webkit-border-top-right-radius: 8px;
+  border-radius: 8px 8px 0 0;
+  color: #000;
+  font-weight: bold;
+  padding: 5px 14px;
+  text-decoration: none;
+  font-size: 11px;
+}
+.overlay .ui-dialog-titlebar ul li.active a,
+.overlay .ui-dialog-titlebar ul li.active a.active,
+.overlay .ui-dialog-titlebar ul li.active a:active,
+.overlay .ui-dialog-titlebar ul li.active a:visited {
+  background-color: #fff;
+  padding-bottom: 7px;
+}
+.overlay .ui-dialog-titlebar ul li a:hover {
+  color: #fff;
+}
+.overlay .ui-dialog-titlebar ul li.active a:hover {
+  color: #000;
+}
Index: modules/overlay/overlay-parent.js
===================================================================
--- modules/overlay/overlay-parent.js
+++ modules/overlay/overlay-parent.js
@@ -0,0 +1,747 @@
+// $Id: parent.js,v 1.1.4.4 2009/06/19 15:32:57 markuspetrux Exp $
+
+(function ($) {
+
+/**
+ * Open or modify overlay based on clicks of links marked with .to-overlay.
+ */
+Drupal.behaviors.overlayParent = {
+  attach: function (context, settings) {
+    // Attach on all admin links without the 'overlay-exclude' class.
+    $('a:not(.overlay-exclude)').filter(function () {
+      return Drupal.overlay.isAdminLink(this.href);
+    })
+    // Respond to their click event.
+    .once('overlay').click(function () {
+
+      // Append render variable, so the server side can choose the right
+      // rendering and add child modal frame code to the page if needed.
+      var linkURL = Drupal.overlay.addOverlayParam($(this).attr('href'));
+
+      // If the modal frame is already open, replace the loaded document with
+      // this new one. Keeps browser history.
+      if (Drupal.overlay.isOpen) {
+        Drupal.overlay.load(linkURL);
+        return false;
+      }
+
+      // There is not an overlay opened yet, we should open a new one.
+      var overlayOptions = {
+        url: linkURL,
+
+        // Remove active class from all header buttons.
+        onOverlayClose: function () {
+          $('a.to-overlay').each(function () {
+            $(this).removeClass('active');
+          });
+        },
+        draggable: false
+      };
+      Drupal.overlay.open(overlayOptions);
+
+      // Prevent default action of the link click event.
+      return false;
+    });
+
+    // Automatically open an overlay if defined in Drupal.settings.overlay.autoOpen.
+    if (Drupal.settings.overlay.autoOpen) {
+      var linkURL = Drupal.overlay.addOverlayParam(Drupal.settings.overlay.autoOpen);
+
+      // Unset autoOpen to prevent looping.
+      delete Drupal.settings.overlay.autoOpen;
+
+      // If the modal frame is already open, replace the loaded document with
+      // this new one. Keeps browser history.
+      if (Drupal.overlay.isOpen) {
+        Drupal.overlay.load(linkURL);
+        return false;
+      }
+
+      // There is not an overlay opened yet, we should open a new one.
+      var overlayOptions = {
+        url: linkURL,
+
+        // Remove active class from all header buttons.
+        onOverlayClose: function () {
+          $('a.to-overlay').each(function () {
+            $(this).removeClass('active');
+          });
+        },
+        draggable: false
+      };
+      Drupal.overlay.open(overlayOptions);
+    }
+  }
+};
+
+/**
+ * Overlay object for parent windows.
+ */
+Drupal.overlay = Drupal.overlay || {
+  options: {},
+  iframe: { $container: null, $element: null },
+  isOpen: false
+};
+
+/**
+ * Open an overlay.
+ *
+ * Ensure that only one overlay is opened ever. Use Drupal.overlay.load() if
+ * the overlay is already open but a new page needs to be opened.
+ *
+ * @param options
+ *   Properties of the overlay to open:
+ *   - url: the URL of the page to open in the overlay.
+ *   - width: width of the overlay in pixels.
+ *   - height: height of the overlay in pixels.
+ *   - autoFit: boolean indicating whether the overlay should be resized to
+ *     fit the contents of the document loaded.
+ *   - onOverlayOpen: callback to invoke when the overlay is opened.
+ *   - onOverlayCanClose: callback to allow external scripts decide if the
+ *     overlay can be closed.
+ *   - onOverlayClose: callback to invoke when the overlay is closed.
+ *   - customDialogOptions: an object with custom jQuery UI Dialog options.
+ *
+ * @return
+ *   If the overlay was opened true, otherwise false.
+ */
+Drupal.overlay.open = function (options) {
+  var self = this;
+
+  // Just one overlay is allowed.
+  if (self.isOpen || $('#overlay-container').size()) {
+    return false;
+  }
+
+  var defaultOptions = {
+    url: options.url,
+    width: options.width,
+    height: options.height,
+    autoFit: (options.autoFit == undefined || options.autoFit),
+    onOverlayOpen: options.onOverlayOpen,
+    onOverlayCanClose: options.onOverlayCanClose,
+    onOverlayClose: options.onOverlayClose,
+    customDialogOptions: options.customDialogOptions || {}
+  }
+
+  self.options = $.extend(defaultOptions, options);
+
+  // Create the dialog and related DOM elements.
+  self.create();
+
+  // Open the dialog offscreen where we can set its size, etc.
+  self.iframe.$container.dialog('option', { position: ['-999em', '-999em'] }).dialog('open');
+
+  return true;
+};
+
+/**
+ * Create the underlying markup and behaviors for the overlay.
+ *
+ * Reuses jQuery UI's dialog component to construct the overlay markup and
+ * behaviors, sanitizing the options previously set in self.options.
+ */
+Drupal.overlay.create = function () {
+  var self = this;
+
+  // Note: We use scrolling="yes" for IE as a workaround to yet another IE bug
+  // where the horizontal scrollbar is always rendered no matter how wide the
+  // iframe element is defined.
+  self.iframe.$element = $('<iframe id="overlay-element" frameborder="0" name="overlay-element"'+ ($.browser.msie ? ' scrolling="yes"' : '') +'/>');
+  self.iframe.$container = $('<div id="overlay-container"/>').append(self.iframe.$element);
+
+  $('body').append(self.iframe.$container);
+
+  // Open callback for jQuery UI Dialog.
+  var dialogOpen = function () {
+    // Unbind the keypress handler installed by ui.dialog itself.
+    // IE does not fire keypress events for some non-alphanumeric keys
+    // such as the tab character. http://www.quirksmode.org/js/keys.html
+    // Also, this is not necessary here because we need to deal with an
+    // iframe element that contains a separate window.
+    // We'll try to provide our own behavior from bindChild() method.
+    $('.overlay').unbind('keypress.ui-dialog');
+
+    // Adjust close button features.
+    $('.overlay .ui-dialog-titlebar-close:not(.overlay-processed)').addClass('overlay-processed')
+      .attr('href', '#')
+      .attr('title', Drupal.t('Close'))
+      .unbind('click')
+      .bind('click', function () { try { self.close(); } catch(e) {}; return false; });
+
+    // Replace the title span element with an h1 element for accessibility.
+    $('.overlay .ui-dialog-title').replaceWith('<h1 id="ui-dialog-title-overlay-container" class="ui-dialog-title" tabindex="-1" unselectable="on">' + $('.overlay .ui-dialog-title').html() + '</h1>');
+
+    // Compute initial dialog size.
+    var dialogSize = self.sanitizeSize({width: self.options.width, height: self.options.height});
+
+    // Compute frame size and dialog position based on dialog size.
+    var frameSize = $.extend({}, dialogSize);
+    frameSize.height -= $('.overlay .ui-dialog-titlebar').outerHeight(true);
+    var dialogPosition = self.computePosition($('.overlay'), dialogSize);
+
+    // Adjust size of the iframe element and container.
+    $('.overlay').width(dialogSize.width).height(dialogSize.height);
+    self.iframe.$container.width(frameSize.width).height(frameSize.height);
+    self.iframe.$element.width(frameSize.width).height(frameSize.height);
+
+    // Update the dialog size so that UI internals are aware of the change.
+    self.iframe.$container.dialog('option', { width: dialogSize.width, height: dialogSize.height });
+
+    // Hide the dialog, position it on the viewport and then fade it in with
+    // the frame hidden until the child document is loaded.
+    self.iframe.$element.hide();
+    $('.overlay').hide().css({top: dialogPosition.top, left: dialogPosition.left});
+    $('.overlay').fadeIn('fast', function () {
+      // Load the document on hidden iframe (see bindChild method).
+      self.load(self.options.url);
+    });
+
+    if ($.isFunction(self.options.onOverlayOpen)) {
+      self.options.onOverlayOpen(self);
+    }
+
+    self.isOpen = true;
+  };
+
+  // Before close callback for jQuery UI Dialog.
+  var dialogBeforeClose = function () {
+    if (self.beforeCloseEnabled) {
+      return true;
+    }
+    if (!self.beforeCloseIsBusy) {
+      self.beforeCloseIsBusy = true;
+      setTimeout(function () { self.close(); }, 1);
+    }
+    return false;
+  };
+
+  // Close callback for jQuery UI Dialog.
+  var dialogClose = function () {
+    $(document).unbind('keydown.overlay-event');
+    $('.overlay .ui-dialog-titlebar-close').unbind('keydown.overlay-event');
+    try {
+      self.iframe.$element.remove();
+      self.iframe.$container.dialog('destroy').remove();
+    } catch(e) {};
+    delete self.iframe.documentSize;
+    delete self.iframe.Drupal;
+    delete self.iframe.$element;
+    delete self.iframe.$container;
+    if (self.beforeCloseEnabled) {
+      delete self.beforeCloseEnabled;
+    }
+    if (self.beforeCloseIsBusy) {
+      delete self.beforeCloseIsBusy;
+    }
+    self.isOpen = false;
+  };
+
+  // Default jQuery UI Dialog options.
+  var dialogOptions = {
+    modal: true,
+    autoOpen: false,
+    closeOnEscape: true,
+    resizable: false,
+    title: Drupal.t('Loading...'),
+    dialogClass: 'overlay',
+    zIndex: 500,
+    open: dialogOpen,
+    beforeclose: dialogBeforeClose,
+    close: dialogClose
+  };
+
+  // Allow external script override default jQuery UI Dialog options.
+  $.extend(dialogOptions, self.options.customDialogOptions);
+
+  // Create the jQuery UI Dialog.
+  self.iframe.$container.dialog(dialogOptions);
+};
+
+/**
+ * Load the given URL into the overlay iframe.
+ *
+ * Use this method to change the URL being loaded in the overlay if it is
+ * already open.
+ */
+Drupal.overlay.load = function (url) {
+  var self = this;
+  var iframe = self.iframe.$element.get(0);
+  // Get the document object of the iframe window.
+  // @see http://xkr.us/articles/dom/iframe-document/
+  var doc = (iframe.contentWindow || iframe.contentDocument);
+  if (doc.document) {
+    doc = doc.document;
+  }
+  doc.location.replace(url);
+};
+
+/**
+ * Check if the dialog can be closed.
+ */
+Drupal.overlay.canClose = function () {
+  var self = this;
+  if (!self.isOpen) {
+    return false;
+  }
+  // Allow external scripts decide if the overlay can be closed.
+  if ($.isFunction(self.options.onOverlayCanClose)) {
+    if (!self.options.onOverlayCanClose(self)) {
+      return false;
+    }
+  }
+  return true;
+};
+
+/**
+ * Close the overlay and remove markup related to it from the document.
+ */
+Drupal.overlay.close = function (args, statusMessages) {
+  var self = this;
+
+  // Offer the user a chance to change their mind if there is a form on the
+  // page, which may have unsaved work on it.
+  var iframeElement = self.iframe.$element.get(0);
+  var iframeDocument = (iframeElement.contentWindow || iframeElement.contentDocument);
+  if (iframeDocument.document) {
+    iframeDocument = iframeDocument.document;
+  }
+
+  // Check if the dialog can be closed.
+  if (!self.canClose()) {
+    delete self.beforeCloseIsBusy;
+    return false;
+  }
+
+  // Hide and destroy the dialog.
+  function closeDialog() {
+    // Prevent double execution when close is requested more than once.
+    if (!Drupal.isObject(self.iframe.$container)) {
+      return;
+    }
+    self.beforeCloseEnabled = true;
+    self.iframe.$container.dialog('close');
+    if ($.isFunction(self.options.onOverlayClose)) {
+      self.options.onOverlayClose(args, statusMessages);
+    }
+  }
+  if (!Drupal.isObject(self.iframe.$element) || !self.iframe.$element.size() || !self.iframe.$element.is(':visible')) {
+    closeDialog();
+  }
+  else {
+    self.iframe.$container.animate({height: 'hide'}, { duration: 'fast', 'queue': false });
+    $('.overlay').animate({opacity: 'hide'}, closeDialog);
+  }
+  return true;
+};
+
+/**
+ * Redirect the overlay parent window to the given URL.
+ *
+ * @param link
+ *   Can be an absolute URL or a relative link to the domain root.
+ */
+Drupal.overlay.redirect = function (link) {
+  if (link.indexOf('http') != 0 && link.indexOf('https') != 0) {
+    var absolute = location.href.match(/https?:\/\/[^\/]*/)[0];
+    link = absolute + link;
+  }
+  location.href = link;
+  return true;
+}
+
+/**
+ * Bind the child window.
+ *
+ * Add tabs on the overlay, keyboard actions and display animation.
+ */
+Drupal.overlay.bindChild = function (iFrameWindow, isClosing) {
+  var self = this;
+  var $iFrameWindow = iFrameWindow.jQuery;
+  var $iFrameDocument = $iFrameWindow(iFrameWindow.document);
+  var autoResizing = false;
+  self.iframe.Drupal = iFrameWindow.Drupal;
+
+  // We are done if the child window is closing.
+  if (isClosing) {
+    return;
+  }
+
+  // Update the dialog title with the child window title.
+  $('.overlay .ui-dialog-title').html($iFrameDocument.attr('title')).focus();
+  // Add a title attribute to the iframe for accessibility.
+  self.iframe.$element.attr('title', Drupal.t('@title dialog', { '@title': $iFrameDocument.attr('title') }));
+
+  // Remove any existing tabs.
+  $('.overlay .ui-dialog-titlebar ul').remove();
+
+  // Setting tabIndex makes the div focusable.
+  $iFrameDocument.attr('tabindex', -1);
+
+  $('.ui-dialog-titlebar-close-bg').animate({opacity: 0.9999}, 'fast');
+
+  // Perform animation to show the iframe element.
+  self.iframe.$element.fadeIn('fast', function () {
+    // @todo: Watch for experience in the way we compute the size of the
+    // iframed document. There are many ways to do it, and none of them
+    // seem to be perfect. Note though, that the size of the iframe itself
+    // may affect the size of the child document, especially on fluid layouts.
+    self.iframe.documentSize = { width: $iFrameDocument.width(), height: $iFrameWindow('body').height() + 25 };
+
+    // Adjust overlay to fit the iframe content?
+    if (self.options.autoFit) {
+      self.resize(self.iframe.documentSize);
+    }
+
+    // Try to enhance keyboard based navigation of the overlay.
+    // Logic inspired by the open() method in ui.dialog.js, and
+    // http://wiki.codetalks.org/wiki/index.php/Docs/Keyboard_navigable_JS_widgets
+
+    // Get a reference to the close button.
+    var $closeButton = $('.overlay .ui-dialog-titlebar-close');
+
+    // Search tabbable elements on the iframed document to speed up related
+    // keyboard events.
+    // @todo: Do we need to provide a method to update these references when
+    // AJAX requests update the DOM on the child document?
+    var $iFrameTabbables = $iFrameWindow(':tabbable:not(form)');
+    var $firstTabbable = $iFrameTabbables.filter(':first');
+    var $lastTabbable = $iFrameTabbables.filter(':last');
+
+    // Unbind keyboard event handlers that may have been enabled previously.
+    $(document).unbind('keydown.overlay-event');
+    $closeButton.unbind('keydown.overlay-event');
+
+    // When the focus leaves the close button, then we want to jump to the
+    // first/last inner tabbable element of the child window.
+    $closeButton.bind('keydown.overlay-event', function (event) {
+      if (event.keyCode && event.keyCode == $.ui.keyCode.TAB) {
+        var $target = (event.shiftKey ? $lastTabbable : $firstTabbable);
+        if (!$target.size()) {
+          $target = $iFrameDocument;
+        }
+        setTimeout(function () { $target.focus(); }, 10);
+        return false;
+      }
+    });
+
+    // When the focus leaves the child window, then drive the focus to the
+    // close button of the dialog.
+    $iFrameDocument.bind('keydown.overlay-event', function (event) {
+      if (event.keyCode) {
+        if (event.keyCode == $.ui.keyCode.TAB) {
+          if (event.shiftKey && event.target == $firstTabbable.get(0)) {
+            setTimeout(function () { $closeButton.focus(); }, 10);
+            return false;
+          }
+          else if (!event.shiftKey && event.target == $lastTabbable.get(0)) {
+            setTimeout(function () { $closeButton.focus(); }, 10);
+            return false;
+          }
+        }
+        else if (event.keyCode == $.ui.keyCode.ESCAPE) {
+          setTimeout(function () { self.close(); }, 10);
+          return false;
+        }
+      }
+    });
+
+    var autoResize = function () {
+      if (typeof self.iframe.$element == 'undefined') {
+        autoResizing = false;
+        $(window).unbind('resize', windowResize);
+        return;
+      }
+      var iframeElement = self.iframe.$element.get(0);
+      var iframeDocument = (iframeElement.contentWindow || iframeElement.contentDocument);
+      if (iframeDocument.document) {
+        iframeDocument = iframeDocument.document;
+      }
+      // Use outerHeight() because otherwise the calculation will be off
+      // because of padding and/or border added by the theme.
+      var height = $(iframeDocument).find('body').outerHeight() + 25;
+      self.iframe.$element.css('height', height);
+      self.iframe.$container.css('height', height);
+      self.iframe.$container.parent().css('height', height + 45);
+      // Don't allow the shadow background to shrink so it's not enough to hide
+      // the whole page. Take the existing document height (with overlay) and
+      // the body height itself for our base calculation.
+      var docHeight = Math.min($(document).find('body').outerHeight(), $(document).height());
+      $('.ui-widget-overlay').height(Math.max(docHeight, $(window).height(), height + 145));
+      setTimeout(autoResize, 150);
+    };
+
+    var windowResize = function () {
+      var width = $(window).width()
+      var change = lastWidth - width;
+      var currentWidth = self.iframe.$element.width();
+      var newWidth = lastFrameWidth - change;
+      lastWidth = width;
+      lastFrameWidth = newWidth;
+
+      if (newWidth >= 300) {
+        self.iframe.$element.css('width', newWidth);
+        self.iframe.$container.css('width', newWidth);
+        self.iframe.$container.parent().css('width', newWidth);
+        widthBelowMin = false;
+      }
+      else {
+        widthBelowMin = true;
+      }
+    }
+
+    if (!autoResizing) {
+      autoResizing = true;
+      autoResize();
+      var lastFrameWidth = self.iframe.$element.width();
+      var lastWidth = $(window).width();
+      $(window).resize(windowResize);
+    }
+
+    // When the focus is captured by the parent document, then try
+    // to drive the focus back to the first tabbable element, or the
+    // close button of the dialog (default).
+    $(document).bind('keydown.overlay-event', function (event) {
+      if (event.keyCode && event.keyCode == $.ui.keyCode.TAB) {
+        setTimeout(function () {
+          if (!$iFrameWindow(':tabbable:not(form):first').focus().size()) {
+            $closeButton.focus();
+          }
+        }, 10);
+        return false;
+      }
+    });
+
+    // If there are tabs in the page, move them to the titlebar.
+    var tabs = $iFrameDocument.find('ul.primary').get(0);
+
+    // This breaks in anything less than IE 7. Prevent it from running.
+    if (typeof tabs != 'undefined' && (!$.browser.msie || parseInt($.browser.version) >= 7)) {
+      $('.ui-dialog-titlebar').append($(tabs).remove().get(0));
+      if ($(tabs).is('.primary')) {
+        $(tabs).find('a').addClass('to-overlay').removeClass('overlay-processed');
+        Drupal.attachBehaviors($(tabs));
+      }
+      // Remove any classes from the list element to avoid theme styles
+      // clashing with our styling.
+      $(tabs).removeAttr('class');
+    }
+  });
+};
+
+/**
+ * Unbind the child window.
+ *
+ * Remove keyboard event handlers, reset title and hide the iframe.
+ */
+Drupal.overlay.unbindChild = function (iFrameWindow) {
+  var self = this;
+
+  // Prevent memory leaks by explicitly unbinding keyboard event handler
+  // on the child document.
+  iFrameWindow.jQuery(iFrameWindow.document).unbind('keydown.overlay-event');
+
+  // Change the overlay title.
+  $('.overlay .ui-dialog-title').html(Drupal.t('Please, wait...'));
+
+  // Hide the iframe element.
+  self.iframe.$element.fadeOut('fast');
+};
+
+/**
+ * Check if the given link is an admin link and should be opened in the overlay.
+ *
+ * Modules and themes can override the default behavior by adding an array of
+ * links and/or regular expressions to
+ * Drupal.settings.overlay.admin[modulename], for links that should be displayed
+ * inside the overlay, or Drupal.settings.overlay.nonAdmin[modulename], for
+ * links that should be displayed as normal in the parent window.
+ */
+Drupal.overlay.isAdminLink = function (url) {
+  // Create a native Link object, so we can use its object methods.
+  var link = $(url.link(url)).get(0);
+  var path = link.pathname.replace(new RegExp(Drupal.settings.basePath), '');
+  // Test the link against module/theme-provided non-admin links.
+  for (module in Drupal.settings.overlay.links.nonAdmin) {
+    var list = Drupal.settings.overlay.links.nonAdmin[module];
+    if ((typeof module == 'string') && list.length) {
+      var i;
+      for (i = 0; i < list.length; i++) {
+        var item = list[i];
+        switch (typeof item) {
+          case 'string':
+            if (path.indexOf(item) === 0) {
+              return false;
+            }
+          default:
+            if (path.match(item)) {
+              return false;
+            }
+        }
+      }
+    }
+  }
+  if (path.indexOf('admin') === 0) {
+    return true;
+  }
+  if (path.indexOf('node/add') === 0) {
+    return true;
+  }
+  var re = new RegExp("node/[0-9]+/(edit|delete)");
+  if (path.match(re)) {
+    return true;
+  }
+  // Test the link against module/theme-provided admin links.
+  for (module in Drupal.settings.overlay.links.admin) {
+    list = Drupal.settings.overlay.links.admin[module];
+    if ((typeof module == 'string') && list.length) {
+      i;
+      for (i = 0; i < list.length; i++) {
+        item = list[i];
+        switch (typeof item) {
+          case 'string':
+            if (path.indexOf(item) === 0) {
+              return true;
+            }
+          default:
+            if (path.match(item)) {
+              return true;
+            }
+        }
+      }
+    }
+  }
+  return false;
+}
+
+/**
+ * Sanitize dialog size.
+ *
+ * Do not let the overlay go over the 0.78x of the width of the screen and set
+ * minimal height. The height is not limited due to how we rely on the parent
+ * window to provide scrolling instead of scrolling in scrolling with the
+ * overlay.
+ *
+ * @param size
+ *   Contains 'width' and 'height' items as numbers.
+ * @return
+ *   The same structure with sanitized number values.
+ */
+Drupal.overlay.sanitizeSize = function (size) {
+  var width, height;
+  var $window = $(window);
+
+  // Use 300px as the minimum width but at most expand to 78% of the window.
+  // Ensures that users see that there is an actual website in the background.
+  var minWidth = 300, maxWidth = parseInt($window.width() * .78);
+  if (typeof size.width != 'number') {
+    width = maxWidth;
+  }
+  // Set to at least minWidth but at most maxWidth. 
+  else if (size.width < minWidth || size.width > maxWidth) {
+    width = Math.min(maxWidth, Math.max(minWidth, size.width));
+  }
+  else {
+    width = size.width;
+  }
+  
+  // Use 100px as the minimum height. Expand to 92% of the window if height
+  // was invalid, to ensure that we have a reasonable chance to show content.
+  var minHeight = 100, maxHeight = parseInt($window.height() * .92);
+  if (typeof size.height != 'number') {
+    height = maxHeight;
+  }
+  else if (size.height < minHeight) {
+    // Do not consider maxHeight as the actual maximum height, since we rely on
+    // the parent window scroll bar to scroll the window. Only set up to be at
+    // least the minimal height.
+    height = Math.max(minHeight, size.height);
+  }
+  else {
+    height = size.height;
+  }
+  return { width: width, height: height };
+};
+
+/**
+ * Compute position to center horizontally and on viewport top vertically.
+ */
+Drupal.overlay.computePosition = function ($element, elementSize) {
+  var $window = $(window);
+  // Consider any region that should be visible above the overlay (such as
+  // an admin toolbar).
+  var $toolbar = $('.overlay-displace-top');
+  var toolbarHeight = 0;
+  $toolbar.each(function () {
+    toolbarHeight += $toolbar.height();
+  });
+  var position = {
+    left: Math.max(0, parseInt(($window.width() - elementSize.width) / 2)),
+    top: toolbarHeight + 20
+  };
+
+  // Reset the scroll to the top of the window so that the overlay is visible again.
+  window.scrollTo(0, 0);
+  return position;
+};
+
+/**
+ * Resize overlay to the given size.
+ * 
+ * @param size
+ *   Contains 'width' and 'height' items as numbers.
+ */
+Drupal.overlay.resize = function (size) {
+  var self = this;
+
+  // Compute frame and dialog size based on requested document size.
+  var titleBarHeight = $('.overlay .ui-dialog-titlebar').outerHeight(true);
+  var frameSize = self.sanitizeSize(size); 
+  var dialogSize = $.extend({}, frameSize);
+  dialogSize.height += titleBarHeight + 15;
+
+  // Compute position on viewport.
+  var dialogPosition = self.computePosition($('.overlay'), dialogSize);
+
+  var animationOptions = $.extend(dialogSize, dialogPosition);
+
+  // Perform the resize animation.
+  $('.overlay').animate(animationOptions, 'fast', function () {
+    // Proceed only if the dialog still exists.
+    if (Drupal.isObject(self.iframe.$element) && Drupal.isObject(self.iframe.$container)) {
+      // Resize the iframe element and container.
+      $('.overlay').width(dialogSize.width).height(dialogSize.height);
+      self.iframe.$container.width(frameSize.width).height(frameSize.height);
+      self.iframe.$element.width(frameSize.width).height(frameSize.height);
+
+      // Update the dialog size so that UI internals are aware of the change.
+      self.iframe.$container.dialog('option', { width: dialogSize.width, height: dialogSize.height });
+
+      // Keep the dim background grow or shrink with the dialog.
+      $('.ui-widget-overlay').height($(document).height());
+      
+      // Animate body opacity, so we fade in the page as it loads in. 
+      $(self.iframe.$element.get(0)).contents().find('body.overlay').animate({opacity: 0.9999}, 'slow');
+    }
+  });
+};
+
+/**
+ * Add overlay rendering GET parameter to the given href.
+ */
+Drupal.overlay.addOverlayParam = function (href) {
+  // Do not process links with an empty href, or that only have the fragment or
+  // which are external links.
+  if (href.length > 0 && href.charAt(0) != '#' && href.indexOf('http') != 0 && href.indexOf('https') != 0) {
+    var fragmentIndex = href.indexOf('#');
+    var fragment = '';
+    if (fragmentIndex != -1) {
+      fragment = href.substr(fragmentIndex);
+      href = href.substr(0, fragmentIndex);
+    }
+    href += (href.indexOf('?') > -1 ? '&' : '?') + 'render=overlay' + fragment;
+  }
+  return href;
+};
+
+})(jQuery);
Index: modules/overlay/overlay.api.php
===================================================================
--- modules/overlay/overlay.api.php
+++ modules/overlay/overlay.api.php
@@ -0,0 +1,52 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Hooks provided by Overlay module.
+ */
+
+/**
+ * @addtogroup hooks
+ * @{
+ */
+
+/**
+ * Allow modules to act when an overlay parent window is initialized.
+ *
+ * The parent window is initialized when a page is displayed in which the
+ * overlay might be required to be displayed, so modules can act here if they
+ * need to take action to accomodate the possibility of the overlay appearing
+ * within a Drupal page.
+ *
+ * @return
+ *   None.
+ */
+function hook_overlay_parent_initialize() {
+  // Add our custom JavaScript.
+  drupal_add_js(drupal_get_path('module', 'hook') . '/hook-overlay.js');
+}
+
+/**
+ * Allow modules to act when an overlay child window is initialized.
+ *
+ * The child window is initialized when a page is displayed from within the
+ * overlay, so modules can act here if they need to take action to work from
+ * within the confines of the overlay.
+ *
+ * @return
+ *   None.
+ */
+function hook_overlay_child_initialize() {
+  // Use a different theme for content administration pages.
+  if (arg(0) == 'admin' && arg(1) == 'content') {
+    if ($theme = variable_get('content_administration_pages_theme', FALSE)) {
+      global $custom_theme;
+      $custom_theme = $theme;
+    }
+  }
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
Index: modules/overlay/overlay.info
===================================================================
--- modules/overlay/overlay.info
+++ modules/overlay/overlay.info
@@ -0,0 +1,7 @@
+; $Id$
+name = Overlay
+description = Displays the Drupal administration interface in an overlay.
+package = Core
+version = VERSION
+core = 7.x
+files[] = overlay.module
Index: modules/overlay/overlay.install
===================================================================
--- modules/overlay/overlay.install
+++ modules/overlay/overlay.install
@@ -0,0 +1,12 @@
+<?php
+// $Id$
+
+/**
+ * Implement hook_enable().
+ *
+ * After enabling, remember that Overlay was just enabled in a session variable.
+ * Now we can react to the enabling of the module at the next page load in overlay_init().
+ */
+function overlay_enable() {
+  $_SESSION['overlay_just_enabled'] = 'step1';
+}
Index: modules/overlay/overlay.module
===================================================================
--- modules/overlay/overlay.module
+++ modules/overlay/overlay.module
@@ -0,0 +1,386 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Displays the Drupal administration interface in an overlay.
+ */
+
+/**
+ * Implement hook_init().
+ *
+ * Determine whether the current page request is destined to appear in the
+ * parent window or in the overlay window, and format the page accordingly.
+ *
+ * @see overlay_mode()
+ */
+function overlay_init() {
+  // @todo: custom_theme does not exist anymore.
+  global $custom_theme;
+  // Only act if the user has access to administration pages. Other modules can
+  // also enable the overlay directly for other uses of the JavaScript.
+  if (user_access('access administration pages')) {
+    // Initialize JavaScript settings to specify admin and non-admin links.
+    drupal_add_js(array('overlay' => array('links' => array('admin' => NULL, 'nonAdmin' => NULL))), 'setting');
+    if (isset($_GET['render']) && $_GET['render'] == 'overlay') {
+      $admin_theme = variable_get('admin_theme', 0);
+      if ($custom_theme != $admin_theme) {
+        // If system module did not switch the theme yet (i.e. this is not an
+        // admin page, per se), we should switch the theme here.
+        $custom_theme = $admin_theme;
+        drupal_add_css(drupal_get_path('module', 'system') . '/admin.css');
+      }
+      overlay_mode('child');
+    }
+    else {
+      // Otherwise add overlay parent code and our behavior.
+      overlay_mode('parent');
+      // Special case for when overlay.module was just enabled; redirect to
+      // the homepage and reopen the modules page inside the overlay.
+      if (isset($_SESSION['overlay_just_enabled'])) {
+        if ($_SESSION['overlay_just_enabled'] == 'step1' && $_GET['q'] == 'admin/config/modules') {
+          $_SESSION['overlay_just_enabled'] = 'step2';
+          drupal_goto('<front>');
+        }
+        else if ($_SESSION['overlay_just_enabled'] == 'step2' && $_GET['q'] == variable_get('site_frontpage','node')) {
+          unset($_SESSION['overlay_just_enabled']);
+          drupal_add_js(array('overlay' => array('autoOpen' => 'admin/config/modules')), 'setting');
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Implement hook_element_info_alter().
+ */
+function overlay_element_info_alter(&$types) {
+  foreach (array('submit', 'button', 'image_button', 'form') as $type) {
+    $types[$type]['#after_build'][] = 'overlay_form_after_build';
+  }
+}
+
+/**
+ * Implement hook_library().
+ */
+function overlay_library() {
+  $module_path = drupal_get_path('module', 'overlay');
+
+  // Overlay parent.
+  $libraries['parent'] = array(
+    'title' => 'Overlay: Parent',
+    'website' => 'http://drupal.org/node/517688',
+    'version' => '1.0',
+    'js' => array(
+      $module_path . '/overlay-parent.js' => array(),
+    ),
+    'css' => array(
+      $module_path . '/overlay-parent.css' => array(),
+    ),
+    'dependencies' => array(
+      array('system', 'ui.dialog'),
+    ),
+  );
+  // Overlay child.
+  $libraries['child'] = array(
+    'title' => 'Overlay: Child',
+    'website' => 'http://drupal.org/node/517688',
+    'version' => '1.0',
+    'js' => array(
+      $module_path . '/overlay-child.js' => array(),
+    ),
+    'dependencies' => array(
+      array('system', 'ui'),
+    ),
+  );
+
+  return $libraries;
+}
+
+/**
+ * Implement hook_drupal_goto_alter().
+ *
+ * If the current page request is inside the overlay, add ?render=overlay to
+ * the new path, so that it appears correctly inside the overlay.
+ *
+ * @see overlay_mode()
+ */
+function overlay_drupal_goto_alter(&$path, &$options, &$http_response_code) {
+  if (overlay_mode() == 'child') {
+    if (isset($options['query'])) {
+      $options['query'] += array('render' => 'overlay');
+    }
+    else {
+      $options['query'] = array('render' => 'overlay');
+    }
+  }
+}
+
+/**
+ * Implement hook_batch_alter().
+ *
+ * If the current page request is inside the overlay, add ?render=overlay to
+ * the success callback URL, so that it appears correctly within the overlay.
+ *
+ * @see overlay_mode()
+ */
+function overlay_batch_alter(&$batch) {
+  if (overlay_mode() == 'child') {
+    if (isset($batch['url_options']['query'])) {
+      $batch['url_options']['query']['render'] = 'overlay';
+    }
+    else {
+      $batch['url_options']['query'] = array('render' => 'overlay');
+    }
+  }
+}
+
+/**
+ * Implement hook_block_info_alter().
+ *
+ * If the current page request is inside the overlay, don't display extraneous
+ * blocks.
+ *
+ * @see overlay_mode()
+ */
+function overlay_block_info_alter(&$blocks) {
+  // @todo: custom_theme does not exist anymore.
+  global $custom_theme;
+
+  if (!empty($custom_theme) && overlay_mode() == 'child') {
+    $themes = list_themes();
+    $theme = $themes[$custom_theme];
+    if (!empty($theme->info['overlay_regions'])) {
+      // Don't show any blocks except the main page content and the help text if
+      // we're in the overlay.
+      foreach ($blocks as $bid => $block) {
+        if (!in_array($block->region, $theme->info['overlay_regions'])) {
+          unset($blocks[$bid]);
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Implement hook_system_info_alter().
+ *
+ * Add default regions for overlay.
+ */
+function overlay_system_info_alter(&$info, $file) {
+  $info['overlay_regions'][] = 'content';
+  $info['overlay_regions'][] = 'help';
+}
+
+/**
+ * Preprocess template variables for html.tpl.php.
+ *
+ * If the current page request is inside the overlay, add appropriate classes
+ * to the <body> element, and simplify the page title.
+ *
+ * @see overlay_mode()
+ */
+function overlay_preprocess_html(&$variables) {
+  if (overlay_mode() == 'child') {
+    // Add overlay class, so themes can react to being displayed in the overlay.
+    $variables['classes_array'][] = 'overlay';
+    // Do not include site name or slogan in the overlay title.
+    $variables['head_title'] = drupal_get_title();
+  }
+}
+
+/**
+ * Preprocess template variables for page.tpl.php.
+ *
+ * Display breadcrumbs correctly inside the overlay.
+ *
+ * @see overlay_mode()
+ */
+function overlay_preprocess_page(&$variables) {
+  if (overlay_mode() == 'child') {
+    // Remove 'Home' from the breadcrumbs.
+    $overlay_breadcrumb = drupal_get_breadcrumb();
+    array_shift($overlay_breadcrumb);
+    $variables['breadcrumb'] = theme('breadcrumb', array('breadcrumb' => $overlay_breadcrumb));
+  }
+}
+
+/**
+ * Preprocess template variables for toolbar.tpl.php.
+ *
+ * Adding the 'overlay-displace-top' class to the toolbar pushes the overlay
+ * down, so it appears below the toolbar.
+ */
+function overlay_preprocess_toolbar(&$variables) {
+  $variables['classes_array'][] = "overlay-displace-top";
+}
+
+/**
+ * Form after_build callback.
+ *
+ * After all hook_form_alter() implementations have been processed, we look at
+ * the list of submit handlers and add our own at the end. The added handler
+ * determines whether or not the user is redirected done at the end of form
+ * processing, so that it's possible to close the overlay after submitting
+ * a form.
+ *
+ * @see _form_builder_handle_input_element()
+ * @see _form_builder_ie_cleanup()
+ * @see form_execute_handlers()
+ * @see form_builder()
+ * @see overlay_form_submit()
+ *
+ * @ingroup forms
+ */
+function overlay_form_after_build($form, &$form_state) {
+  if (isset($_GET['render']) && $_GET['render'] == 'overlay') {
+    // Form API may have already captured submit handlers from the submitted
+    // button before after_build callback is invoked. This may have been done
+    // by _form_builder_handle_input_element(). If so, the list of submit
+    // handlers is stored in the $form_state array, which is something we can
+    // also alter from here, luckily. Rememeber: our goal here is to set
+    // $form_state['redirect'] to FALSE if the API overlay_close_dialog() has
+    // been invoked. That's because we want to tell the parent window to close
+    // the overlay.
+    if (!empty($form_state['submit_handlers']) && !in_array('overlay_form_submit', $form_state['submit_handlers'])) {
+      $form_state['submit_handlers'][] = 'overlay_form_submit';
+    }
+    // If this element has submit handlers, then append our own.
+    if (isset($form['#submit'])) {
+      $form['#submit'][] = 'overlay_form_submit';
+    }
+  }
+  return $form;
+}
+
+/**
+ * Generic form submit handler.
+ *
+ * When we are requested to close an overlay, we don't want Form API to
+ * perform any redirection once the submitted form has been processed.
+ *
+ * When $form_state['redirect'] is set to FALSE, then Form API will simply
+ * re-render the form with the values still in its fields. And this is all
+ * we need to output the JavaScript that will tell the parent window to close
+ * the child dialog.
+ *
+ * @see overlay_mode()
+ * @ingroup forms
+ */
+function overlay_form_submit($form, &$form_state) { 
+  $settings = &drupal_static(__FUNCTION__);
+
+  // Check if we have a request to close the overlay.
+  $args = overlay_close_dialog();
+
+  // Make sure the overlay is closed when a node edit form has been saved
+  // or previewed (but not when delete has been requested) in child mode.
+  // Wait until $form_state['redirect'] has a value (which is not until the
+  // submit button handler has been called), so that we have somewhere
+  // to redirect to.
+  if ($args === FALSE && overlay_mode() == 'child' && !empty($form['#node_edit_form']) && isset($form_state['redirect']) && $form_state['clicked_button']['#value'] !== t('Delete')) {
+    $args = overlay_close_dialog(TRUE);
+  }
+
+  // Make sure the overlay is closed when the node delete form has been
+  // confirmed.
+  if ($args === FALSE && overlay_mode() == 'child' && $form['#form_id'] === 'node_delete_confirm') {
+    $args = overlay_close_dialog(TRUE);
+  }
+
+  // Close the overlay if the overlay module has been disabled
+  if (!module_exists('overlay')) {
+    $args = overlay_close_dialog(TRUE);
+  }
+
+  // Close the overlay only if specifically requested.
+  if ($args !== FALSE) {
+    if (!isset($settings)) {
+      $settings = array(
+        'overlayChild' => array(
+          'closeOverlay' => TRUE,
+          'statusMessages' => theme('status_messages'),
+          'args' => $args,
+        ),
+      );
+      // Tell the child window to perform the redirection when requested to.
+      if (!empty($form_state['redirect'])) {
+        if (is_array($form_state['redirect'])) {
+          $settings['overlayChild']['redirect'] = url($form_state['redirect'][0], $form_state['redirect'][1]);
+        }
+        else {
+          $settings['overlayChild']['redirect'] = url($form_state['redirect']);
+        }
+      }
+      drupal_add_js($settings, array('type' => 'setting'));
+    }
+    // Tell FAPI to redraw the form without redirection after all submit
+    // callbacks have been processed.
+    $form_state['redirect'] = FALSE;
+  }
+}
+
+/**
+ * Set overlay mode and add proper JavaScript and styles to the page.
+ *
+ * @param $mode
+ *   To set the mode, pass in either 'parent' or 'child'. 'parent' is used in
+ *   the context of a parent window (a regular browser window), and JavaScript
+ *   is added so that administrative links in the parent window will open in
+ *   an overlay. 'child' is used in the context of the child overlay window (the
+ *   page actually appearing within the overlay iframe) and JavaScript and CSS
+ *   are added so that Drupal behaves nicely from within the overlay.
+ *
+ *   This parameter is optional, and if omitted, the current mode will be
+ *   returned with no action taken.
+ * @return
+ *   The current mode, if any has been set, or NULL if no mode has been set.
+ * @ingroup overlay_api
+ */
+function overlay_mode($mode = NULL) {
+  global $base_path;
+  $overlay_mode = &drupal_static(__FUNCTION__);
+
+  // Make sure external resources are not included more than once. Also return
+  // current mode, if no mode was specified.
+  if (isset($overlay_mode) || !isset($mode)) {
+    return $overlay_mode;
+  }
+  $overlay_mode = $mode;
+
+  switch ($overlay_mode) {
+    case 'parent':
+      drupal_add_library('overlay', 'parent');
+
+      // Allow modules to act upon overlay events.
+      module_invoke_all('overlay_parent_initialize');
+      break;
+
+    case 'child':
+      drupal_add_library('overlay', 'child');
+
+      // Allow modules to act upon overlay events.
+      module_invoke_all('overlay_child_initialize');
+      break;
+  }
+  return $overlay_mode;
+}
+
+/**
+ * Callback to close the overlay dialog.
+ *
+ * @param $set
+ *   If set, will set the current close dialog mode to the given state.
+ *   Use FALSE to disable close dialog mode. Otherwise, the argument will
+ *   be forwarded to the onOverlayClose callback of the overlay.
+ * @return
+ *   The current overlay close dialog mode, TRUE if the overlay should close or
+ *   FALSE if it should not (default).
+ */
+function overlay_close_dialog($set = NULL) {
+  $close = &drupal_static(__FUNCTION__, FALSE);
+  if (isset($set)) {
+    $close = $set;
+  }
+  return $close;
+}