? .settings
Index: misc/tabledrag.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/tabledrag.js,v
retrieving revision 1.38
diff -u -p -r1.38 tabledrag.js
--- misc/tabledrag.js	18 May 2010 06:46:45 -0000	1.38
+++ misc/tabledrag.js	7 Jun 2010 14:17:45 -0000
@@ -451,7 +451,7 @@ Drupal.tableDrag.prototype.dropRow = fun
 
       self.rowObject.markChanged();
       if (self.changed == false) {
-        $(Drupal.theme('tableDragChangedWarning')).insertBefore(self.table).hide().fadeIn('slow');
+        self.rowObject.addChangedWarning();
         self.changed = true;
       }
     }
@@ -1056,6 +1056,10 @@ Drupal.tableDrag.prototype.row.prototype
   }
 };
 
+Drupal.tableDrag.prototype.row.prototype.addChangedWarning = function () {
+  $(Drupal.theme('tableDragChangedWarning')).insertBefore(this.table).hide().fadeIn('slow');
+}
+
 /**
  * Stub function. Allows a custom handler when a row is indented.
  */
Index: modules/field_ui/field_ui-display-overview-table.tpl.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui-display-overview-table.tpl.php,v
retrieving revision 1.2
diff -u -p -r1.2 field_ui-display-overview-table.tpl.php
--- modules/field_ui/field_ui-display-overview-table.tpl.php	26 May 2010 07:49:52 -0000	1.2
+++ modules/field_ui/field_ui-display-overview-table.tpl.php	7 Jun 2010 14:17:45 -0000
@@ -16,35 +16,54 @@
  */
 ?>
 <?php if ($rows): ?>
+<div id="field-display-overview-wrapper">
+  <?php if ($changed_warning): ?>
+    <div id="field-settings-changed-warning" class="warning"><span class="warning tabledrag-changed">*</span>&nbsp;<?php print t('Changes made in this table will not be saved until the form is submitted.') ?></div>
+  <?php endif; ?>
   <table id="field-display-overview" class="field-display-overview sticky-enabled">
     <thead>
       <tr>
         <th><?php print t('Field'); ?></th>
         <th><?php print t('Weight'); ?></th>
         <th><?php print t('Label'); ?></th>
-        <th><?php print t('Format'); ?></th>
+        <th colspan="3"><?php print t('Format'); ?></th>
       </tr>
     </thead>
     <tbody>
       <tr class="region-message region-visible-message <?php print empty($rows['visible']) ? 'region-empty' : 'region-populated'; ?>">
-        <td colspan="4"><em><?php print t('No field is displayed'); ?></em></td>
+        <td colspan="5"><em><?php print t('No field is displayed'); ?></em></td>
       </tr>
       <?php
       $count = 0;
       foreach ($rows['visible'] as $row): ?>
-        <tr class="<?php print $count % 2 == 0 ? 'odd' : 'even'; ?> <?php print $row->class ?>">
+        <tr id="<?php print $row->id; ?>" class="<?php print $count % 2 == 0 ? 'odd' : 'even'; ?> <?php print $row->class ?>">
           <td><span class="<?php print $row->label_class; ?>"><?php print $row->human_name; ?></span></td>
           <td><?php print $row->weight . $row->hidden_name; ?></td>
           <td><?php if (isset($row->label)) print $row->label; ?></td>
-          <td><?php print $row->type; ?></td>
+          <?php if (isset($row->settings_edit_form)) : ?>
+            <td colspan="3">
+              <?php print $row->type; ?>
+              <?php print $row->settings_edit_form; ?>
+            </td>
+          <?php else :?>
+            <td>
+              <?php print $row->type; ?>
+            </td>
+            <td class="field-formatter-summary-cell">
+              <?php print $row->settings_summary; ?>
+            </td>
+            <td>
+              <?php print $row->settings_edit; ?>
+            </td>
+          <?php endif; ?>
         </tr>
         <?php $count++;
       endforeach; ?>
       <tr class="region-title region-title-hidden">
-        <td colspan="4"><?php print t('Hidden'); ?></td>
+        <td colspan="5"><?php print t('Hidden'); ?></td>
       </tr>
       <tr class="region-message region-hidden-message <?php print empty($rows['hidden']) ? 'region-empty' : 'region-populated'; ?>">
-        <td colspan="4"><em><?php print t('No field is hidden'); ?></em></td>
+        <td colspan="5"><em><?php print t('No field is hidden'); ?></em></td>
       </tr>
       <?php foreach ($rows['hidden'] as $row): ?>
         <tr class="<?php print $count % 2 == 0 ? 'odd' : 'even'; ?> <?php print $row->class ?>">
@@ -52,9 +71,16 @@
           <td><?php print $row->weight . $row->hidden_name; ?></td>
           <td><?php if (isset($row->label)) print $row->label; ?></td>
           <td><?php print $row->type; ?></td>
+          <td class="field-formatter-summary-cell">
+            <?php print $row->settings_summary; ?>
+          </td>
+          <td>
+            <?php print $row->settings_edit; ?>
+          </td>
         </tr>
         <?php $count++;
       endforeach; ?>
     </tbody>
   </table>
+</div>
 <?php endif; ?>
Index: modules/field_ui/field_ui.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.admin.inc,v
retrieving revision 1.52
diff -u -p -r1.52 field_ui.admin.inc
--- modules/field_ui/field_ui.admin.inc	31 May 2010 18:15:20 -0000	1.52
+++ modules/field_ui/field_ui.admin.inc	7 Jun 2010 14:17:45 -0000
@@ -588,9 +588,28 @@ function field_ui_display_overview_form(
     return $form;
   }
 
+  $form_state += array(
+    'formatter_settings_edit' => NULL,
+    'changed_warning' => FALSE,
+    'dragged_rows' => array(),
+  );
+
+  // Track dragged rows.
+  if (!empty($form_state['values']['dragged_rows'])) {
+    $dragged_rows = explode('|', $form_state['values']['dragged_rows']);
+    $form_state['dragged_rows'] = array_unique($dragged_rows);
+  }
+
+  // Preserve tabledrag's warning message if present.
+  if ($form_state['dragged_rows']) {
+    $form_state['changed_warning'] = TRUE;
+  }
+  $changed_asterisk = '<span class="warning tabledrag-changed">*</span>';
+
   $table = array(
     '#theme' => 'field_ui_display_overview_table',
     '#field_rows' => array(),
+    '#changed_warning' => $form_state['changed_warning'],
     '#tree' => TRUE,
   );
 
@@ -606,9 +625,9 @@ function field_ui_display_overview_form(
 
   foreach ($instances as $name => $instance) {
     $display = $instance['display'][$view_mode];
-
+    $changed = in_array($name, $form_state['dragged_rows']) ? $changed_asterisk : '';
     $table[$name]['human_name'] = array(
-      '#markup' => check_plain($instance['label']),
+      '#markup' => check_plain($instance['label']) . $changed,
     );
     $table[$name]['weight'] = array(
       '#type' => 'textfield',
@@ -626,13 +645,121 @@ function field_ui_display_overview_form(
     );
     $field = field_info_field($instance['field_name']);
 
+    // The handling of the 'hidden' region in field_ui.js relies on the
+    // 'formatter type' select, so it is present in all cases, and hidden with
+    // CSS when the row is in 'edit settings' mode.
     $formatter_options = field_ui_formatter_options($field['type']);
     $formatter_options['hidden'] = t('<Hidden>');
     $table[$name]['type'] = array(
       '#type' => 'select',
       '#options' => $formatter_options,
       '#default_value' => $display['type'],
+      '#ajax' => array(
+        'callback' => 'field_ui_formatter_settings_js',
+        'wrapper' => 'field-display-overview-wrapper',
+        'effect' => 'fade',
+      ),
+      '#field_name' => $name,
+      '#op' => 'change_format',
     );
+    // Formatter settings.
+
+    // Check the currently selected formatter, and merge persisted values for
+    // formatter settings.
+    $settings_changed = FALSE;
+    if (isset($form_state['values']['settings'][$name]['type'])) {
+      $formatter_type = $form_state['values']['settings'][$name]['type'];
+    }
+    else {
+      $formatter_type = $display['type'];
+    }
+    if (isset($form_state['formatter_settings'][$name])) {
+      $settings = $form_state['formatter_settings'][$name];
+      $settings_changed = TRUE;
+    }
+    else {
+      $settings = $display['settings'];
+    }
+    $settings += field_info_formatter_settings($formatter_type);
+
+    $instance['display'][$view_mode]['type'] = $formatter_type;
+    $formatter = field_info_formatter_types($formatter_type);
+    $instance['display'][$view_mode]['module'] = $formatter['module'];
+    $instance['display'][$view_mode]['settings'] = $settings;
+
+    // Base button element for the various formatter settings actions.
+    $base_button = array(
+      '#submit' => array('field_ui_formatter_settings_submit'),
+      '#ajax' => array(
+        'callback' => 'field_ui_formatter_settings_js',
+        'wrapper' => 'field-display-overview-wrapper',
+        'effect' => 'fade',
+      ),
+      '#field_name' => $name,
+    );
+
+    if ($form_state['formatter_settings_edit'] == $name) {
+      // We are currently editing this field's formatter settings. Display the
+      // settings form and submit buttons.
+      $table[$name]['settings_edit_form'] = array();
+      $additions = module_invoke($formatter['module'], 'field_formatter_settings_form', $field, $instance, $view_mode);
+      if (is_array($additions)) {
+        $table[$name]['settings_edit_form'] = array(
+          '#type' => 'container',
+          '#attributes' => array('class' => array('field-formatter-settings-edit-form')),
+        );
+        $table[$name]['settings_edit_form']['label'] = array(
+          '#markup' => t('Format settings:') . ' <span class="formatter-name">' . $formatter['label'] . '</span>',
+        );
+        $table[$name]['settings_edit_form']['settings'] = $additions;
+        $table[$name]['settings_edit_form']['actions'] = array('#type' => 'actions');
+        $table[$name]['settings_edit_form']['actions']['save_settings'] = $base_button + array(
+          '#type' => 'submit',
+          '#name' => $name . '_formatter_settings_update',
+          '#value' => t('Update'),
+          '#op' => 'update',
+        );
+        $table[$name]['settings_edit_form']['actions']['cancel_settings'] = $base_button + array(
+          '#type' => 'submit',
+          '#name' => $name . '_formatter_settings_cancel',
+          '#value' => t('Cancel'),
+          '#op' => 'cancel',
+          // Do not check errors for the 'Cancel' button.
+          '#limit_validation_errors' => array(),
+        );
+        $table[$name]['#settings_editing'] = TRUE;
+        // When formatter is changed, cancel the currently edited settings. The
+        // select 'formatter type' input is hidden in editing mode, so this only
+        // happens is the row is dragged into the 'hidden' section.
+        $table[$name]['type']['#ajax']['trigger_as'] = array('name' => $name . '_formatter_settings_cancel');
+      }
+    }
+    else {
+      // Display a summary of the current formatter settings.
+      $summary = module_invoke($formatter['module'], 'field_formatter_settings_summary', $field, $instance, $view_mode);
+      $table[$name]['settings_summary'] = array();
+      $table[$name]['settings_edit'] = array();
+      if ($summary) {
+        $table[$name]['settings_summary'] = array(
+          '#markup' => '<div class="field-formatter-summary">' . $summary . '</div>',
+        );
+        $table[$name]['settings_edit'] = $base_button + array(
+          '#type' => 'image_button',
+          '#name' => $name . '_formatter_settings_edit',
+          '#src' => 'misc/configure.png',
+          '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')),
+          '#op' => 'edit',
+          // Do not check errors for the 'Edit' button.
+          '#limit_validation_errors' => array(),
+          '#prefix' => '<div class="field-formatter-settings-edit-wrapper">',
+          '#suffix' => '</div>',
+        );
+        if ($settings_changed) {
+          $table[$name]['#settings_changed'] = TRUE;
+          $table[$name]['settings_summary']['#prefix'] = '<span class="warning tabledrag-changed">*</span>&nbsp;';
+        }
+      }
+    }
     $table['#field_rows'][] = $name;
 
     // Collect default formatters for the JS script.
@@ -643,8 +770,9 @@ function field_ui_display_overview_form(
   // Non-field elements.
   foreach ($extra_fields as $name => $extra_field) {
     $display = $extra_field['display'][$view_mode];
+    $changed = in_array($name, $form_state['dragged_rows']) ? $changed_asterisk : '';
     $table[$name]['human_name'] = array(
-      '#markup' => check_plain($extra_field['label']),
+      '#markup' => check_plain($extra_field['label']) . $changed,
     );
     $table[$name]['weight'] = array(
       '#type' => 'textfield',
@@ -660,8 +788,11 @@ function field_ui_display_overview_form(
       '#options' => $extra_visibility_options,
       '#default_value' => $display['visible'] ? 'visible' : 'hidden',
     );
+    $table[$name]['settings_summary'] = array();
+    $table[$name]['settings_edit'] = array();
     $table['#field_rows'][] = $name;
   }
+
   $form['settings'] = $table;
 
   // Custom display settings.
@@ -693,16 +824,82 @@ function field_ui_display_overview_form(
     );
   }
 
+  // Hidden element used by field_ui.js to track dragged rows.
+  $form['dragged_rows'] = array('#type' => 'hidden');
+
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
 
   $form['#attached']['js'][] = drupal_get_path('module', 'field_ui') . '/field_ui.js';
   $form['#attached']['css'][] = drupal_get_path('module', 'field_ui') . '/field_ui.css';
+
   drupal_add_js(array('fieldDefaultFormatters' => $default_formatters), 'setting');
 
   return $form;
 }
 
+
+/**
+ * Form submit handler for the formatter settings buttons.
+ */
+function field_ui_formatter_settings_submit($form, &$form_state) {
+  $trigger = $form_state['triggering_element'];
+  $field_name = $trigger['#field_name'];
+  $op = $trigger['#op'];
+
+  switch ($op) {
+    case 'edit':
+      // Store the field whose settings are currently being edited.
+      $form_state['formatter_settings_edit'] = $field_name;
+      break;
+
+    case 'update':
+      // Store the saved settings.
+      $values = $form_state['values']['settings'][$field_name]['settings_edit_form']['settings'];
+      $form_state['formatter_settings'][$field_name] = $values;
+      $form_state['changed_warning'] = TRUE;
+      // Fall-through to the 'cancel' case.
+    case 'cancel':
+      // Unset the field as being currently edited.
+      $form_state['formatter_settings_edit'] = NULL;
+      break;
+  }
+
+  $form_state['rebuild'] = TRUE;
+}
+
+/**
+ * AJAX handler for the formatter settings buttons.
+ */
+function field_ui_formatter_settings_js($form, &$form_state) {
+  $trigger = $form_state['triggering_element'];
+  $field_name = $trigger['#field_name'];
+  $op = $trigger['#op'];
+
+  // Apply the AJAX effect to updated elements.
+  switch ($op) {
+    case 'change_format':
+      $updated = array('settings_summary');
+      break;
+
+    case 'edit':
+      $updated = array('settings_edit_form');
+      break;
+
+    case 'update':
+    case 'cancel':
+      $updated = array('type', 'settings_summary', 'settings_edit');
+      break;
+  }
+  foreach ($updated as $key) {
+    $element = &$form['settings'][$field_name][$key];
+    $element['#prefix'] = '<div class="ajax-new-content">' . (isset($element['#prefix']) ? $element['#prefix'] : '');
+    $element['#suffix'] = (isset($element['#suffix']) ? $element['#suffix'] : '') . '</div>';
+  }
+
+  return $form['settings'];
+}
+
 /**
  * Theme preprocess function for field_ui-display-overview-table.tpl.php.
  */
@@ -731,22 +928,24 @@ function template_preprocess_field_ui_di
 
       $row = new stdClass();
       foreach (element_children($element) as $child) {
-        if (array_key_exists('label', $element[$child])) {
-          $row->{$child} = new stdClass();
-          $row->{$child}->label = drupal_render($element[$child]['label']);
-          $row->{$child}->type = drupal_render($element[$child]['type']);
-        }
-        else {
-          $row->{$child} = drupal_render($element[$child]);
-        }
+        $row->{$child} = drupal_render($element[$child]);
       }
+      $row->settings_class = (!empty($element['#settings_class']) ? $element['#settings_class'] : '');
       $row->class = 'draggable';
+      if (isset($element['#settings_editing'])) {
+        $row->class .= ' field-formatter-settings-editing';
+      }
+      if (isset($element['#settings_changed'])) {
+        $row->class .= ' field-formatter-settings-changed';
+      }
       $row->label_class = 'label-field';
+      $row->id = 'row-' . strtr($key, '_', '-');
       $rows[$visibility][] = $row;
     }
   }
 
   $vars['rows'] = $rows;
+  $vars['changed_warning'] = $elements['#changed_warning'];
 }
 
 /**
@@ -761,7 +960,29 @@ function field_ui_display_overview_form_
   // Save data for 'regular' fields.
   foreach ($form['#fields'] as $field_name) {
     $instance = field_info_instance($entity_type, $field_name, $bundle);
-    $instance['display'][$view_mode] = $form_values['settings'][$field_name];
+    $values = $form_values['settings'][$field_name];
+    // Get formatter settings. They lie either directly in submitted form
+    // values (if the whole form was submitted while some formatter
+    // settings were being edited), or have been persisted in
+    // $form_state.
+    $settings = $instance['display'][$view_mode]['settings'];
+    if (isset($values['settings_edit_form']['settings'])) {
+      $settings = $values['settings_edit_form']['settings'];
+    }
+    elseif (isset($form_state['formatter_settings'][$field_name])) {
+      $settings = $form_state['formatter_settings'][$field_name];
+    }
+
+    // Only save settings actually used by the selected formatter.
+    $default_settings = field_info_formatter_settings($values['type']);
+    $settings = array_intersect_key($settings, $default_settings);
+
+    $instance['display'][$view_mode] = array(
+      'label' => $values['label'],
+      'type' => $values['type'],
+      'weight' => $values['weight'],
+      'settings' => $settings,
+    );
     field_update_instance($instance);
   }
 
Index: modules/field_ui/field_ui.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.api.php,v
retrieving revision 1.6
diff -u -p -r1.6 field_ui.api.php
--- modules/field_ui/field_ui.api.php	4 May 2010 16:11:08 -0000	1.6
+++ modules/field_ui/field_ui.api.php	7 Jun 2010 14:17:45 -0000
@@ -131,6 +131,63 @@ function hook_field_widget_settings_form
   return $form;
 }
 
+
+/**
+ * Returns a form for a formatter's settings.
+ *
+ * @param $field
+ *   The field structure being configured.
+ * @param $instance
+ *   The instance structure being configured.
+ *
+ * @return
+ *   The form definition for the formatter settings.
+ */
+function hook_field_formatter_settings_form($field, $instance, $view_mode) {
+  $display = $instance['display'][$view_mode];
+  $settings = $display['settings'];
+
+  $form = array();
+
+  if ($display['type'] == 'text_trimmed' || $display['type'] == 'text_summary_or_trimmed') {
+    $form['trim_length'] = array(
+      '#title' => t('Length'),
+      '#type' => 'textfield',
+      '#size' => 20,
+      '#default_value' => $settings['trim_length'],
+      '#element_validate' => array('_element_validate_integer_positive'),
+      '#required' => TRUE,
+    );
+  }
+
+  return $form;
+
+}
+
+/**
+ * Returns a short summary for the current formatter settings of an instance.
+ *
+ * @param $field
+ *   The field structure being configured.
+ * @param $instance
+ *   The instance structure being configured.
+ *
+ * @return
+ *   A string containing a short summary of the formatter settings.
+ */
+function hook_field_formatter_settings_summary($field, $instance, $view_mode) {
+  $display = $instance['display'][$view_mode];
+  $settings = $display['settings'];
+
+  $summary = '';
+
+  if ($display['type'] == 'text_trimmed' || $display['type'] == 'text_summary_or_trimmed') {
+    $summary = t('Length: @chars chars', array('@chars' => $settings['trim_length']));
+  }
+
+  return $summary;
+}
+
 /**
  * Provide information on view mode tabs for an entity type.
  *
Index: modules/field_ui/field_ui.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.css,v
retrieving revision 1.2
diff -u -p -r1.2 field_ui.css
--- modules/field_ui/field_ui.css	23 May 2010 19:10:23 -0000	1.2
+++ modules/field_ui/field_ui.css	7 Jun 2010 14:17:45 -0000
@@ -16,10 +16,54 @@
   padding-bottom: .5em;
 }
 
-/* Manage display */
+/* 'Manage display' overview */
 .field-display-overview tr.region-title td {
   font-weight: bold;
 }
 .field-display-overview tr.region-populated {
   display: none;
 }
+.field-display-overview .field-formatter-summary-cell {
+  font-size: 11px;
+  line-height: 13px;
+}
+.field-display-overview .field-formatter-summary {
+  float: left;
+}
+.field-display-overview td.field-formatter-summary-cell span.warning {
+  display: block;
+  float: left;
+  margin-right: .5em;
+}
+.field-display-overview .field-formatter-settings-edit-wrapper {
+  float: right;
+}
+.field-display-overview .field-formatter-settings-edit {
+  float: right;
+  margin: -3px 0;
+  padding: 1px 8px;
+}
+.field-display-overview tr.field-formatter-settings-changed {
+  background: #FFFFBB;
+}
+.field-display-overview tr.drag {
+  background: #FFEE77;
+}
+.field-display-overview tr.field-formatter-settings-editing {
+  background: #D5E9F2;
+}
+.field-display-overview tr.field-formatter-settings-editing td {
+  vertical-align: top;
+}
+.field-display-overview tr.field-formatter-settings-editing .field-formatter-type {
+  display: none;
+}
+.field-display-overview .field-formatter-settings-edit-form  .formatter-name{
+  font-weight: bold;
+}
+.field-display-overview .field-formatter-settings-edit-form .form-item {
+  margin: 10px 0;
+}
+.field-display-overview .field-formatter-settings-edit-form .form-submit {
+  margin-bottom: 0;
+}
Index: modules/field_ui/field_ui.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.js,v
retrieving revision 1.3
diff -u -p -r1.3 field_ui.js
--- modules/field_ui/field_ui.js	23 May 2010 19:10:23 -0000	1.3
+++ modules/field_ui/field_ui.js	7 Jun 2010 14:17:45 -0000
@@ -102,15 +102,37 @@ Drupal.behaviors.fieldManageDisplayDrag 
       checkEmptyRegions(this.table, this);
     };
 
+    // The AJAX behavior on formatter settings updates the whole table, so we
+    // make sure the 'Save' warning is displayed only once on the page.
+    tableDrag.row.prototype.addChangedWarning = function () {
+      if (!$('#field-settings-changed-warning').length) {
+        $(Drupal.theme('tableDragChangedWarning')).insertBefore(this.table).hide().fadeIn('slow');
+      }
+    }
+
+    // Custom message with an HTML id so that addChangedWarning() can avoid
+    // duplicates.
+    Drupal.theme.prototype.tableDragChangedWarning = function () {
+      return '<div id="field-settings-changed-warning" class="warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('Changes made in this table will not be saved until the form is submitted.') + '</div>';
+    };
+
     // Add a handler to update the formatter selector when a row is dropped in
     // or out of the 'Hidden' section.
     tableDrag.onDrop = function () {
       var dragObject = this;
+      var row = dragObject.rowObject.element;
       var regionRow = $(dragObject.rowObject.element).prevAll('tr.region-message').get(0);
       var visibility = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
 
+      // Allow the server to track dragged rows and preserve 'changed' markers
+      // and the warning message through AJAX refreshes of the table.
+      var $input = $('input[name=dragged_rows]');
+      var dragged = $input.val();
+      dragged += (dragged ? '|' : '') + row.id.replace(new RegExp('^row-'), '').replace('-', '_');
+      $input.val(dragged);
+
       // Update the 'format' selector if the visibility changed.
-      var $select = $('select.field-formatter-type', dragObject.rowObject.element);
+      var $select = $('select.field-formatter-type', row);
       var oldVisibility = $select[0].className.replace(/([^ ]+[ ]+)*field-display-([^ ]+)([ ]+[^ ]+)*/, '$2');
       if (visibility != oldVisibility) {
         $select.removeClass('field-display-' + oldVisibility).addClass('field-display-' + visibility);
@@ -134,6 +156,8 @@ Drupal.behaviors.fieldManageDisplayDrag 
             var value = 'hidden';
           }
           $select.val(value);
+          // Fire AJAX update of formatter settings.
+          $select.change();
         }
         $select.removeData('noUpdate');
       }
