=== added file 'elements.js'
--- /dev/null	
+++ elements.js	
@@ -0,0 +1,22 @@
+if (Drupal.jsEnabled) {
+  $(document).ready(function() {
+    $('div.form-comboselect').each(function() {
+      var defaults = $(this).find('select');
+      var custom = $(this).find('input');
+      if (defaults.val() == 'other') {
+        custom.show();
+      }
+      else {
+        custom.hide();
+      }
+      defaults.click(function() {
+        if (defaults.val() == 'other') {
+          custom.show();
+        }
+        else {
+          custom.hide();
+        }
+      });
+    });
+  });
+}
=== modified file 'elements.module'
--- elements.module	
+++ elements.module	
@@ -12,6 +12,13 @@
 function elements_elements() {
   $types['tableselect'] = array('#input' => TRUE, '#advanced_select' => TRUE, '#multiple' => TRUE, '#process' => array('_elements_expand_tableselect' => array()));
   $types['imagebutton'] = array('#input' => TRUE, '#button_type' => 'submit',);
+  $types['comboselect'] = array(
+    '#input' => TRUE,
+    '#process' => array('_elements_expand_comboselect' => array()),
+    '#validate' => array('_elements_comboselect_validate' => array()),
+    '#autocomplete_path' => FALSE,
+    '#other' => t('Other...')
+  );
   return $types;
 }
 
@@ -82,4 +89,63 @@ function theme_tableselect($element) {
   $first_col = $element['#advanced_select'] ? array(theme('table_select_header_cell')) : array('');
   $header = array_merge($first_col, $element['#header']);
   return theme('table', $header, $rows);
+}
+
+function _elements_expand_comboselect($element) {
+  $element['#tree'] = TRUE;
+  $element['default'] = array('#type' => 'select');
+  if (!$element['#required']) {
+    $element['default']['#options']['none'] = t('-- Please select --');
+  }
+  $i = 0;
+  foreach ($element['#default_options'] as $option) {
+    $element['default']['#options']["option_$i"] = $option;
+    if ($option == $element['#default_value']) {
+      $element['default']['#default_value'] = "option_$i";
+    }
+    ++$i;
+  }
+  $element['default']['#options']['other'] = $element['#other'];
+  $element['custom'] = array(
+    '#type' => 'textfield',
+    '#autocomplete_path' => $element['#autocomplete_path'],
+  );
+  if (isset($element['#default_value']) && !isset($element['default']['#default_value'])) {
+    $element['default']['#default_value'] = 'other';
+    $element['custom']['#default_value'] = $element['#default_value'];
+  }
+  return $element;
+}
+
+function _elements_comboselect_validate($element) {
+  switch ($element['#value']['default']) {
+    case 'none':
+      $value = '';
+      break;
+
+    case 'other':
+      $value = $element['#value']['custom'];
+      break;
+
+    default:
+      $value = $element['default']['#options'][$element['#value']['default']];
+      break;
+  }
+  if ($element['#required'] && $value === '') {
+    form_error($element, t('%name field is required.', array('%name' => $element['#title'])));
+  }
+  else {
+    form_set_value($element, $value);
+  }
+}
+
+function theme_comboselect($element) {
+  drupal_add_js(drupal_get_path('module', 'elements') .'/elements.js');
+  $output = '<div class="form-comboselect container-inline">';
+  unset($element['default']['#printed']);
+  $output .= drupal_render($element['default']);
+  unset($element['custom']['#printed']);
+  $output .= drupal_render($element['custom']);
+  $output .= '</div>';
+  return theme('form_element', $element, $output);
 }
\ No newline at end of file
