diff --git a/components/date.inc b/components/date.inc
index b79f31f..07b4426 100644
--- a/components/date.inc
+++ b/components/date.inc
@@ -20,7 +20,6 @@ function _webform_defaults_date() {
       'timezone' => 'user',
       'start_date' => '-2 years',
       'end_date' => '+2 years',
-      'year_textfield' => 0,
       'datepicker' => 1,
       'title_display' => 0,
       'description' => '',
@@ -82,15 +81,6 @@ function _webform_edit_date($component) {
     '#parents' => array('extra', 'datepicker'),
   );
 
-  $form['display']['year_textfield'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Use a textfield for year'),
-    '#default_value' => $component['extra']['year_textfield'],
-    '#description' => t('If checked, the generated date field will use a textfield for the year. Otherwise it will use a select list.'),
-    '#weight' => 5,
-    '#parents' => array('extra', 'year_textfield'),
-  );
-
   $form['validation']['start_date'] = array(
     '#type' => 'textfield',
     '#title' => t('Start date'),
@@ -118,15 +108,14 @@ function _webform_edit_date($component) {
  */
 function _webform_render_date($component, $value = NULL, $filter = TRUE) {
   $element = array(
-    '#type' => 'date',
+    '#type' => 'webform_date',
     '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
     '#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
     '#weight' => $component['weight'],
     '#description' => $filter ? _webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
     '#required' => $component['mandatory'],
-    '#start_date' => trim($component['extra']['start_date']),
-    '#end_date' => trim($component['extra']['end_date']),
-    '#year_textfield' => $component['extra']['year_textfield'],
+    '#min' => trim($component['extra']['start_date']),
+    '#max' => trim($component['extra']['end_date']),
     '#default_value' => $filter ? _webform_filter_values($component['value'], NULL, NULL, NULL, FALSE) : $component['value'],
     '#timezone' => $component['extra']['timezone'],
     '#process' => array('webform_expand_date'),
@@ -147,7 +136,6 @@ function _webform_render_date($component, $value = NULL, $filter = TRUE) {
 
   // Set the value from Webform.
   if (isset($value[0]) && $value[0] !== '') {
-    $value = webform_date_array($value[0], 'date');
     $element['#default_value'] = $value;
   }
 
@@ -158,70 +146,14 @@ function _webform_render_date($component, $value = NULL, $filter = TRUE) {
  * Form API #process function for Webform date fields.
  */
 function webform_expand_date($element) {
-  // Accept a string or array value for #default_value.
-  if (!empty($element['#default_value']) && is_string($element['#default_value'])) {
-    $timezone = $element['#timezone'] != 'user' ? NULL : 'user';
-    $timestring = webform_strtodate('c', $element['#default_value'], $timezone);
-    $element['#default_value'] = webform_date_array($timestring, 'date');
-  }
-
-  // Set defaults according to existing #default_value (set by Form API)
-  if (isset($element['#default_value']['month']) || isset($element['#default_value']['day']) || isset($element['#default_value']['year'])) {
-    $default_values = array(
-      'month' => $element['#default_value']['month'],
-      'day' => $element['#default_value']['day'],
-      'year' => $element['#default_value']['year'],
-    );
-  }
-  else {
-    $default_values = array(
-      'day' => NULL,
-      'month' => NULL,
-      'year' => NULL,
-    );
-  }
-
-  // Let Drupal do it's normal expansion.
-  $element = form_process_date($element);
-
-  // Set default values.
-  foreach ($default_values as $type => $value) {
-    switch ($type) {
-      case 'month':
-        $none = t('Month');
-        break;
-      case 'day':
-        $none = t('Day');
-        break;
-      case 'year':
-        $none = t('Year');
-        break;
-    }
-    unset($element[$type]['#value']);
-    $element[$type]['#default_value'] = isset($default_values[$type]) ? $default_values[$type] : NULL;
-    $element[$type]['#options'] = array('' => $none) + $element[$type]['#options'];
-  }
 
   // Convert relative dates to absolute ones.
-  foreach (array('start_date', 'end_date') as $start_end) {
+  foreach (array('min', 'max', 'default_value') as $start_end) {
     $timezone = $element['#timezone'] != 'user' ? NULL : 'user';
-    $date = webform_strtodate('Y-m-d', $element['#' . $start_end], $timezone);
+    $date = empty($element['#' . $start_end]) ? '' : webform_strtodate('Y-m-d', $element['#' . $start_end], $timezone);
     $element['#' . $start_end] = $date ? $date : '';
   }
 
-  // Tweak the year field.
-  if ($element['#year_textfield']) {
-    $element['year']['#type'] = 'textfield';
-    $element['year']['#size'] = 5;
-    $element['year']['#maxlength'] = 4;
-    unset($element['year']['#options']);
-  }
-  elseif ($element['#start_date'] || $element['#end_date']) {
-    $start_year = $element['#start_date'] ? webform_strtodate('Y', $element['#start_date']) : webform_strtodate('Y', '-2 years');
-    $end_year = $element['#end_date'] ? webform_strtodate('Y', $element['#end_date']) : webform_strtodate('Y', '+2 years');
-    $element['year']['#options'] = array('' => t('Year')) + drupal_map_assoc(range($start_year, $end_year));
-  }
-
   return $element;
 }
 
@@ -231,37 +163,33 @@ function webform_expand_date($element) {
 function theme_webform_date($variables) {
   $element = $variables['element'];
 
-  $element['year']['#attributes']['class'] = array('year');
-  $element['month']['#attributes']['class'] = array('month');
-  $element['day']['#attributes']['class'] = array('day');
-
-  // Add error classes to all items within the element.
-  if (form_get_error($element)) {
-    $element['year']['#attributes']['class'][] = 'error';
-    $element['month']['#attributes']['class'][] = 'error';
-    $element['day']['#attributes']['class'][] = 'error';
-  }
-
   $class = array('webform-container-inline');
 
   // Add the JavaScript calendar if available (provided by Date module package).
   if (!empty($element['#datepicker'])) {
     $class[] = 'webform-datepicker';
     $calendar_class = array('webform-calendar');
-    if ($element['#start_date']) {
-      $calendar_class[] = 'webform-calendar-start-' . $element['#start_date'];
+    if ($element['#min']) {
+      $calendar_class[] = 'webform-calendar-start-' . $element['#min'];
     }
-    if ($element['#end_date']) {
-      $calendar_class[] = 'webform-calendar-end-' . $element['#end_date'];
+    if ($element['#max']) {
+      $calendar_class[] = 'webform-calendar-end-' . $element['#max'];
     }
     $calendar_class[] ='webform-calendar-day-' . variable_get('date_first_day', 0);
 
     $calendar = theme('webform_calendar', array('component' => $element['#webform_component'], 'calendar_classes' => $calendar_class));
   }
 
+  // Render the date element itself.
+  $element['#attributes']['type'] = 'date';
+  $element['#value'] = isset($element['#value']) ? $element['#value'] : $element['#default_value'];
+  $element['#placeholder'] = 'YYYY-MM-DD';
+  element_set_attributes($element, array('id', 'name', 'value', 'min', 'max', 'placeholder'));
+  _form_set_class($element, array('form-text', 'form-date'));
+
   $output = '';
   $output .= '<div class="' . implode(' ', $class) . '">';
-  $output .= drupal_render_children($element);
+  $output .= '<input' . drupal_attributes($element['#attributes']) . ' />';
   $output .= isset($calendar) ? $calendar : '';
   $output .= '</div>';
 
@@ -272,28 +200,20 @@ function theme_webform_date($variables) {
  * Element validation for Webform date fields.
  */
 function webform_validate_date($element, $form_state) {
-  // Check if the user filled the required fields.
-  foreach (array('day', 'month', 'year') as $field_type) {
-    if (!is_numeric($element[$field_type]['#value']) && $element['#required']) {
-      form_error($element, t('!name field is required.', array('!name' => $element['#title'])));
-      return;
-    }
-  }
-
-  if ($element['month']['#value'] !== '' || $element['day']['#value'] !== '' || $element['year']['#value'] !== '') {
+  if ($element['#value'] !== '') {
     // Check for a valid date.
-    if (!checkdate((int) $element['month']['#value'], (int) $element['day']['#value'], (int) $element['year']['#value'])) {
+    if (!checkdate($element['#value'])) {
       form_error($element, t('Entered !name is not a valid date.', array('!name' => $element['#title'])));
       return;
     }
 
     // Create a timestamp of the entered value for comparison.
-    $timestamp = strtotime($element['year']['#value'] . '-' . $element['month']['#value'] . '-' . $element['day']['#value']);
+    $timestamp = strtotime($element['#value']);
     $format = webform_date_format('short');
 
     // Flip start and end if needed.
-    $date1 = strtotime($element['#start_date']);
-    $date2 = strtotime($element['#end_date']);
+    $date1 = strtotime($element['#min']);
+    $date2 = strtotime($element['#max']);
     if ($date1 !== FALSE && $date2 !== FALSE) {
       $start_date = $date1 < $date2 ? $date1 : $date2;
       $end_date = $date1 > $date2 ? $date1 : $date2;
diff --git a/components/number.inc b/components/number.inc
deleted file mode 100644
index e69de29..0000000
diff --git a/js/webform.js b/js/webform.js
index 70ac37a..b7b98cc 100644
--- a/js/webform.js
+++ b/js/webform.js
@@ -43,16 +43,15 @@ Drupal.webform.datepicker = function(context) {
       minDate: startDate,
       maxDate: endDate,
       onSelect: function(dateText, inst) {
-        var date = dateText.split('-');
-        $webformDatepicker.find('select.year, input.year').val(+date[0]);
-        $webformDatepicker.find('select.month').val(+date[1]);
-        $webformDatepicker.find('select.day').val(+date[2]);
+        $webformDatepicker.find('input.form-date').val(dateText);
       },
       beforeShow: function(input, inst) {
         // Get the select list values.
-        var year = $webformDatepicker.find('select.year, input.year').val();
-        var month = $webformDatepicker.find('select.month').val();
-        var day = $webformDatepicker.find('select.day').val();
+        var dateText = $webformDatepicker.find('input.form-date').val();
+        var date = dateText.split('-');
+        var year = date[0];
+        var month = date[1];
+        var day = date[2];
 
         // If empty, default to the current year/month/day in the popup.
         var today = new Date();
diff --git a/webform.module b/webform.module
index b036c2a..d1791e3 100644
--- a/webform.module
+++ b/webform.module
@@ -480,7 +480,23 @@ function webform_admin_paths() {
 }
 
 /**
- * Implements hook_perm().
+ * Implements hook_elements().
+ *
+ * Ideally we could put these definitions in each modules .inc file, but because
+ * this list is generated on every page load, we code them manually here to
+ * prevent unnecessary loading of those .inc files.
+ */
+function webform_elements() {
+  $types['webform_date'] = array(
+    '#input' => TRUE,
+    '#theme' => 'webform_date',
+    '#theme_wrappers' => array('webform_element'),
+  );
+  return $types;
+}
+
+/**
+ * Implements hook_permission().
  */
 function webform_permission() {
   return array(
