diff --git a/includes/common.inc b/includes/common.inc
index 1a90a9e..1c22880 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -6233,6 +6233,9 @@ function drupal_common_theme() {
     'form' => array(
       'render element' => 'element',
     ),
+    'options' => array(
+      'render element' => 'element',
+    ),
     'textarea' => array(
       'render element' => 'element',
     ),
diff --git a/includes/form.inc b/includes/form.inc
index da2b7e2..06112b4 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -2898,6 +2898,465 @@ function theme_container($variables) {
 }
 
 /**
+ * Theme an options element.
+ *
+ * @param $variables
+ *
+ * @ingroup themeable
+ */
+function theme_options($variables) {
+  $element = $variables['element'];
+
+  $classes = array();
+  if (isset($element['#attributes']['class'])) {
+    $classes = $element['#attributes']['class'];
+  }
+
+  $classes[] = 'form-options';
+  $classes[] = 'options-key-type-'. $element['#key_type'];
+
+  if ($element['#key_type_toggled']) {
+    $classes[] = 'options-key-custom';
+  }
+
+  if (isset($element['#optgroups']) && $element['#optgroups']) {
+    $classes[] = 'options-optgroups';
+  }
+
+  if (isset($element['#multiple']) && $element['#multiple']) {
+    $classes[] = 'options-multiple';
+  }
+
+  $options = '';
+  $options .= drupal_render($element['options_field']);
+  if (isset($element['default_value_field'])) {
+    $options .= drupal_render($element['default_value_field']);
+  }
+
+  $settings = '';
+  if (isset($element['custom_keys'])) {
+    $settings .= drupal_render($element['custom_keys']);
+  }
+  if (isset($element['multiple'])) {
+    $settings .= drupal_render($element['multiple']);
+  }
+  if (isset($element['option_settings'])) {
+    $settings .= drupal_render($element['option_settings']);
+  }
+
+  $output = '';
+  $output .= '<div class="' . implode(' ', $classes) .'">';
+  $output .= theme('fieldset', array('element' => array(
+    '#title' => t('Options'),
+    '#collapsible' => FALSE,
+    '#children' => $options,
+    '#attributes' => array('class' => array('options')),
+  )));
+
+  if (!empty($settings)) {
+    $output .= theme('fieldset', array('element' => array(
+      '#title' => t('Option settings'),
+      '#collapsible' => FALSE,
+      '#children' => $settings,
+      '#attributes' => array('class' => array('option-settings')),
+    )));
+  }
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Logic function for form_options_expand(). Do not call directly.
+ *
+ * @see form_options_expand()
+ */
+function _form_options_expand($element) {
+  $element['#options'] = isset($element['#options']) ? $element['#options'] : array();
+  $element['#multiple'] = isset($element['#multiple']) ? $element['#multiple'] : FALSE;
+
+  $element['#tree'] = TRUE;
+  $element['#theme'] = 'options';
+
+  $element['#attached']['js'] = array(
+    'misc/tabledrag.js' => array('weight' => JS_LIBRARY + 5),
+    'misc/options-element.js' => array(),
+  );
+  $element['#attached']['css'] = array(
+    'misc/options-element.css',
+  );
+
+  // Add the key type toggle checkbox.
+  if (!isset($element['custom_keys']) && $element['#key_type'] != 'custom' && !empty($element['#key_type_toggle'])) {
+    $element['custom_keys'] = array(
+      '#title' => is_string($element['#key_type_toggle']) ? $element['#key_type_toggle'] : t('Customize keys'),
+      '#type' => 'checkbox',
+      '#default_value' => $element['#key_type_toggled'],
+      '#attributes' => array('class' => array('key-type-toggle')),
+      '#description' => t('Customizing the keys will allow you to save one value internally while showing a different option to the user.'),
+    );
+  }
+
+  // Add the multiple value toggle checkbox.
+  if (!isset($element['multiple']) && !empty($element['#multiple_toggle'])) {
+    $element['multiple'] = array(
+      '#title' => is_string($element['#multiple_toggle']) ? $element['#multiple_toggle'] : t('Allow multiple values'),
+      '#type' => 'checkbox',
+      '#default_value' => !empty($element['#multiple']),
+      '#attributes' => array('class' => array('multiple-toggle')),
+      '#description' => t('Multiple values will let users select multiple items in this list.'),
+    );
+  }
+
+  // Add the main textarea for adding options.
+  if (!isset($element['options'])) {
+    $element['options_field'] = array(
+      '#type' => 'textarea',
+      '#resizable' => TRUE,
+      '#cols' => 60,
+      '#rows' => 5,
+      '#required' => isset($element['#required']) ? $element['#required'] : FALSE,
+      '#description' => t('List options one option per line.'),
+      '#attributes' => $element['#disabled'] ? array('readonly' => 'readonly') : array(),
+    );
+
+    // If validation fails, reload the user's text even if it's not valid.
+    if (isset($element['#value']['text'])) {
+      $element['options_field']['#value'] = $element['#value']['text'];
+    }
+    // Most of the time, we'll be converting the options array into the text.
+    else {
+      $element['options_field']['#value'] = isset($element['#options']) ? form_options_to_text($element['#options'], $element['#key_type']) : '';
+    }
+
+    if ($element['#key_type'] == 'mixed' || $element['#key_type'] == 'numeric' || $element['#key_type'] == 'custom') {
+      $element['options_field']['#description'] .= ' ' . t('Key-value pairs may be specified by separating each option with pipes, such as <em>key|value</em>.');
+    }
+    elseif ($element['#key_type_toggle']) {
+      $element['options_field']['#description'] .= ' ' . t('If the %toggle field is checked, key-value pairs may be specified by separating each option with pipes, such as <em>key|value</em>.', array('%toggle' => $element['custom_keys']['#title']));
+    }
+    if ($element['#key_type'] == 'numeric') {
+      $element['options_field']['#description'] .= ' ' . t('This field requires all specified keys to be integers.');
+    }
+  }
+
+  // Add the field for storing default values.
+  if ($element['#default_value'] !== FALSE && !isset($element['default_value_field'])) {
+    $element['default_value_field'] = array(
+      '#title' => t('Default value'),
+      '#type' => 'textfield',
+      '#size' => 60,
+      '#value' => isset($element['#default_value']) ? ($element['#multiple'] ? implode(', ', (array) $element['#default_value']) : $element['#default_value']) : '',
+      '#description' => t('Specify the keys that should be selected by default.'),
+    );
+    if ($element['#multiple']) {
+      $element['default_value_field']['#description'] .= ' ' . t('Multiple default values may be specified by separating keys with commas.');
+    }
+  }
+
+  // Remove properties that will confuse the FAPI.
+  unset($element['#options']);
+  $element['#required'] = FALSE;
+
+  return $element;
+}
+
+/**
+ * Logic function for form_options_validate(). Do not call directly.
+ *
+ * @see form_options_validate()
+ */
+function _form_options_validate($element, &$form_state) {
+  // Convert text to an array of options.
+  $duplicates = array();
+  $options = form_options_from_text($element['#value']['options_text'], $element['#key_type'], empty($element['#optgroups']), $duplicates);
+
+  // Check if a key is used multiple times.
+  if (count($duplicates) == 1) {
+    form_error($element, t('The key %key has been used multiple times. Each key must be unique to display properly.', array('%key' => reset($duplicates))));
+  }
+  elseif (!empty($duplicates)) {
+    array_walk($duplicates, 'check_plain');
+    $duplicate_list = theme('item_list', array('items' => $duplicates));
+    form_error($element, t('The following keys have been used multiple times. Each key must be unique to display properly.') . $duplicate_list);
+  }
+
+  // Add the list of duplicates to the page so that we can highlight the fields.
+  if (!empty($duplicates)) {
+    drupal_add_js(array('optionsElement' => array('errors' => drupal_map_assoc($duplicates))), 'setting');
+  }
+
+  // Check if no options are specified.
+  if (empty($options) && $element['#required']) {
+    form_error($element, t('At least one option must be specified.'));
+  }
+
+  // Check for numeric keys if needed.
+  if ($element['#key_type'] == 'numeric') {
+    foreach ($options as $key => $value) {
+      if (!is_int($key)) {
+        form_error($element, t('The keys for the %title field must be integers.', array('%title' => $element['#title'])));
+        break;
+      }
+    }
+  }
+
+  // Check that the limit of options has not been exceeded.
+  if (!empty($element['#limit'])) {
+    $count = 0;
+    foreach ($options as $value) {
+      if (is_array($value)) {
+        $count += count($value);
+      }
+      else {
+        $count++;
+      }
+    }
+    if ($count > $element['#limit']) {
+      form_error($element, t('The %title field supports a maximum of @count options. Please reduce the number of options.', array('%title' => $element['#title'], '@count' => $element['#limit'])));
+    }
+  }
+}
+
+/**
+ * Logic function for form_type_options_value(). Do not call directly.
+ *
+ * @see form_type_options_value()
+ */
+function _form_type_options_value(&$element, $edit = FALSE) {
+  if ($edit === FALSE) {
+     return array(
+       'options' => isset($element['#options']) ? $element['#options'] : array(),
+       'default_value' => isset($element['#default_value']) ? $element['#default_value'] : '',
+     );
+  }
+  else {
+    // Convert text to an array of options.
+    $duplicates = array();
+    $options = form_options_from_text($edit['options_field'], $element['#key_type'], empty($element['#optgroups']), $duplicates);
+
+    // Convert default value.
+    if (isset($edit['default_value_field'])) {
+      if (!empty($edit['multiple'])) {
+        $default_value = array();
+        $default_items = explode(',', $edit['default_value_field']);
+        foreach ($default_items as $key) {
+          $key = trim($key);
+          if ($value = _form_options_search($key, $options)) {
+            $default_value[] = $value;
+          }
+        }
+      }
+      else {
+        $default_value = _form_options_search(trim($edit['default_value_field']), $options);
+      }
+    }
+
+    return array(
+      'options' => $options,
+      'default_value' => $default_value,
+      'options_text' => $edit['options_field'],
+      'default_value_text' => $edit['default_value_field'],
+    );
+  }
+}
+
+/**
+ * Logic function for form_options_to_text(). Do not call directly.
+ *
+ * @see form_options_to_text()
+ */
+function _form_options_to_text($options, $key_type) {
+  $output = '';
+  $previous_key = false;
+
+  foreach ($options as $key => $value) {
+    // Convert groups.
+    if (is_array($value)) {
+      $output .= '<' . $key . '>' . "\n";
+      foreach ($value as $subkey => $subvalue) {
+        $output .= (($key_type == 'mixed' || $key_type == 'numeric' || $key_type == 'custom') ? $subkey . '|' : '') . $subvalue . "\n";
+      }
+      $previous_key = $key;
+    }
+    // Typical key|value pairs.
+    else {
+      // Exit out of any groups.
+      if (isset($options[$previous_key]) && is_array($options[$previous_key])) {
+        $output .= "<>\n";
+      }
+      // Skip empty rows.
+      if ($options[$key] !== '') {
+        if ($key_type == 'mixed' || $key_type == 'numeric' || $key_type == 'custom') {
+          $output .= $key . '|' . $value . "\n";
+        }
+        else {
+          $output .= $value . "\n";
+        }
+      }
+      $previous_key = $key;
+    }
+  }
+
+  return $output;
+}
+
+/**
+ * Logic function for form_options_from_text(). Do not call directly.
+ *
+ * @see form_options_from_text()
+ */
+function _form_options_from_text($text, $key_type, $flat = FALSE, &$duplicates = array()) {
+  $keys = array();
+  $items = array();
+  $rows = array_filter(explode("\n", trim($text)));
+  $group = FALSE;
+  foreach ($rows as $row) {
+    $row = trim($row);
+    $matches = array();
+
+    // Check for a simple empty row.
+    if (empty($row)) {
+      continue;
+    }
+    // Check if this row is a group.
+    elseif (!$flat && preg_match('/^\<((([^>|]*)\|)?([^>]*))\>$/', $row, $matches)) {
+      if ($matches[1] === '') {
+        $group = FALSE;
+      }
+      else {
+        $group = $matches[4] ? $matches[4] : '';
+        $keys[] = $group;
+      }
+    }
+    // Check if this row is a key|value pair.
+    elseif (($key_type == 'mixed' || $key_type == 'custom' || $key_type == 'numeric') && preg_match('/^([^|]+)\|(.*)$/', $row, $matches)) {
+      $key = $matches[1];
+      $value = $matches[2];
+      $keys[] = $key;
+      $items[] = array(
+        'key' => $key,
+        'value' => $value,
+        'group' => $group,
+      );
+    }
+    // Set this this row as a straight value.
+    else {
+      $items[] = array(
+        'key' => NULL,
+        'value' => $row,
+        'group' => $group,
+      );
+    }
+  }
+
+  // Expand the list into a nested array, assign keys and check duplicates.
+  $options = array();
+  $new_key = 0;
+  foreach ($items as $item) {
+    // Assign a key if needed.
+    if ($key_type == 'none') {
+      $item['key'] = $new_key++;
+    }
+    elseif (!isset($item['key'])) {
+      while (in_array($new_key, $keys)) {
+        $new_key++;
+      }
+      $keys[] = $new_key;
+      $item['key'] = $new_key;
+    }
+
+    if ($item['group']) {
+      if (isset($options[$item['group']][$item['key']])) {
+        $duplicates[] = $item['key'];
+      }
+      $options[$item['group']][$item['key']] = $item['value'];
+    }
+    else {
+      if (isset($options[$item['key']])) {
+        $duplicates[] = $item['key'];
+      }
+      $options[$item['key']] = $item['value'];
+    }
+  }
+
+  return $options;
+}
+
+/**
+ * Recursive function for finding default value keys. Matches on keys or values.
+ */
+function _form_options_search($needle, $haystack) {
+  if (isset($haystack[$needle])) {
+    return $needle;
+  }
+  foreach ($haystack as $key => $value) {
+    if (is_array($value) && ($return = _form_options_search($needle, $value))) {
+      return $return;
+    }
+    if ($value == $needle) {
+      return $key;
+    }
+  }
+}
+
+/**
+ * Expand the "options" form element type.
+ *
+ * The "options" type is simply an enhanced textarea that makes it easier to
+ * create key|value pairs and put items into optgroups.
+ */
+function form_options_expand($element) {
+  return _form_options_expand($element);
+}
+
+/**
+ * Validate the "options" form element type.
+ */
+function form_options_validate($element, &$form_state) {
+  _form_options_validate($element, $form_state);
+}
+
+/**
+ * This function adjusts the value of the element from a text value to an array.
+ */
+function form_type_options_value(&$element, $edit = FALSE) {
+  return _form_type_options_value($element, $edit);
+}
+
+/**
+ * Create a textual representation of options from an array.
+ *
+ * @param $options
+ *   An array of options used in a select list.
+ * @param $key_type
+ *   How key/value pairs should be interpreted. Available options:
+ *   - mixed
+ *   - numeric
+ *   - associative
+ *   - custom
+ *   - none
+ */
+function form_options_to_text($options, $key_type) {
+  return _form_options_to_text($options, $key_type);
+}
+
+/**
+ * Create an array representation of text option values.
+ *
+ * If the Key of the option is within < >, treat as an optgroup
+ * 
+ * <Group 1>
+ *   creates an optgroup with the label "Group 1"
+ * 
+ * <>
+ *   Exits the current group, allowing items to be inserted at the root element.
+ */
+function form_options_from_text($text, $key_type, $flat = FALSE, &$duplicates = array()) {
+  return _form_options_from_text($text, $key_type, $flat, $duplicates);
+}
+
+/**
  * Returns HTML for a table with radio buttons or checkboxes.
  *
  * An example of per-row options:
diff --git a/modules/field/modules/list/list.module b/modules/field/modules/list/list.module
index 4310ab4..44115d3 100644
--- a/modules/field/modules/list/list.module
+++ b/modules/field/modules/list/list.module
@@ -66,17 +66,19 @@ function list_field_info() {
  */
 function list_field_settings_form($field, $instance, $has_data) {
   $settings = $field['settings'];
-
   $form['allowed_values'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Allowed values list'),
-    '#default_value' => $settings['allowed_values'],
+    '#type' => 'options',
+    '#options' => isset( $settings['allowed_values']['options']) ? $settings['allowed_values']['options'] : NULL,
+    '#title' => t('Allowed values'),
+    '#default_value' => '',
     '#required' => FALSE,
-    '#rows' => 10,
     '#description' => '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label. The key is the value that will be stored in the database, and must be a %type value. The label is optional, and the key will be used as the label if no label is specified.', array('%type' => $field['type'] == 'list_text' ? t('text') : t('numeric'))) . '</p>',
     '#element_validate' => array('list_allowed_values_setting_validate'),
     '#list_field_type' => $field['type'],
     '#access' => empty($settings['allowed_values_function']),
+    '#key_type' => 'associative',
+    '#key_type_toggle' => t('Custom keys'),
+    '#key_type_toggled' => TRUE,
   );
 
   if ($field['type'] == 'list_boolean') {
@@ -231,6 +233,9 @@ function list_allowed_values($field) {
  */
 function list_extract_allowed_values($string_values, $position_keys = FALSE) {
   $values = array();
+  // @TODO
+  // Ugly ahead.
+  return $string_values = $string_values['options'];
 
   $list = explode("\n", $string_values);
   $list = array_map('trim', $list);
diff --git a/modules/system/system.module b/modules/system/system.module
index 839ec06..bea746e 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -435,6 +435,21 @@ function system_element_info() {
     '#theme' => 'file',
     '#theme_wrappers' => array('form_element'),
   );
+  $types['options'] = array(
+    '#input' => TRUE,
+    '#process' => array('form_options_expand'),
+    '#limit' => 100,
+    '#optgroups' => TRUE,
+    '#multiple' => FALSE,
+    '#options' => array(),
+    '#key_type' => 'mixed',
+    '#key_type_toggle' => NULL,
+    '#key_type_toggled' => FALSE,
+    '#element_validate' => array('form_options_validate'),
+    '#disabled' => FALSE,
+    '#theme' => 'options',
+    '#theme_wrappers' => array('form_element'),
+  );
   $types['tableselect'] = array(
     '#input' => TRUE,
     '#js_select' => TRUE,
@@ -1112,6 +1127,19 @@ function system_library() {
     ),
   );
 
+  // Options Element.
+  $libraries['options'] = array(
+    'title' => 'Options Element',
+    'website' => 'http://drupal.org/project/options_element',
+    'version' => '1.0',
+    'js' => array(
+      'misc/options-element.js' => array(),
+    ),
+    'css' => array(
+      'misc/options-element.css' => array(),
+    ),
+  );
+
   // Vertical Tabs.
   $libraries['vertical-tabs'] = array(
     'title' => 'Vertical Tabs',
