diff --git a/multiple_value_widget.module b/multiple_value_widget.module
index e7c9b32..bd6582e 100644
--- a/multiple_value_widget.module
+++ b/multiple_value_widget.module
@@ -20,115 +20,80 @@ function multiple_value_widget_theme() {
  * Impements hook_theme_registry_alter().
  */
 function multiple_value_widget_theme_registry_alter(&$theme_registry) {
-  $theme_registry['field_multiple_value_form']['function'] = 'multiple_value_widget_field_multiple_value_form';
-  $theme_registry['file_widget_multiple']['function'] = 'multiple_value_widget_file_widget_multiple';
+  $theme_registry['field_multiple_value_form']['function'] = 'multiple_value_widget_generic';
+  $theme_registry['file_widget_multiple']['function'] = 'multiple_value_widget_generic';
 }
 
 /**
- * Implements theme_field_multiple_value_form().
+ * Implements hook_field_attach_form().
+ *
+ * @see _field_invoke()
  */
-function multiple_value_widget_field_multiple_value_form($variables) {
-
-  $element = $variables['element'];
-
-  // Why do we need this?
-  if ($element['#cardinality'] == 1) {
-    return;
-  }
-
-  // Sort items according to '_weight' (needed when the form comes back after
-  // preview or failed validation).
-  $widgets = array();
+function multiple_value_widget_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
+  $default_options = array(
+    'default' => FALSE,
+    'deleted' => FALSE,
+    'language' => NULL,
+  );
 
-  foreach (element_children($element) as $key) {
-    if ($key === 'add_more') {
-      $add_more_button = &$element[$key];
+  list(, , $bundle) = entity_extract_ids($entity_type, $entity);
+  $instances = _field_invoke_get_instances($entity_type, $bundle, $default_options);
+
+  // Iterate through the instances and collect results.
+  foreach ($instances as $instance) {
+    // field_info_field() is not available for deleted fields, so use
+    // field_info_field_by_id().
+    $field = field_info_field_by_id($instance['field_id']);
+    $field_name = $field['field_name'];
+    $field_langcode = $form[$field_name]['#language'];
+    $field_form_element = &$form[$field_name][$field_langcode];
+    if ($field['cardinality'] != 1 && isset($field_form_element['#theme'])) {
+      $field_form_element['#process'][] = 'multiple_value_field_form_element_process';
     }
-    else {
-      $widgets[] = &$element[$key];
-    }
-  }
-
-  $first_widget = $widgets[0];
-  // Special case for Entity reference module.
-  // TODO: Find more clear way to read field instance.
-  if (isset($first_widget['target_id'])) {
-    $first_widget = $first_widget['target_id'];
-  }
-  $instance = field_read_instance($first_widget['#entity_type'], $first_widget['#field_name'], $first_widget['#bundle']);
-  if (empty($instance['widget']['settings']['multiple_value_widget']) || $instance['widget']['settings']['multiple_value_widget'] == 'table') {
-    return theme_field_multiple_value_form($variables);
   }
+}
 
-  $widget_type = $instance['widget']['settings']['multiple_value_widget'];
-
-  usort($widgets, '_field_sort_items_value_helper');
-  $id = 'mvw-' . $element['#field_name'];
-  multiple_value_widget_add_asserts($id, $widget_type);
-
-  $groups = array();
-  $output = '<div id="' . $id . '" class="mvw-type-' . $widget_type . '">';
-  foreach ($widgets as $delta => $widget) {
-    $widget['_weight']['#attributes']['class'] = array('mvw-weight-delta-order');
-    $group_id = 'mvw-group-' . $element['#field_name'] . '-' . $delta;
-
-    $title = $element['#title'] . ' (' . ($delta + 1) . ')';
-
-    $element['#delta'] = $delta;
-    drupal_alter('multiple_value_widget_element_title', $title, $element);
-
-    if ($widget_type == 'tabs') {
-      $links['mvw-tab-' . $delta] = array(
-        'href' => '',
-        'title' => $title,
-        'html' => TRUE,
-        'fragment' => $group_id ,
-        'external' => TRUE,
-      );
-    }
+/**
+ * Stores the field's instance information as an element property.
+ */
+function multiple_value_field_form_element_process($element, &$form_state, &$form) {
+  $parents = $element['#field_parents'];
+  $field_name = $element['#field_name'];
+  $langcode = $element['#language'];
 
-    $groups[$delta] = array(
-      '#theme' => 'multiple_value_widget_group',
-      '#title' => $title,
-      '#widget_type' => $widget_type,
-      '#attributes' => array(
-        'id' => $group_id,
-        'class' => array('mvw-group', 'delta-' . $delta),
-      ),
-      'widget' => $widget,
-    );
-  }
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
 
-  if ($widget_type == 'tabs' && isset($links)) {
-    $attributes = array('class' => array('mvw-tabs'));
-    $output .= theme('links', array('links' => $links, 'attributes' => $attributes));
+  if (!empty($field_state['instance']['widget']['settings']['multiple_value_widget']) && $field_state['instance']['widget']['settings']['multiple_value_widget'] !== 'table') {
+    $element['#multiple_value_widget'] = $field_state['instance'];
   }
 
-  $output .= render($groups);
-
-  $output .= '</div>';
-  $output .= '<div class="clearfix">' . drupal_render($add_more_button) . '</div>';
-
-  return $output;
+  return $element;
 }
 
 /**
- * Implements theme_file_widget_multiple().
+ * Implements theme_multiple_value_widget_generic().
  */
-function multiple_value_widget_file_widget_multiple($variables) {
+function multiple_value_widget_generic($variables) {
 
   $element = $variables['element'];
 
-  // Get our list of widgets in order (needed when the form comes back after
-  // preview or failed validation).
-  $widgets = array();
-  foreach (element_children($element) as $key) {
-    $widgets[] = &$element[$key];
+  if (!isset($element['#multiple_value_widget'])) {
+    $theme_function = 'theme_' . $variables['theme_hook_original'];
+    return $theme_function($variables);
   }
 
-  $instance = field_read_instance($widgets[0]['#entity_type'], $widgets[0]['#field_name'], $widgets[0]['#bundle']);
-  if (empty($instance['widget']['settings']['multiple_value_widget']) || $instance['widget']['settings']['multiple_value_widget'] == 'table') {
-    return theme_file_widget_multiple($variables);
+  // Obtain the file instance information.
+  $instance = $element['#multiple_value_widget'];
+
+  // Sort widgets.
+  $widgets = array();
+  foreach (element_children($element) as $key) {
+    if ($key === 'add_more') {
+      $add_more_button = &$element[$key];
+    }
+    else {
+      $widgets[] = &$element[$key];
+    }
   }
 
   $widget_type = $instance['widget']['settings']['multiple_value_widget'];
@@ -141,23 +106,22 @@ function multiple_value_widget_file_widget_multiple($variables) {
 
   $output = '<div id="' . $id . '" class="mvw-type-' . $widget_type . '">';
 
-  $gpoups = array();
+  $groups = array();
   $total_widgets = count($widgets);
   foreach ($widgets as $delta => &$widget) {
 
-    // Save the uploading row for last.
-    if ($widget['#file'] == FALSE) {
-      $widget['#title'] = $element['#file_upload_title'];
-      $widget['#description'] = $element['#file_upload_description'];
-      continue;
-    }
-
-    if (isset($widget['#file'])) {
-      $title = '<span class="file">' . check_plain($widget['#file']->filename) . '</span>';
-      $title .= ' <span class="file-size">(' . format_size($widget['#file']->filesize) . ')</span> ';
-    }
-    else {
-      $title = $element['#title'] . ' (' . ($delta + 1) . ')';
+    $title = $element['#title'] . ' (' . ($delta + 1) . ')';
+    if ($variables['theme_hook_original'] == 'file_widget_multiple') {
+      // Save the uploading row for last.
+      if ($widget['#file'] == FALSE) {
+        $widget['#title'] = $element['#file_upload_title'];
+        $widget['#description'] = $element['#file_upload_description'];
+        continue;
+      }
+      if (isset($widget['#file'])) {
+        $title = '<span class="file">' . check_plain($widget['#file']->filename) . '</span>';
+        $title .= ' <span class="file-size">(' . format_size($widget['#file']->filesize) . ')</span> ';
+      }
     }
     $element['#delta'] = $delta;
 
@@ -199,6 +163,9 @@ function multiple_value_widget_file_widget_multiple($variables) {
   }
   $output .= render($groups);
   $output .= '</div>';
+  if (isset($add_more_button)) {
+    $output .= '<div class="clearfix">' . drupal_render($add_more_button) . '</div>';
+  }
 
   $output .= drupal_render_children($element);
 
@@ -218,7 +185,6 @@ function multiple_value_widget_add_asserts($id, $widget_type) {
   drupal_add_js(array('mvw' => array($id => $widget_type)), 'setting');
 }
 
-
 /**
  * Returns HTML for a single widget group.
  */
@@ -256,7 +222,6 @@ function theme_multiple_value_widget_group($vars) {
   return $output;
 }
 
-
 /**
  * Impements hook_from_FORM_ID_alter().
  */
@@ -275,8 +240,10 @@ function multiple_value_widget_form_field_ui_field_edit_form_alter(&$form, &$for
 
   if ($multiple_values_behaviors == FIELD_BEHAVIOR_DEFAULT || in_array($widget['type'], $file_field_widgets)) {
 
-    if (isset($form['#instance']['widget']['settings']['multiple_value_widget'])) {
-      $default_value = $form['#instance']['widget']['settings']['multiple_value_widget'];
+    $settings = $form['#instance']['widget']['settings'];
+
+    if (isset($settings['multiple_value_widget'])) {
+      $default_value = $settings['multiple_value_widget'];
     }
     else {
       $default_value = 'table';
