diff --git a/core/includes/common.inc b/core/includes/common.inc
index 5882f40..8725602 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2994,6 +2994,35 @@ function drupal_add_tabledrag($table_id, $action, $relationship, $group, $subgro
   drupal_add_js($settings, 'setting');
 }
 
+function drupal_attach_tabledrag(&$element, $options) {
+  $table_id = $options[0];
+  $action = $options[1];
+  $relationship = $options[2];
+  $group = $options[3];
+  $subgroup = !empty($options[4]) ? $options[4] : NULL;
+  $source = !empty($options[5]) ? $options[5] : NULL;
+  $hidden = !empty($options[6]) ? $options[6] : TRUE;
+  $limit = !empty($options[7]) ? $options[7] : 0;
+
+  $tabledrag_id = &drupal_static(__FUNCTION__  . '_setting', FALSE);
+  $tabledrag_id = (!isset($tabledrag_id)) ? 0 : $tabledrag_id + 1;
+
+  // If a subgroup or source isn't set, assume it is the same as the group.
+  $target = isset($subgroup) ? $subgroup : $group;
+  $source = isset($source) ? $source : $target;
+  $settings['tableDrag'][$table_id][$group][$tabledrag_id] = array(
+    'target' => $target,
+    'source' => $source,
+    'relationship' => $relationship,
+    'action' => $action,
+    'hidden' => $hidden,
+    'limit' => $limit,
+  );
+
+  $element['#attached']['library'][] = array('system', 'drupal.tabledrag');
+  $element['#attached']['js'][] = array('data' => $settings, 'type' => 'setting');
+}
+
 /**
  * Deletes old cached JavaScript files and variables.
  */
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index c77ddd0..13b0d4c 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1869,7 +1869,7 @@ function drupal_pre_render_table(array $element) {
     foreach ($element['#tabledrag'] as &$args) {
       array_unshift($args, $element['#attributes']['id']);
     }
-    $element['#attached']['drupal_add_tabledrag'] = $element['#tabledrag'];
+    drupal_attach_tabledrag($element, $element['#tabledrag']);
   }
 
   return $element;
diff --git a/core/modules/book/book.admin.inc b/core/modules/book/book.admin.inc
index 1d7061b..a5f24d3 100644
--- a/core/modules/book/book.admin.inc
+++ b/core/modules/book/book.admin.inc
@@ -22,8 +22,8 @@
 function theme_book_admin_table($variables) {
   $form = $variables['form'];
 
-  drupal_add_tabledrag('book-outline', 'match', 'parent', 'book-plid', 'book-plid', 'book-mlid', TRUE, MENU_MAX_DEPTH - 2);
-  drupal_add_tabledrag('book-outline', 'order', 'sibling', 'book-weight');
+  drupal_attach_tabledrag($form, array('book-outline', 'match', 'parent', 'book-plid', 'book-plid', 'book-mlid', TRUE, MENU_MAX_DEPTH - 2));
+  drupal_attach_tabledrag($form, array('book-outline', 'order', 'sibling', 'book-weight'));
 
   $header = array(t('Title'), t('Weight'), t('Parent'), t('Operations'));
 
diff --git a/core/modules/field/field.form.inc b/core/modules/field/field.form.inc
index 6f99192..1ec481d 100644
--- a/core/modules/field/field.form.inc
+++ b/core/modules/field/field.form.inc
@@ -77,13 +77,12 @@ function theme_field_multiple_value_form($variables) {
         'class' => array('field-multiple-table'),
       ),
     );
+    drupal_attach_tabledrag($table, array($table_id, 'order', 'sibling', $order_class));
     $output = '<div class="form-item">';
     $output .= drupal_render($table);
     $output .= $element['#description'] ? '<div class="description">' . $element['#description'] . '</div>' : '';
     $output .= '<div class="clearfix">' . drupal_render($add_more_button) . '</div>';
     $output .= '</div>';
-
-    drupal_add_tabledrag($table_id, 'order', 'sibling', $order_class);
   }
   else {
     foreach (element_children($element) as $key) {
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
index ede866c..d34983a 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
@@ -194,8 +194,8 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
     $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui');
 
     // Add tabledrag behavior.
-    $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'order', 'sibling', 'field-weight');
-    $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
+    drupal_attach_tabledrag($form, array('field-display-overview', 'order', 'sibling', 'field-weight'));
+    drupal_attach_tabledrag($form, array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name'));
 
     return $form;
   }
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index 723abc6..d0a2d98 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -413,7 +413,6 @@ function theme_file_widget_multiple($variables) {
     );
   }
 
-  drupal_add_tabledrag($table_id, 'order', 'sibling', $weight_class);
 
   $build = array(
     '#theme' => 'table',
@@ -424,6 +423,8 @@ function theme_file_widget_multiple($variables) {
     ),
   );
 
+  drupal_attach_tabledrag($build, array($table_id, 'order', 'sibling', $weight_class));
+
   $output = empty($rows) ? '' : drupal_render($build);
   $output .= drupal_render_children($element);
   return $output;
diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index b8f9c96..a77fb5d 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -59,7 +59,7 @@ function theme_image_style_effects($variables) {
     '#rows' => $rows,
     '#attributes' => array('id' => 'image-style-effects'),
   );
-  drupal_add_tabledrag('image-style-effects', 'order', 'sibling', 'image-effect-order-weight');
+  drupal_attach_tabledrag($table, array('image-style-effects', 'order', 'sibling', 'image-effect-order-weight'));
   return drupal_render($table);
 }
 
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index f62b933..612ba82 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -219,12 +219,13 @@ function theme_language_negotiation_configure_form($variables) {
       '#rows' => $rows,
       '#attributes' => array('id' => "language-negotiation-methods-$type"),
     );
+
+    drupal_attach_tabledrag($build, array("language-negotiation-methods-$type", 'order', 'sibling', "language-method-weight-$type"));
+
     $table  = drupal_render($form[$type]['configurable']);
     $table .= drupal_render($build);
     $table .= drupal_render_children($form[$type]);
 
-    drupal_add_tabledrag("language-negotiation-methods-$type", 'order', 'sibling', "language-method-weight-$type");
-
     $output .= '<div class="form-item table-language-group table-' . $type . '-wrapper">' . $title . $description . $table . '</div>';
   }
 
diff --git a/core/modules/menu/menu.admin.inc b/core/modules/menu/menu.admin.inc
index 2fe9455..768ebd5 100644
--- a/core/modules/menu/menu.admin.inc
+++ b/core/modules/menu/menu.admin.inc
@@ -17,9 +17,6 @@
 function theme_menu_overview_form($variables) {
   $form = $variables['form'];
 
-  drupal_add_tabledrag('menu-overview', 'match', 'parent', 'menu-plid', 'menu-plid', 'menu-mlid', TRUE, MENU_MAX_DEPTH - 1);
-  drupal_add_tabledrag('menu-overview', 'order', 'sibling', 'menu-weight');
-
   $header = array(
     t('Menu link'),
     array('data' => t('Enabled'), 'class' => array('checkbox')),
@@ -70,6 +67,9 @@ function theme_menu_overview_form($variables) {
     ),
   );
 
+  drupal_attach_tabledrag($table, array('menu-overview', 'match', 'parent', 'menu-plid', 'menu-plid', 'menu-mlid', TRUE, MENU_MAX_DEPTH - 1));
+  drupal_attach_tabledrag($table, array('menu-overview', 'order', 'sibling', 'menu-weight'));
+
   $output .= drupal_render($form['inline_actions']);
   $output .= drupal_render($table);
   $output .= drupal_render_children($form);
diff --git a/core/modules/views_ui/views_ui.theme.inc b/core/modules/views_ui/views_ui.theme.inc
index 38a8fe4..96d1865 100644
--- a/core/modules/views_ui/views_ui.theme.inc
+++ b/core/modules/views_ui/views_ui.theme.inc
@@ -207,7 +207,7 @@ function theme_views_ui_build_group_filter_form($variables) {
       'id' => 'views-filter-groups',
     ),
   );
-  drupal_add_tabledrag('views-filter-groups', 'order', 'sibling', 'weight');
+  drupal_attach_tabledrag($table, array('views-filter-groups', 'order', 'sibling', 'weight'));
   $render_form = drupal_render_children($form);
   return $output . $render_form . drupal_render($table) . drupal_render($form['add_group']) . $more;
 }
@@ -226,7 +226,7 @@ function theme_views_ui_rearrange_filter_form(&$variables) {
     if ($group_id !== 'ungroupable') {
       // Set up tabledrag so that it changes the group dropdown when rows are
       // dragged between groups.
-      drupal_add_tabledrag('views-rearrange-filters', 'match', 'sibling', 'views-group-select', 'views-group-select-' . $group_id);
+      drupal_attach_tabledrag($form['override'], array('views-rearrange-filters', 'match', 'sibling', 'views-group-select', 'views-group-select-' . $group_id));
 
       // Title row, spanning all columns.
       $row = array();
@@ -286,7 +286,6 @@ function theme_views_ui_rearrange_filter_form(&$variables) {
   }
 
   if (!empty($ungroupable_rows)) {
-    drupal_add_tabledrag('views-rearrange-filters-ungroupable', 'order', 'sibling', 'weight');
     $header = array(t('Ungroupable filters'), t('Weight'), array('class' => array('views-hide-label'), 'data' => t('Group')), array('class' => array('views-hide-label'), 'data' => t('Remove')));
     $table = array(
       '#theme' => 'table',
@@ -297,11 +296,11 @@ function theme_views_ui_rearrange_filter_form(&$variables) {
         'class' => array('arrange'),
       ),
     );
+    drupal_attach_tabledrag($table, array('views-rearrange-filters-ungroupable', 'order', 'sibling', 'weight'));
     $output .= drupal_render($table);
   }
 
   // Set up tabledrag so that the weights are changed when rows are dragged.
-  drupal_add_tabledrag('views-rearrange-filters', 'order', 'sibling', 'weight');
   $table = array(
     '#theme' => 'table',
     '#rows' => $rows,
@@ -310,6 +309,7 @@ function theme_views_ui_rearrange_filter_form(&$variables) {
       'class' => array('arrange'),
     ),
   );
+  drupal_add_tabledrag($table, array('views-rearrange-filters', 'order', 'sibling', 'weight'));
   $output .= drupal_render($table);
   $output .= '</div>';
 
