diff --git a/autosave.api.php b/autosave.api.php
new file mode 100644
index 0000000..c03ca5a
--- /dev/null
+++ b/autosave.api.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @file
+ * API documentation for Autosave module.
+ */
+
+/**
+ * Implements hook_autosave_prevent_alter().
+ *
+ * @param $prevent_autosave
+ *   Set this to TRUE to prevent autosaving.
+ *
+ *   More useful parameters are in $_POST.
+ */
+function hook_autosave_prevent_alter(&$prevent_autosave) {
+  $path = $_POST['autosave_form_path'];
+  $path_args = explode("/", $path);
+  // check if node has just been saved - if it has then it's because AS ajax fired off as user was submitting
+  // if it had just been submitted - no need to AS now
+  //    - easy to figure out if we are submitting an edit to existing node
+  //    - little harder if we have just added a node
+  if ($path_args[0] == 'node') {
+    // update case
+    if (is_numeric($path_args[1])) {
+      $submitted = node_load($path_args[1]);
+    }
+    else {
+      // add case
+      $submitted = db_query_range("SELECT created AS changed FROM {node} WHERE uid = :uid and type = :type ORDER BY created DESC", 0, 1, array(
+        ':uid' => $user->uid,
+        ':type' => str_replace("-", "_", $path_args[2])))->fetchObject();
+    }
+    $prevent_autosave = ($submitted && (REQUEST_TIME - $submitted->changed < variable_get('autosave_period', 10))) ? TRUE : $prevent_autosave;
+  }
+}
diff --git a/autosave.install b/autosave.install
index 8d564b2..0d1f1d8 100644
--- a/autosave.install
+++ b/autosave.install
@@ -28,8 +28,9 @@ function autosave_install() {
 ().
  */
 function autosave_uninstall() {
-  // TODO The drupal_(un)install_schema functions are called automatically in D7.
-  // drupal_uninstall_schema('autosave')
+  variable_del('autosave_period');
+  variable_del('autosave_hidden');
+  variable_del('autosave_form_ids');
 }
 
 /**
@@ -66,8 +67,53 @@ function autosave_schema() {
           'not null'    => TRUE,
           'size'        => 'big',
         ),
+        'args' => array(
+          'type'        => 'text',
+          'size'        => 'big',
+        ),
       ),
       'primary key' => array('form_id', 'path', 'uid'),
     ),
   );
 }
+
+/**
+ * New column in {autosaved_forms} : args
+ */
+function autosave_update_7000() {
+  $spec = array(
+    'type'        => 'text',
+    'size'        => 'big',
+  );
+  db_add_field( 'autosaved_forms', 'args', $spec);
+
+  // Fill in the args field of already saved forms.
+  $result = db_select('autosaved_forms', 'af')
+    ->fields('af', array('path', 'uid', 'form_id'))
+    ->execute()
+    ->fetchAll();
+
+  foreach ($result as $form) {
+    $path_parts = explode('/', $form->path);
+    unset($node);
+    if (strpos($form->path, 'node/add/') === 0) {
+      $node = new stdClass();
+      $node->type = $path_parts[2];
+      node_object_prepare($node);
+      $node->uid = $form->uid;
+      $author = user_load($form->uid);
+      $node->name = $author->name;
+    }
+    elseif (($path_parts[0] == 'node') && ($path_parts[2] == 'edit')) {
+      $node = node_load($path_parts[1]);
+    }
+    if (isset($node)) {
+      db_update('autosaved_forms')
+        ->condition('form_id', $form->form_id)
+        ->condition('uid', $form->uid)
+        ->condition('path', $form->path)
+        ->fields(array('args' => array(serialize($node))))
+        ->execute();
+    }
+  }
+}
diff --git a/autosave.js b/autosave.js
index 1a1c399..1dceb6c 100644
--- a/autosave.js
+++ b/autosave.js
@@ -12,8 +12,8 @@ Drupal.behaviors.autosave.attach = function (context, settings) {
   }
 
   autosaveSettings = settings.autosave;
-
-  $('#' + autosaveSettings.formid).not('.autosave-processed').addClass('autosave-processed').autosave({
+  var $selector = $('input[name="form_id"][value="' + autosaveSettings.formid + '"] ').parents('form').not('.autosave-processed');
+  $selector.addClass('autosave-processed').autosave({
     interval: autosaveSettings.period * 1000, // Time in ms
     url: autosaveSettings.url,
     setup: function (e, o) {
diff --git a/autosave.module b/autosave.module
index 1c61c37..fea9ea5 100644
--- a/autosave.module
+++ b/autosave.module
@@ -111,6 +111,12 @@ function autosave_admin_settings($form, &$form_state) {
     '#suffix' => "</div>",
   );
 
+  $form['autosave_form_ids'] = array(
+    '#type' => 'textarea',
+    '#default_value' => variable_get('autosave_form_ids', ''),
+    '#title' => t('Form ids to autosave'),
+    '#description' => t('Add the form ids that autosave should apply to. Each form id should go into a separate line. Note that node form autosaving can also be enabled on the node type admin form. The form id of a form is the \'value\' attribute of the hidden &lt;input&gt; HTML element with the name \'form_id\' in the &lt;form&gt;.'),
+  );
   return system_settings_form($form);
 }
 
@@ -127,69 +133,117 @@ function autosave_form_node_type_form_alter(&$form, $form_state) {
 }
 
 /**
- * Implements hook_form_BASE_FORM_ID_alter().
+ * Implements hook_form_alter().
  */
-function autosave_form_node_form_alter(&$form, &$form_state, $form_id) {
-  $node = $form['#node'];
-
-  if (arg(0) != 'admin' && variable_get('autosave_' . $node->type, 0) && empty($_POST['autosave_form_path'])) {
-    $path = request_path();
-
-    // Make a note in the form of what the original path is, since when submitting
-    // the autosaved form to our own callback it will not be the same.
-    $form['autosave_form_path'] = array(
-      '#type' => 'hidden',
-      '#value' => $path,
-    );
+function autosave_form_alter(&$form, &$form_state, $form_id) {
+  // Autosaving node forms can be enabled both by adding the form_id at
+  // admin/config/content/autosave or by checking the 'Enable Autosave'
+  // checkbox at admin/structure/types/manage/[node:type]. The following
+  // variable is TRUE if autosaving is enabled on the latter link and we
+  // are on a node form.
+  $autosave_node_form = FALSE;
+  if (!empty($form['#node_edit_form'])) {
+    $node = $form['#node'];
+    $autosave_node_form = (variable_get('autosave_' . $node->type, 0) && (arg(0) != 'admin'));
+  }
+  $form_ids = explode("\n", variable_get('autosave_form_ids', ''));
+  foreach ($form_ids as &$formid) {
+    $formid = trim($formid);
+  }
 
-    $formid = str_replace("_", "-", $form_id);
-
-    $settings['autosave']['formid'] = $formid;
-    $settings['autosave']['url'] = url('autosave/handler');
-    $settings['autosave']['period'] = variable_get('autosave_period', 10);
-    $settings['autosave']['q'] = $path;
-    $settings['autosave']['hidden'] = variable_get('autosave_hidden', 0);
-    $settings['autosave']['theme'] = $GLOBALS['theme'];
-
-    // If an autosaved version of the form exists, let the user know so that
-    // he can restore it if desired.
-    $timestamp = db_query("SELECT timestamp FROM {autosaved_forms} WHERE form_id = :form_id AND path = :path AND uid = :uid", array(
-      ':form_id' => $form_id,
-      ':path' => $path,
-      ':uid' => $GLOBALS['user']->uid,
-    ))->fetchField();
-    $settings['autosave']['savedTimestamp'] = $timestamp ? $timestamp : 0;
-    $settings['autosave']['savedDate'] = $timestamp ? format_date($timestamp) : 0;
-    $settings['autosave']['formToken'] = drupal_get_token($form_id);
-
-    $form['autosave_form_path']['#attached']['library'][] = array('autosave', 'autosave');
-    $form['autosave_form_path']['#attached']['js'][] = array(
-      'data' => $settings,
-      'type' => 'setting',
-      'scope' => JS_DEFAULT,
-    );
+  if (($autosave_node_form || in_array($form_id, $form_ids))) {
+    // Remove the autosaved form when submitting it.
+    array_unshift($form['#submit'], 'autosave_remove_autosaved_form_submit');
+    if (empty($_POST['autosave_form_path'])) {
+      $request_path = request_path();
+      // We store the drupal system paths, not the aliases.
+      $path = drupal_lookup_path('source', $request_path);
+      // For already system paths $path is FALSE.
+      if (!$path) {
+        $path = $request_path;
+      }
+      // Make a note in the form of what the original path is, since when
+      // submitting the autosaved form to our own callback it will not be
+      // the same.
+      $form['autosave_form_path'] = array(
+        '#type' => 'hidden',
+        '#value' => $path,
+      );
+
+      // Store form arguments in db only if the form has not been autosaved
+      // before.
+      if (!empty($form_state['build_info']['args']) && strpos($path, 'autosave/restore/') !== 0) {
+        $key = array(
+          'form_id' => $form_id,
+          'uid' => $GLOBALS['user']->uid,
+          'path' => $path,
+        );
+        db_merge('autosaved_forms')
+          ->key($key)
+          ->insertFields(array_merge($key, array(
+            'timestamp' => 0,
+            'serialized' => '',
+            'args' => serialize($form_state['build_info']['args'])
+          )))
+          ->updateFields($key)
+          ->execute();
+      }
+
+      $settings['autosave']['formid'] = $form_id;
+      $settings['autosave']['url'] = url('autosave/handler');
+      $settings['autosave']['period'] = variable_get('autosave_period', 10);
+      $settings['autosave']['q'] = $path;
+      $settings['autosave']['hidden'] = variable_get('autosave_hidden', 0);
+      $settings['autosave']['theme'] = $GLOBALS['theme'];
+
+      // If an autosaved version of the form exists, let the user know so that
+      // he can restore it if desired.
+      $timestamp = db_query("SELECT timestamp FROM {autosaved_forms} WHERE form_id = :form_id AND path = :path AND uid = :uid", array(
+        ':form_id' => $form_id,
+        ':path' => $path,
+        ':uid' => $GLOBALS['user']->uid,
+      ))->fetchField();
+      $settings['autosave']['savedTimestamp'] = $timestamp ? $timestamp : 0;
+      $settings['autosave']['savedDate'] = $timestamp ? format_date($timestamp) : 0;
+      $settings['autosave']['formToken'] = drupal_get_token($form_id);
+
+      $form['#id'] = str_replace("_", "-", $form_id);
+      $form['autosave_form_path']['#attached']['library'][] = array('autosave', 'autosave');
+      $form['autosave_form_path']['#attached']['js'][] = array(
+        'data' => $settings,
+        'type' => 'setting',
+        'scope' => JS_DEFAULT,
+      );
+    }
   }
 }
 
 /**
+ * Form submit callback to remove the autosaved form when submitting it.
+ */
+function autosave_remove_autosaved_form_submit($form, $form_state) {
+  global $user;
+  db_delete('autosaved_forms')
+    ->condition('form_id', $form['#form_id'])
+    ->condition('path', $_POST['autosave_form_path'])
+    ->condition('uid', $user->uid)
+    ->execute();
+}
+
+/**
  * Menu callback; AHAH return the form, repopulated with autosaved data.
  *
  * @global type $user
- * @param string $formid
- *   The ID of the form to reload.  This should be in Javascript format, vis,
- *   using - instead of _.
+ * @param string $form_id
+ *   The form_id of the form to reload.
  * @param int $timestamp
  *   The timestamp at which the autosaved form was saved.  This is used to
  *   differentiate between different people mucking with the same form.
  */
-function autosave_restore($formid, $timestamp) {
+function autosave_restore($form_id, $timestamp) {
   global $user;
-
-  // Convert the form ID back to the PHP version.  I do hate that duality...
-  $form_id = str_replace("-", "_", $formid);
-
   // Fetch the saved form, if any.
-  $record = autosave_get_autosaved_form($form_id, $timestamp, $GLOBALS['user']->uid);
+  $record = autosave_get_autosaved_form($form_id, $timestamp, $user->uid);
 
   if ($record) {
     // We need to extract and reuse any additional page arguments that the
@@ -202,17 +256,11 @@ function autosave_restore($formid, $timestamp) {
     }
     $form_state['input'] = unserialize($record->serialized);
 
-    // The node_form() form builder expects the first argument to be a full node
-    // object, even when adding a new node. The node/add/[type] menu item only
-    // has a string as its argument, instead of a full object, so we convert it
-    // here for the form.
-    $build_info_args = $menu_item['page_arguments'];
-    if (is_string($build_info_args[0])) {
-      $node = (object) array('type' => $build_info_args[0]);
-      node_object_prepare($node);
-      $build_info_args[0] = $node;
+    // Restore form arguments.
+    if (!empty($record->args)) {
+      $args = unserialize($record->args);
+      $form_state['build_info']['args'] = $args;
     }
-    $form_state['build_info']['args'] = $build_info_args;
 
     // Disable the "this form has already been submitted" nonsense by making
     // Drupal think the form is being rebuilt as part of a multi-step form.
@@ -227,12 +275,11 @@ function autosave_restore($formid, $timestamp) {
     // originally.
     $form['#action'] = url($record->path);
     $form['autosave_form_path']['#value'] = $record->path;
-
     // We don't want to change the HTML ID of the form, because we're replacing
     // it in-place.  Drupal wants to give this a suffix for some reason.
-    $form['#id'] = $formid;
+    $form['#id'] = str_replace("_", "-", $form_id);
 
-    $commands[] = ajax_command_replace('#' . $formid, drupal_render($form));
+    $commands[] = ajax_command_replace('#' . $form['#id'], drupal_render($form));
 
     return array(
       '#type' => 'ajax',
@@ -273,9 +320,8 @@ function autosave_save_access() {
  * should not be able to access its saved version.  We also check that the
  * form's token is correct to avoid CSRF attacks.
  *
- * @param string $formid
- *   The ID of the form to reload.  This should be in Javascript format, vis,
- *   using - instead of _.
+ * @param string $form_id
+ *   The form_id of the form to reload.
  * @param int $timestamp
  *   The timestamp at which the autosaved form was saved.  This is used to
  *   differentiate between different people mucking with the same form.
@@ -285,48 +331,33 @@ function autosave_save_access() {
  * @return boolean
  *   True if the user should have restore access to this form, false otherwise.
  */
-function autosave_restore_access($formid, $timestamp, $form_token) {
-  $record = autosave_get_autosaved_form($formid, $timestamp, $GLOBALS['user']->uid);
+function autosave_restore_access($form_id, $timestamp, $form_token) {
+  $record = autosave_get_autosaved_form($form_id, $timestamp, $GLOBALS['user']->uid);
 
   if (isset($record->path)) {
     $menu_item = autosave_menu_get_item($record->path);
-
-    $token = drupal_valid_token($form_token, str_replace('-', '_', $formid));
+    $token = drupal_valid_token($form_token, $form_id);
     $menu = isset($menu_item['access']) ? $menu_item['access'] : FALSE;
     return $token && $menu;
   }
 }
 
 /**
- * Menu callback; autosaves the node.
+ * Menu callback; autosaves the form.
  */
 function autosave_save() {
   global $user;
+  // Possibility to prevent autosaving.
+  $prevent_autosave = FALSE;
+  drupal_alter('autosave_prevent', $prevent_autosave);
 
   $path = $_POST['autosave_form_path'];
   $form_id = $_POST['form_id'];
   // Not all variables need to be serialized.
-  //    - for Drupal 6 version need to remove op and form_build_id
   unset($_POST['autosave_form_path'], $_POST['op'], $_POST['form_build_id']);
   $serialized = serialize($_POST);
 
-  // check if node has just been saved - if it has then it's because AS ajax fired off as user was submitting
-  // if it had just been submitted - no need to AS now
-  //    - easy to figure out if we are submitting an edit to existing node
-  //    - little harder if we have just added a node
-  $path_args = explode("/", $path);
-  // update case
-  if (is_numeric($path_args[1])) {
-    $submitted = node_load($path_args[1]);
-  }
-  else {
-    // add case
-    $submitted = db_query_range("SELECT created AS changed FROM {node} WHERE uid = :uid and type = :type ORDER BY created DESC", 0, 1, array(
-      ':uid' => $user->uid,
-      ':type' => str_replace("-", "_", $path_args[2])))->fetchObject();
-  }
-
-  if (!$submitted || (REQUEST_TIME - $submitted->changed) > 10) {
+  if (!$prevent_autosave) {
     // Currently, each user can have only one autosave form at a particular path.
     db_merge('autosaved_forms')->key(array(
       'form_id' => $form_id,
@@ -343,6 +374,31 @@ function autosave_save() {
   exit();
 }
 
+/**
+ * Implements hook_autosave_prevent_alter().
+ */
+function autosave_autosave_prevent_alter(&$prevent_autosave) {
+  // TODO: Do something clever for not just node forms.
+  $path = $_POST['autosave_form_path'];
+  $path_args = explode("/", $path);
+  // check if node has just been saved - if it has then it's because AS ajax fired off as user was submitting
+  // if it had just been submitted - no need to AS now
+  //    - easy to figure out if we are submitting an edit to existing node
+  //    - little harder if we have just added a node
+  if ($path_args[0] == 'node') {
+    // update case
+    if (($path_args[2] == 'edit') && is_numeric($path_args[1])) {
+      $submitted = node_load($path_args[1]);
+    }
+    elseif ($path_args[1] == 'add') {
+      // add case
+      $submitted = db_query_range("SELECT created AS changed FROM {node} WHERE uid = :uid and type = :type ORDER BY created DESC", 0, 1, array(
+        ':uid' => $user->uid,
+        ':type' => str_replace("-", "_", $path_args[2])))->fetchObject();
+    }
+    $prevent_autosave = ($submitted && (REQUEST_TIME - $submitted->changed < variable_get('autosave_period', 10))) ? TRUE : $prevent_autosave;
+  }
+}
 
 /**
  * Get the autosaved form at a particular path for a user.
@@ -364,7 +420,7 @@ function autosave_get_autosaved_form($form_id, $timestamp, $uid) {
 
   if (empty($forms[$form_id][$timestamp])) {
     // Fetch the saved form, if any.
-    $forms[$form_id][$timestamp] = db_query("SELECT form_id, serialized, path, timestamp FROM {autosaved_forms} WHERE form_id = :form_id AND timestamp = :timestamp AND uid = :uid", array(
+    $forms[$form_id][$timestamp] = db_query("SELECT form_id, serialized, path, timestamp, args FROM {autosaved_forms} WHERE form_id = :form_id AND timestamp = :timestamp AND uid = :uid", array(
       ':form_id' => str_replace('-', '_', $form_id),
       ':timestamp' => $timestamp,
       ':uid' => $uid,
