diff --git includes/form.inc includes/form.inc
index 2c273ac..a5a134d 100644
--- includes/form.inc
+++ includes/form.inc
@@ -1014,8 +1014,9 @@ function form_builder($form_id, $element, &$form_state) {
 
   // The #after_build flag allows any piece of a form to be altered
   // after normal input parsing has been completed.
-  if (isset($element['#after_build']) && !isset($element['#after_build_done'])) {
-    foreach ($element['#after_build'] as $function) {
+  if ((isset($element['#after_build']) || isset($form_state['complete form']['#after_build_recursive'])) && !isset($element['#after_build_done'])) {
+    $functions = array_merge(isset($element['#after_build']) ? $element['#after_build'] : array(), isset($form_state['complete form']['#after_build_recursive']) ? $form_state['complete form']['#after_build_recursive'] : array());
+    foreach ($functions as $function) {
       $element = $function($element, $form_state);
       $element['#after_build_done'] = TRUE;
     }
diff --git modules/overlay/overlay-child.js modules/overlay/overlay-child.js
new file mode 100644
index 0000000..7f19a83
--- /dev/null
+++ modules/overlay/overlay-child.js
@@ -0,0 +1,120 @@
+// $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: {}
+};
+
+/**
+ * Use a Drupal behavior to attach the child dialog behavior so that it will be
+ * automatically attached to new content.
+ */
+Drupal.behaviors.overlayChild = {
+  attach: function(context) {
+    Drupal.overlayChild.attachBehavior(context);
+  }
+};
+
+/**
+ * Attach child dialog behavior.
+ */
+Drupal.overlayChild.attachBehavior = function(context) {
+  var self = Drupal.overlayChild;
+  var settings = Drupal.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 todo here.
+  if (!self.isObject(parent.Drupal) || !self.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() { parent.Drupal.overlay.close(settings.args, settings.statusMessages); }, 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 (self.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 iframed document.
+  self.attachBehaviors(context);
+};
+
+/**
+ * Check if the given variable is an object.
+ */
+Drupal.overlayChild.isObject = function(something) {
+  return (something !== null && typeof something === 'object');
+};
+
+/**
+ * Attach child related behaviors to the iframed document.
+ */
+Drupal.overlayChild.attachBehaviors = function(context) {
+  $.each(this.behaviors, function() {
+    this(context);
+  });
+};
+
+/**
+ * Add target="_new" to all external URLs.
+ */
+Drupal.overlayChild.behaviors.parseLinks = function(context) {
+  $('a:not(.overlay-processed)', context).addClass('overlay-processed').each(function() {
+    // Do not process links that have the class "overlay-exclude".
+    if ($(this).hasClass('overlay-exclude')) {
+      return;
+    }
+    // Obtain the href attribute of the link.
+    var href = $(this).attr('href');
+    // Do not process links with an empty href, or that only have the fragment.
+    if (href.length <= 0 || href.charAt(0) == '#') {
+      return;
+    }
+    if (href.indexOf('http') != 0 && href.indexOf('https') != 0) {
+      // Keep internal linked pages in the overlay.
+      href += (href.indexOf('?') > -1 ? '&' : '?') + 'render=overlay';
+      $(this).attr('href', href);
+    }
+    else {
+      $(this).attr('target', '_new');
+    }
+  });
+  $('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);
diff --git modules/overlay/overlay-parent.css modules/overlay/overlay-parent.css
new file mode 100644
index 0000000..01e2972
--- /dev/null
+++ modules/overlay/overlay-parent.css
@@ -0,0 +1,179 @@
+/* $Id$ */
+
+/**
+ * jQuery UI Dialog classes.
+ */
+.overlay {
+  color: #000;
+  padding-right: 30px;
+}
+
+.overlay .ui-dialog-titlebar {
+  position: relative;
+  height: 30px;
+  white-space: nowrap;
+  z-index: 2;
+}
+
+.overlay .ui-dialog-title {
+  display: block;
+  position: absolute;
+  top: 0;
+  left: 0;
+  margin: 0.2em 0.5em;
+  padding: 0;
+  color: #fff;
+  font-size: 20px;
+}
+
+.overlay .ui-dialog-titlebar-close {
+  display: block;
+  position: absolute;
+  right: -26px;
+  top: 30px;
+  margin: 0;
+  padding: 0;
+  width: 26px;
+  height: 26px;
+}
+
+.overlay .ui-dialog-titlebar-close-bg {
+  background: transparent url(images/close.png) no-repeat;
+  width: 32px;
+  height: 36px;
+  position: absolute;
+  right: -32px;
+  top: 30px;
+  opacity: 0;
+  filter: alpha(opacity=0);
+}
+
+.overlay .ui-dialog-titlebar-close span {
+  display: none;
+}
+
+.overlay .ui-dialog-content {
+  color: #292929;
+  background-color: #f8f8f8;
+}
+
+/**
+ * ui-dialog overlay.
+ */
+.ui-widget-overlay {
+  position: absolute;
+  top: 0; left: 0;
+  width: 100%; height: 100%;
+  background-color: #000;
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+
+/**
+ * Overlay content and shadows.
+ */
+#overlay-container {
+  margin: 0;
+  padding: 0;
+  background: #fff url(images/loading.gif) no-repeat 50% 50%;
+}
+
+#overlay-container div.overlay-shadow {
+  position: absolute;
+  z-index: 1;
+  opacity: 0;
+  filter: alpha(opacity=0);
+}
+
+#overlay-container div.overlay-shadow-bottom {
+  height: 15px;
+  background: transparent url(images/ovrly-shdw-bt.png) repeat-x;
+  margin: -5px 0 0 15px;
+  position: relative;
+}
+
+#overlay-element {
+  margin: 0;
+  padding: 0;
+  border: none;
+}
+
+#overlay-container div.overlay-shadow-right {
+  top: 30px;
+  right: 15px;
+  width: 15px;
+  background: transparent url(images/ovrly-shdw-rt.png) repeat-y;
+}
+
+#overlay-container div.overlay-shadow-bottom-right {
+  bottom: -15px;
+  left: 0px;
+  width: 15px;
+  height: 15px;
+  background: transparent url(images/ovrly-shdw-bt-rt.png) no-repeat;
+}
+
+#overlay-container div.overlay-shadow-bottom-left {
+  top: 0px;
+  left: -15px;
+  width: 15px;
+  height: 15px;
+  background: transparent url(images/ovrly-shdw-bt-lt.png) no-repeat;
+}
+
+/**
+ * Tabs on the overlay.
+ */
+.ui-dialog-titlebar ul {
+  float: right;
+  border-bottom: none;
+  margin: 0 20px 0 0;
+  padding: 9px 0 0;
+  line-height: normal;
+  text-transform: uppercase;
+  font-size: 12px;
+}
+
+.ui-dialog-titlebar ul li {
+  display: inline;
+  list-style: none;
+  margin-left: 1px;
+}
+
+.ui-dialog-titlebar ul li {
+  background: transparent url(images/tab_inactive_rt.png) no-repeat top right;
+  padding: 4px 8px 7px 0;
+}
+
+.ui-dialog-titlebar ul li a,
+.ui-dialog-titlebar ul li a.active,
+.ui-dialog-titlebar ul li a:active,
+.ui-dialog-titlebar ul li a:visited {
+  background: transparent url(images/tab_inactive_lt.png) no-repeat;
+  color: #000;
+  font-weight: bold;
+  padding: 4px 15px 7px 20px;
+  text-decoration: none;
+}
+
+.ui-dialog-titlebar ul li.active {
+  background: transparent url(images/tab_active_rt.png) no-repeat top right;
+}
+
+.ui-dialog-titlebar ul li.active a,
+.ui-dialog-titlebar ul li.active a.active,
+.ui-dialog-titlebar ul li.active a:active,
+.ui-dialog-titlebar ul li.active a:visited {
+  background: transparent url(images/tab_active_lt.png) no-repeat;
+  color: #000;
+  font-weight: bold;
+  padding: 4px 15px 7px 20px;
+}
+
+.ui-dialog-titlebar ul li a:hover {
+  color: #fff;
+}
+
+.ui-dialog-titlebar ul li.active a:hover {
+  color: #000;
+}
diff --git modules/overlay/overlay-parent.js modules/overlay/overlay-parent.js
new file mode 100644
index 0000000..e47e523
--- /dev/null
+++ modules/overlay/overlay-parent.js
@@ -0,0 +1,504 @@
+// $Id: parent.js,v 1.1.4.4 2009/06/19 15:32:57 markuspetrux Exp $
+
+(function ($) {
+
+Drupal.behaviors.keepOverlay = {
+  attach: function(context) {
+
+    // Attach on the .to-overlay class.
+    $('a.to-overlay:not(.overlay-processed)').addClass('overlay-processed').click(function() {
+
+      // Remove the active class from where it was, and add the active class to
+      // this link, so the button keeps highlighting where we are. Only
+      // highlight active items in the shortcuts bar.
+      $('#toolbar a').each(function() {
+        $(this).removeClass('active');
+      });
+      if ($(this).parents('div.toolbar-shortcuts').length) {
+        $(this).addClass('active');
+      }
+
+      // 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 = $(this).attr('href');
+      linkURL += (linkURL.indexOf('?') > -1 ? '&' : '?') + 'render=overlay';
+
+      // 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 overlay opened yet, we should open a new one.
+      var toolbarHeight = $('#toolbar').height();
+      var overlayOptions = {
+        url: linkURL,
+        width: $(window).width() - 40,
+        height: $(window).height() - 40 - toolbarHeight,
+        // Remove active class from all header buttons.
+        onOverlayClose: function() { $('#toolbar a').each(function() { $(this).removeClass('active'); }); }
+      };
+      Drupal.overlay.open(overlayOptions);
+
+      // Set position and styling to let the admin toolbar work.
+      $('.overlay').css('top', toolbarHeight + 20);
+      $('#toolbar').css('z-index', 2000);
+
+      // Prevent default action of the link click event.
+      return false;
+    });
+  }
+};
+
+/**
+ * Overlay object for parent windows.
+ */
+Drupal.overlay = Drupal.overlay || {
+  options: {},
+  iframe: { $container: null, $element: null },
+  isOpen: false
+};
+
+/**
+ * Open an overlay.
+ */
+Drupal.overlay.open = function(options) {
+  var self = this;
+
+  // Just one overlay is allowed.
+  if (self.isOpen || $('#overlay-container').size()) {
+    return false;
+  }
+
+  // Build overlay frame options structure.
+  self.options = {
+    url: options.url,
+    width: options.width,
+    height: options.height,
+    autoFit: (options.autoFit == undefined || options.autoFit),
+    onOverlayClose: options.onOverlayClose
+  };
+
+  // Create the dialog and related DOM elements.
+  self.create(options);
+
+  // 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 overlay.
+ */
+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);
+  self.iframe.$element
+    .after($('<div class="overlay-shadow overlay-shadow-right" />').append('<div class="overlay-shadow overlay-shadow-bottom-right" />'))
+    .after($('<div class="overlay-shadow overlay-shadow-bottom" />').append('<div class="overlay-shadow overlay-shadow-bottom-left" />'));
+
+  $('body').append(self.iframe.$container);
+
+  self.iframe.$container.dialog({
+    modal: true,
+    autoOpen: false,
+    closeOnEscape: true,
+    resizable: false,
+    title: Drupal.t('Loading...'),
+    dialogClass: 'overlay',
+    open: 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', 'javascript:void(0)')
+        .attr('title', Drupal.t('Close'))
+        .unbind('click')
+        .bind('click', function() { try { self.close(false); } catch(e) {}; return false; })
+        .before('<div class="ui-dialog-titlebar-close-bg" />');
+
+      // 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);
+      });
+
+      self.isOpen = true;
+    },
+    beforeclose: function() {
+      if (self.beforeCloseEnabled) {
+        return true;
+      }
+      if (!self.beforeCloseIsBusy) {
+        self.beforeCloseIsBusy = true;
+        setTimeout(function() { self.close(false); }, 1);
+      }
+      return false;
+    },
+    close: 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;
+    }
+  });
+};
+
+/**
+ * Load the given URL into the dialog iframe.
+ */
+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;
+  }
+  return true;
+};
+
+/**
+ * Close the overlay.
+ */
+Drupal.overlay.close = function(args, statusMessages) {
+  var self = this;
+
+  // 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 (!self.isObject(self.iframe.$container)) {
+      return;
+    }
+    self.beforeCloseEnabled = true;
+    self.iframe.$container.dialog('close');
+    if ($.isFunction(self.options.onOverlayClose)) {
+      self.options.onOverlayClose(args, statusMessages);
+    }
+  }
+  if (!self.isObject(self.iframe.$element) || !self.iframe.$element.size() || !self.iframe.$element.is(':visible')) {
+    closeDialog();
+  }
+  else {
+    self.iframe.$element.fadeOut('fast', function() {
+      $('.overlay').animate({height: 'hide', opacity: 'hide'}, closeDialog);
+    });
+  }
+  return true;
+};
+
+/**
+ * Bind the child window.
+ */
+Drupal.overlay.bindChild = function(iFrameWindow, isClosing) {
+  var self = this;
+  var $iFrameWindow = iFrameWindow.jQuery;
+  var $iFrameDocument = $iFrameWindow(iFrameWindow.document);
+  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'));
+
+  // Remove any existing tabs.
+  $('.overlay .ui-dialog-titlebar ul').remove();
+
+  // Setting tabIndex makes the div focusable.
+  // Setting outline to 0 prevents a border on focus in Mozilla.
+  // Inspired by ui.dialog initialization code.
+  $iFrameDocument.attr('tabIndex', -1).css('outline', 0);
+
+  $('.ui-dialog-titlebar-close-bg').animate({opacity: 1}, '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, specially on fluid layouts.
+    // If you get in trouble, then I would suggest to choose a known dialog
+    // size and disable the option autoFit.
+    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');
+
+    // Set focus to the first tabbable element in the content area or the
+    // first button. If there are no tabbable elements, set focus on the
+    // close button of the dialog itself.
+    if (!$firstTabbable.focus().size()) {
+      $iFrameDocument.focus();
+    }
+
+    // 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(false); }, 10);
+          return false;
+        }
+      }
+    });
+
+    // 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;
+      }
+    });
+
+    var tabs = $iFrameDocument.find('ul.horizontal-tabs-panes, ul.primary').get(0);
+
+    // If there are tabs in the page, move them to the titlebar.
+    if (typeof tabs != 'undefined') {
+      $('.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.
+ */
+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 variable is an object.
+ */
+Drupal.overlay.isObject = function(something) {
+  return (something !== null && typeof something === 'object');
+};
+
+/**
+ * Sanitize dialog size.
+ */
+Drupal.overlay.sanitizeSize = function(size) {
+  var width, height;
+  var $window = $(window);
+  var minWidth = 300, maxWidth = parseInt($window.width() * .92);
+  if (typeof size.width != 'number') {
+    width = maxWidth;
+  }
+  else if (size.width < minWidth || size.width > maxWidth) {
+    width = Math.min(maxWidth, Math.max(minWidth, size.width));
+  }
+  else {
+    width = size.width;
+  }
+  var minHeight = 100, maxHeight = parseInt($window.height() * .92);
+  if (typeof size.height != 'number') {
+    height = maxHeight;
+  }
+  else if (size.height < minHeight) {
+    // Do not consider maxHeight, 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 the possibly displayed admin toolbar.
+  var $toolbar = $('#toolbar');
+  var toolbarHeight = $toolbar ? $toolbar.height() : 0;
+  var position = {
+    left: Math.max(0, parseInt(($window.width() - elementSize.width) / 2)),
+    top: toolbarHeight + 20
+  };
+  // @todo: this helps when the toolbar moves with the page, since otherwise
+  // we might open a screen which does not show on the viewport. It is not
+  // nice however, when one scrolls up top again and the overlay is not there.
+  if ($element.css('position') != 'fixed') {
+    var $document = $(document);
+    position.left += $document.scrollLeft();
+    position.top += $document.scrollTop();
+  }
+  return position;
+};
+
+/**
+ * Resize overlay.
+ */
+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 (self.isObject(self.iframe.$element) && self.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);
+      $('.overlay-shadow-right').height(frameSize.height);
+      
+      // Animate shadows and the close button
+      $('.overlay-shadow', $(this)).animate({opacity:1}, 'slow');
+
+      // 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 page as it loads in. 
+      $(self.iframe.$element.get(0)).contents().find('body.overlay').animate({opacity:1}, 'slow');
+    }
+  });
+};
+
+})(jQuery);
diff --git modules/overlay/overlay.info modules/overlay/overlay.info
new file mode 100644
index 0000000..13a0fd1
--- /dev/null
+++ modules/overlay/overlay.info
@@ -0,0 +1,7 @@
+; $Id$
+name = Administration overlay
+description = Displays the Drupal administration interface in an overlay.
+package = Core
+version = VERSION
+core = 7.x
+files[] = overlay.module
diff --git modules/overlay/overlay.module modules/overlay/overlay.module
new file mode 100644
index 0000000..5f215ee
--- /dev/null
+++ modules/overlay/overlay.module
@@ -0,0 +1,192 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Displays the Drupal administration interface in an overlay.
+ */
+
+/**
+ * Displaying an overlay parent window.
+ */
+define('OVERLAY_PARENT', 0);
+
+/**
+ * Displaying an overlay child window.
+ */
+define('OVERLAY_CHILD', 1);
+
+/**
+ * Implementation of hook_init().
+ */
+function overlay_init() {
+  global $custom_theme;
+  // Only act if the admin toolbar "is enabled" (user has access).
+  if (user_access('access toolbar')) {
+    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(OVERLAY_CHILD);
+    }
+    else {
+      // Otherwise add overlay parent code and our behavior.
+      overlay_mode(OVERLAY_PARENT);
+    }
+  }
+}
+
+/**
+ * Implementation of hook_elements().
+ */
+function overlay_elements() {
+  $elements = array();
+  $elements['form']['#after_build_recursive'][] = 'overlay_form_after_build';
+  return $elements;
+}
+
+/**
+ * Preprocess template variables for page.tpl.php.
+ */
+function overlay_preprocess_page(&$variables) {
+  if (overlay_mode() == OVERLAY_CHILD) {
+    // When rendering a page for the overlay, skip all regions generated by
+    // blocks, except the content and help regions.
+    foreach ($variables['page'] as $key => $value) {
+      if (strpos($key, '#') !== 0 && !in_array($key, array('content', 'help'))) {
+        unset($variables['page'][$key]);
+      }
+    }
+    // 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();
+  }
+}
+
+/**
+ * Form after build callback.
+ *
+ * Ok, all hook_form_alter() have been processed. Now, if someone has enabled
+ * the global variable $GLOBALS['overlay_page_template'], then we want to
+ * scan the form structure in search of elements with submit handlers.
+ *
+ * @see _form_builder_handle_input_element()
+ * @see _form_builder_ie_cleanup()
+ * @see form_execute_handlers()
+ * @see form_builder()
+ *
+ * @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 set $form_state['redirect'] is set 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.
+ *
+ * @ingroup forms
+ */
+function overlay_form_submit($form, &$form_state) {
+  if (is_array($form_state['redirect'])) {
+    if (!empty($form_state['redirect'][1])) {
+      if (is_array($form_state['redirect'][1])) {
+        // Query is an array, add our marker as a key.
+        $form_state['redirect'][1]['render'] = 'overlay';
+      }
+      else {
+        // Query is not an array, add our marker as string.
+        $form_state['redirect'][1] .= '&render=overlay';
+      }
+    }
+    else {
+      // Empty or is not set, but parent is array. Add array.
+      $form_state['redirect'][1] = array('render' => 'overlay');
+    }
+  }
+  elseif (!isset($form_state['redirect']) || ($form_state['redirect'] !== FALSE && $form_state['redirect'] !== NULL)) {
+    // Not an array. Save the path value and add our own marker.
+    $form_state['redirect'] = array(!empty($form_state['redirect']) ? $form_state['redirect'] : $_GET['q'], array('render' => 'overlay'));
+  }
+}
+
+/**
+ * Set overlay mode and add proper Javascript and styles to the page.
+ *
+ * @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;
+  $module_path = drupal_get_path('module', 'overlay');
+
+  switch($mode) {
+    case OVERLAY_PARENT:
+      // Add required jQuery UI elements. Note that we don't use
+      // drupal_add_library() here, since we have no use for the CSS files added
+      // by the library.
+      drupal_add_js('misc/ui/ui.core.js', array('weight' => JS_LIBRARY + 5));
+      drupal_add_js('misc/ui/ui.dialog.js', array('weight' => JS_LIBRARY + 6));
+
+      drupal_add_css($module_path . '/overlay-parent.css');
+      drupal_add_js($module_path . '/overlay-parent.js');
+
+      $settings = array(
+        'overlay' => array(
+          'shadowPath' => $base_path . drupal_get_path('module', 'overlay') . '/images/ovrly-shdw-bt-lt.png',
+        ),
+      );
+      drupal_add_js($settings, array('type' => 'setting'));
+      break;
+
+   case OVERLAY_CHILD:
+      // Disable admin toolbar, which is something child windows don't need.
+      module_invoke('toolbar', 'suppress', TRUE);
+
+      // This is required to get access to jQuery UI extensions to jQuery itself,
+      // such as the ':focusable' and ':tabbable' selectors. No need for the whole
+      // library, so not using drupal_add_library().
+      drupal_add_js('misc/ui/ui.core.js', array('weight' => JS_LIBRARY + 5));
+
+      // Add javascript to the child page.
+      drupal_add_js($module_path . '/overlay-child.js');
+      break;
+  }
+  return $overlay_mode;
+}
diff --git profiles/default/default.info profiles/default/default.info
index df84c2f..3026262 100644
--- profiles/default/default.info
+++ profiles/default/default.info
@@ -14,3 +14,4 @@ dependencies[] = taxonomy
 dependencies[] = dblog
 dependencies[] = search
 dependencies[] = toolbar
+dependencies[] = overlay
