diff --git a/link.module b/link.module
index 1e9d088..a5739f6 100644
--- a/link.module
+++ b/link.module
@@ -336,6 +336,27 @@ function link_field_widget_form(&$form, &$form_state, $field, $instance, $langco
     '#type' => $instance['widget']['type'],
     '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
   );
+  if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
+    $field_parents = $element['#field_parents'];
+    $field_name = $element['#field_name'];
+    $language = $element['#language'];
+    $parents = array_merge($field_parents, array($field_name, $language, $delta));
+    $element['remove_button'] = array(
+      '#delta' => $delta,
+      '#name' => implode('_', $parents) . '_remove_button',
+      '#type' => 'submit',
+      '#value' => t('Remove'),
+      '#validate' => array(),
+      '#submit' => array('link_remove_submit'),
+      '#limit_validation_errors' => array(),
+      '#weight' => 1000,
+      '#ajax' => array(
+        'effect' => 'fade',
+        'callback' => 'link_remove_callback',
+        //'wrapper' is set at link_field_attach_form()
+      ),
+    );
+  }
   return $element;
 }
 
@@ -899,6 +920,108 @@ function link_field_process($element, $form_state, $complete_form) {
 }
 
 /**
+ * Form submission handler for remove buttons of link_field elements.
+ *
+ * @see file_managed_file_process()
+ */
+function link_remove_submit($form, &$form_state) {
+  // Determine which delta the 'Remove' button was triggered.
+  $button = $form_state['triggering_element'];
+  $delta = $button['#delta'];
+
+  $address = array_slice($button['#array_parents'], 0, -2);
+
+  $parent_element = drupal_array_get_nested_value($form, $address);
+  $field_name = $parent_element['#field_name'];
+  $langcode = $parent_element['#language'];
+  $parents = $parent_element['#field_parents'];
+
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
+
+  for ($i = $delta; $i <= $field_state['items_count']; $i++) {
+    $old_element_address = array_merge($address, array($i + 1));
+    $new_element_address = array_merge($address, array($i));
+
+    $moving_element = drupal_array_get_nested_value($form, $old_element_address);
+    $moving_element_value = drupal_array_get_nested_value($form_state['values'], $old_element_address);
+    $moving_element_input = drupal_array_get_nested_value($form_state['input'], $old_element_address);
+    $moving_element_field = drupal_array_get_nested_value($form_state['field']['#parents'], $old_element_address);
+
+    // Tell the element where it's being moved to.
+    $moving_element['#parents'] = $new_element_address;
+
+    // Move the element around.
+    form_set_value($moving_element, $moving_element_value, $form_state);
+    drupal_array_set_nested_value($form_state['input'], $moving_element['#parents'], $moving_element_input);
+    drupal_array_set_nested_value($form_state['field']['#parents'], $moving_element['#parents'], $moving_element_field);
+
+    // Move the entity in our saved state.
+    if (isset($field_state['entity'][$i + 1])) {
+      $field_state['entity'][$i] = $field_state['entity'][$i + 1];
+    }
+    else {
+      unset($field_state['entity'][$i]);
+    }
+  }
+
+  // Replace the deleted entity with an empty one. This helps to ensure that
+  // trying to add a new entity won't ressurect a deleted entity
+  // from thev trash bin.
+  // $count = count($field_state['entity']);
+  // Then remove the last item. But we must not go negative.
+  if ($field_state['items_count'] > 0) {
+    $field_state['items_count']--;
+  }
+
+  // Fix the weights. Field UI lets the weights be in a range of
+  // (-1 * item_count) to (item_count). This means that when we remove one,
+  // the range shrinks; weights outside of that range then get set to
+  // the first item in the select by the browser, floating them to the top.
+  // We use a brute force method because we lost weights on both ends
+  // and if the user has moved things around, we have to cascade because
+  // if I have items weight weights 3 and 4, and I change 4 to 3 but leave
+  // the 3, the order of the two 3s now is undefined and may not match what
+  // the user had selected.
+  $input = drupal_array_get_nested_value($form_state['input'], $address);
+  // Sort by weight.
+  uasort($input, '_field_sort_items_helper');
+
+  // Reweight everything in the correct order.
+  $weight = -1 * $field_state['items_count'];
+  foreach ($input as $key => $item) {
+    if ($item) {
+      $input[$key]['_weight'] = $weight++;
+    }
+  }
+  drupal_array_set_nested_value($form_state['input'], $address, $input);
+  field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
+
+  $form_state['rebuild'] = TRUE;
+}
+
+/**
+ * Callback to rebuild the form for AJAX.
+ */
+function link_remove_callback($form, &$form_state) {
+  $button = $form_state['triggering_element'];
+
+  // Go one level up in the form, to the widgets container.
+  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -2));
+  $field_name = $element['#field_name'];
+  $langcode = $element['#language'];
+  $parents = $element['#field_parents'];
+
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
+
+  $field = $field_state['field'];
+  if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
+    return;
+  }
+
+  return $element;
+}
+
+/**
  * Implements hook_field_formatter_info().
  */
 function link_field_formatter_info() {
@@ -1521,3 +1644,38 @@ function link_i18n_string_list_field_alter(&$strings, $type = NULL, $object = NU
     $strings['field'][$object['field_name']][$object['bundle']]['title_value']['string'] = $object['settings']['title_value'];
   }
 }
+
+/**
+ * Implements hook_field_attach_form().
+ *
+ * @see field_add_more_js()
+ * @see link_field_widget_form()
+ */
+function link_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
+
+  foreach (field_info_instances($entity_type, $form['#bundle']) as $field_name => $instance) {
+    $field = field_info_field($field_name);
+
+      if ($field['type'] == 'link_field') {
+
+      $element_langcode = $form[$field_name]['#language'];
+      if ($form[$field_name][$element_langcode]['#max_delta'] > 0) {
+        $form[$field_name][$element_langcode]['#max_delta']--;
+      }
+    }
+
+    if ($field['type'] == 'link_field'
+        && $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED
+        && empty($form_state['programmed'])
+        && field_access('edit', $field, $entity_type)) {
+
+      $element_langcode = $form[$field_name]['#language'];
+      $element_wrapper = $form[$field_name][$element_langcode]['add_more']['#ajax']['wrapper'];
+      for ($i = 0; $i <= $form[$field_name][$element_langcode]['#max_delta']; $i++) {
+        if (isset($form[$field_name][$element_langcode][$i]['remove_button'])) {
+          $form[$field_name][$element_langcode][$i]['remove_button']['#ajax']['wrapper'] = $element_wrapper;
+        }
+      }
+    }
+  }
+}
