Index: select.inc
===================================================================
--- select.inc	(revision 13784)
+++ select.inc	(working copy)
@@ -81,6 +81,14 @@
     '#description' => t('Check this option if this component contains an e-mail address that should get a copy of the submission. Emails are sent individually so other emails will not be shown to the recipient.') .' '.
                       t('To use the option with a select component, you must use key-value pairs seperated by pipes. i.e. user@example.com|Sample user.'),
   );
+  $edit_fields['extra']['other_option'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow "other" option'),
+    '#return_value' => 'Y',
+    '#default_value' => $currfield['extra']['other_option'],
+    '#description' => t('Check this option if you would like to allow the user to enter a value that is not one of the set values.') .' '.
+                      t('The last option in your list of options is the "Other" option.'),
+  );
   return $edit_fields;
 }
 
@@ -175,6 +183,7 @@
   if ($component['extra']['aslist'] === 'Y') {
     // Set display as a select list:
     $form_item['#type'] = 'select';
+    $form_item['#theme'] = 'webform_select';
     if ($component['extra']['multiple'] === 'Y') {
       $form_item['#multiple'] = TRUE;
     }
@@ -191,6 +200,13 @@
       $form_item['#type'] = 'radios';
     }
   }
+
+  if ($component['extra']['other_option'] === 'Y') {
+    $form_item['#other_option'] = TRUE;
+  }
+  else {
+    $form_item['#other_option'] = FALSE;
+  }
   return $form_item;
 }
 
@@ -279,6 +295,14 @@
       }
     }
   }
+  else {
+      $option_values = array_keys(_webform_select_options($component['extra']['items'], TRUE));
+      $other_value = $option_values[count($option_values)-1];
+      if ($component['extra']['other_option'] && $data == $other_value) {
+        $other_name = $component['form_key'] . '-other';
+        $data = $_POST['submitted'][$other_name];
+      }
+  }
 }
 
 /**
@@ -334,6 +358,9 @@
     'webform_mail_select' => array(
       'arguments' => array('data' => NULL, 'component' => NULL),
     ),
+    'webform_select' => array(
+      'arguments' => array('element' => NULL),
+    ),
   );
 }
 
@@ -515,3 +542,51 @@
   }
   return $options;
 }
+
+function theme_webform_select($element) {
+  $select = '';
+  $size = $element['#size'] ? ' size="'. $element['#size'] .'"' : '';
+  _form_set_class($element, array('form-select'));
+  $multiple = $element['#multiple'];
+
+  $other_option_input = '';
+  $other_js = '';
+  // Show "other" option if needed
+  if ($element['#other_option']) {
+    $other_value = '';
+    // the ID and name of the "other" input field are based off the ID and name of the select element
+    $other_name = substr($element['#name'], 0, -1) . '-other]';
+    $other_id = $element['#id'] . '-other';
+    // Determine the value of the "other" option, which is the last option for the element
+    $option_values = array_keys($element['#options']);
+    $other_option = $option_values[count($option_values)-1];
+    $hide_input_js = "$('#" . $other_id . "').hide();";
+    // Assume that if the element value is not one of the options, the "other" option is selected
+    if (!in_array($element['#value'], $option_values)) {
+      // Get the other value from the select element and set the value of the select field to be the "other" option
+      $other_value = $element['#value'];
+      $element['#value'] = $other_option;
+      $hide_input_js = '';
+    }
+    $other_option_input = ' <input id="' . $other_id . '" name="' . $other_name . '" type="textfield" value="' . check_plain($other_value) . '"/>';
+    // Javascript needed for showing/hiding the "other" input field
+    $other_js = "
+<script type='text/javascript'>
+$(document).ready(function() {
+  " . $hide_input_js . "
+  $('#" . $element['#id'] . "').change(function() {
+    if (this.value == '" . $other_option . "') {
+      $('#" . $other_id . "').show();
+    }
+    else {
+      $('#" . $other_id . "').hide();
+    }
+  });
+});
+</script>
+    ";
+    // Add jquery librarys needed for show/hide functionality.
+    drupal_add_js(drupal_get_path('module', 'webform') .'/webform.js');
+  }
+  return theme('form_element', $element, '<select name="'. $element['#name'] .''. ($multiple ? '[]' : '') .'"'. ($multiple ? ' multiple="multiple" ' : '') . drupal_attributes($element['#attributes']) .' id="'. $element['#id'] .'" '. $size .'>'. form_select_options($element) .'</select> ' . $other_option_input . $other_js);
+}
\ No newline at end of file
