Index: modules/overlay/overlay-parent.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/overlay/overlay-parent.js,v
retrieving revision 1.53
diff -u -r1.53 overlay-parent.js
--- modules/overlay/overlay-parent.js	31 Jul 2010 12:54:59 -0000	1.53
+++ modules/overlay/overlay-parent.js	6 Aug 2010 16:57:36 -0000
@@ -43,6 +43,10 @@
  *   child document is fully loaded.
  * - drupalOverlayLoad: This event is triggered when the overlay is finished
  *   loading.
+ * - drupalOverlayStoreFormData: This event is triggered when the overlay is
+ *   saving form data for possible restoration.
+ * - drupalOverlayRestoreFormData: This event is triggered when the overlay is
+ *   restoring form data back into the form.
  * - drupalOverlayResize: This event is triggered when the overlay is being
  *   resized to match the parent window.
  */
@@ -50,7 +54,8 @@
   isOpen: false,
   isOpening: false,
   isClosing: false,
-  isLoading: false
+  isLoading: false,
+  formData: {}
 };
 
 Drupal.overlay.prototype = {};
@@ -119,6 +124,9 @@
     .bind('drupalOverlayReady' + eventClass +
           ' drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerSyncURLFragment'))
     .bind('drupalOverlayClose' + eventClass, $.proxy(this, 'eventhandlerRefreshPage'))
+    .bind('drupalOverlayBeforeLoad' + eventClass +
+          ' drupalOverlayBeforeClose' + eventClass, $.proxy(this, 'eventhandlerStoreFormData'))
+    .bind('drupalOverlayReady' + eventClass, $.proxy(this, 'eventhandlerRestoreFormData'))
     .bind('drupalOverlayBeforeClose' + eventClass +
           ' drupalOverlayBeforeLoad' + eventClass +
           ' drupalOverlayResize' + eventClass, $.proxy(this, 'eventhandlerDispatchEvent'))
@@ -237,6 +245,110 @@
 };
 
 /**
+ * Saves form data of any form within the overlay for possible restoration.
+ *
+ * The form data is being stored in a JavaScript variable so forms can be
+ * restored if the overlay was closed accidentally and browser's back-button
+ * is being used.
+ */
+Drupal.overlay.storeFormData = function() {
+  if (!this.isOpen || !this.iframeWindow || !this.iframeWindow.document) {
+    return;
+  }
+
+  var self = this;
+  $('form', this.iframeWindow.document).each(function() {
+    var $form = $(this);
+    var formId = $form.attr('id');
+    // Overwrite any old data, replace it with the newer data. If we eventually
+    // do come back to this form, we'll want to re-populate it with the most up
+    // to date data available to us.
+    self.formData[formId] = {};
+    $form.find(':input').each(function() {
+      var $input = $(this);
+      var name = $input.attr('name');
+      // Basic validation: make sure the name is a non-empty string, and bypass
+      // input fields that aren't worth storing.
+      if (typeof name == 'string' && name.length && name != 'form_build_id' && name != 'form_token' && name != 'form_id' && name != 'op') {
+        // For checkboxes, store whether or not it's checked instead of storing
+        // an arbitrary value.
+        if ($input.is(':checkbox')) {
+          self.formData[formId][name] = $input.is(':checked');
+        }
+        // For radio buttons, only store the value if this specific radio button
+        // is currently selected.
+        else if ($input.is(':radio')) {
+          if ($input.is(':checked')) {
+            self.formData[formId][name] = $input.val();
+          }
+        }
+        // For everything else, just store the value.
+        else {
+          self.formData[formId][name] = $input.val();
+        }
+      }
+    });
+  });
+
+  // Allow other scripts to respond to this event.
+  $(document).trigger('drupalOverlaySaveFormData');
+};
+
+/**
+ * Restores previously stored form data of any form within the overlay.
+ *
+ * @see Drupal.overlay.storeFormData()
+ */
+Drupal.overlay.restoreFormData = function() {
+  if (!this.isOpen || !this.iframeWindow || !this.iframeWindow.document) {
+    return;
+  }
+
+  var self = this;
+  $('form', this.iframeWindow.document).each(function() {
+    var $form = $(this);
+    var formId = $form.attr('id');
+    if (typeof self.formData[formId] == 'object') {
+      $form.find(':input').each(function() {
+        var $input = $(this);
+        var name = $input.attr('name');
+        // Basic validation: make sure the name is a non-empty string.
+        if (typeof name == 'string' && name.length && typeof self.formData[formId][name] != 'undefined') {
+          // With checkboxes, we don't change the value; instead, we change
+          // the "checked" attribute.
+          if ($input.is(':checkbox')) {
+            if (self.formData[formId][name]) {
+              $input.attr('checked', 'checked').change();
+            }
+            else {
+              $input.removeAttr('checked').change();
+            }
+          }
+          // With radios, we also don't change the value; instead, we alter
+          // the "checked" attribute, checking it only if its value matches
+          // the value stored.
+          else if ($input.is(':radio')) {
+            if ($input.val() == self.formData[formId][name]) {
+              $input.attr('checked', 'checked').change();
+            }
+            else {
+              $input.removeAttr('checked').change();
+            }
+          }
+          // For all other elements, just set the value to the stored data.
+          else {
+            $input.val(self.formData[formId][name]);
+          }
+        }
+      });
+
+      // Allow other scripts to respond to this event.
+      $(document).trigger('drupalOverlayRestoreFormData');
+    }
+  });
+};
+
+/**
  * Bind the child window.
  *
  * Note that this function is fired earlier than Drupal.overlay.loadChild.
@@ -611,6 +723,26 @@
 };
 
 /**
+ * Event handler: stores form data of any form within the overlay.
+ *
+ * @param event
+ *   Event being triggered
+ */
+Drupal.overlay.eventhandlerStoreFormData = function (event) {
+  this.storeFormData();
+};
+
+/**
+ * Event handler: restores form data of any form within the overlay.
+ *
+ * @param event
+ *   Event being triggered
+ */
+Drupal.overlay.eventhandlerRestoreFormData = function (event) {
+  this.restoreFormData();
+};
+
+/**
  * Event handler: if the child window suggested that the parent refresh on
  * close, force a page refresh.
  *
