diff --git a/includes/form_builder.admin.inc b/includes/form_builder.admin.inc
index f0ae0bd..f2bd73a 100644
--- a/includes/form_builder.admin.inc
+++ b/includes/form_builder.admin.inc
@@ -590,7 +590,7 @@ function form_builder_field_configure($form, $form_state, $form_type, $form_id,
       $function = $property_settings['form'];
       // Set a default value on the property to avoid notices.
       $element['#' . $property] = isset($element['#' . $property]) ? $element['#' . $property] : NULL;
-      $form = array_merge($form, $function($form_state, $form_type, $element));
+      $form = array_merge($form, $function($form_state, $form_type, $element, $property));
     }
   }
 
@@ -673,7 +673,7 @@ function form_builder_field_configure_submit(&$form, &$form_state) {
   foreach ($form_state['values'] as $property => $value) {
     if (in_array($property, $saveable)) {
       // Remove empty properties entirely.
-      if ($value == '') {
+      if ($value === '' || is_null($value)) {
         unset($element['#'. $property]);
       }
       else {
diff --git a/includes/form_builder.properties.inc b/includes/form_builder.properties.inc
index 1ccb04a..f8c9f33 100644
--- a/includes/form_builder.properties.inc
+++ b/includes/form_builder.properties.inc
@@ -12,7 +12,7 @@
  * but instead the array key that is used to reference the element in the
  * Form API structure.
  */
-function form_builder_property_key_form(&$form_state, $form_type, $element) {
+function form_builder_property_key_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['key'] = array(
@@ -69,7 +69,7 @@ function form_builder_property_key_form_validate($element, $form_state) {
 /**
  * Configuration form for the "title" property.
  */
-function form_builder_property_title_form(&$form_state, $form_type, $element) {
+function form_builder_property_title_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['title'] = array(
@@ -86,7 +86,7 @@ function form_builder_property_title_form(&$form_state, $form_type, $element) {
 /**
  * Configuration form for the "title_display" property.
  */
-function form_builder_property_title_display_form(&$form_state, $form_type, $element) {
+function form_builder_property_title_display_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['title_display'] = array(
@@ -114,7 +114,7 @@ function form_builder_property_title_display_form(&$form_state, $form_type, $ele
  * This field is in the "hidden" builder group, meaning it's never shown in
  * the main editing interface. However, it's still there if editing without JS.
  */
-function form_builder_property_weight_form(&$form_state, $form_type, $element) {
+function form_builder_property_weight_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   if (!isset($_REQUEST['js'])) {
@@ -133,7 +133,7 @@ function form_builder_property_weight_form(&$form_state, $form_type, $element) {
 /**
  * Configuration form for the "description" property.
  */
-function form_builder_property_description_form(&$form_state, $form_type, $element) {
+function form_builder_property_description_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['description'] = array(
@@ -149,7 +149,7 @@ function form_builder_property_description_form(&$form_state, $form_type, $eleme
 /**
  * Configuration form for the "required" property.
  */
-function form_builder_property_required_form(&$form_state, $form_type, $element) {
+function form_builder_property_required_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['required'] = array(
@@ -166,7 +166,7 @@ function form_builder_property_required_form(&$form_state, $form_type, $element)
 /**
  * Configuration form for the "options" property.
  */
-function form_builder_property_options_form(&$form_state, $form_type, $element) {
+function form_builder_property_options_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   // Checkboxes have an implied "multiple" property.
@@ -216,7 +216,7 @@ function form_builder_property_options_form_submit(&$form, &$form_state) {
 /**
  * Configuration form for the "default_value" property.
  */
-function form_builder_property_default_value_form(&$form_state, $form_type, $element) {
+function form_builder_property_default_value_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['default_value'] = array(
@@ -235,7 +235,7 @@ function form_builder_property_default_value_form(&$form_state, $form_type, $ele
 /**
  * Configuration form for the "markup" property.
  */
-function form_builder_property_markup_form(&$form_state, $form_type, $element) {
+function form_builder_property_markup_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   // TODO: This is a placeholder until "#markup" becomes available in D7.
@@ -265,7 +265,7 @@ function form_builder_property_markup_form_submit(&$form, &$form_state) {
 /**
  * Configuration form for the "size" property.
  */
-function form_builder_property_size_form(&$form_state, $form_type, $element) {
+function form_builder_property_size_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['size'] = array(
@@ -283,7 +283,7 @@ function form_builder_property_size_form(&$form_state, $form_type, $element) {
 /**
  * Configuration form for the "rows" property.
  */
-function form_builder_property_rows_form(&$form_state, $form_type, $element) {
+function form_builder_property_rows_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['rows'] = array(
@@ -301,7 +301,7 @@ function form_builder_property_rows_form(&$form_state, $form_type, $element) {
 /**
  * Configuration form for the "cols" property.
  */
-function form_builder_property_cols_form(&$form_state, $form_type, $element) {
+function form_builder_property_cols_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['cols'] = array(
@@ -321,7 +321,7 @@ function form_builder_property_cols_form(&$form_state, $form_type, $element) {
 /**
  * Configuration form for the "field_prefix" property.
  */
-function form_builder_property_field_prefix_form(&$form_state, $form_type, $element) {
+function form_builder_property_field_prefix_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['field_prefix'] = array(
@@ -338,7 +338,7 @@ function form_builder_property_field_prefix_form(&$form_state, $form_type, $elem
 /**
  * Configuration form for the "field_suffix" property.
  */
-function form_builder_property_field_suffix_form(&$form_state, $form_type, $element) {
+function form_builder_property_field_suffix_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['field_suffix'] = array(
@@ -355,7 +355,7 @@ function form_builder_property_field_suffix_form(&$form_state, $form_type, $elem
 /**
  * Configuration form for the "collapsible" property.
  */
-function form_builder_property_collapsible_form(&$form_state, $form_type, $element) {
+function form_builder_property_collapsible_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['collapsible'] = array(
@@ -372,7 +372,7 @@ function form_builder_property_collapsible_form(&$form_state, $form_type, $eleme
 /**
  * Configuration form for the "collapsed" property.
  */
-function form_builder_property_collapsed_form(&$form_state, $form_type, $element) {
+function form_builder_property_collapsed_form(&$form_state, $form_type, $element, $property) {
   $form = array();
 
   $form['collapsed'] = array(
diff --git a/modules/webform/form_builder_webform.components.inc b/modules/webform/form_builder_webform.components.inc
index 7d64ce4..93ac632 100644
--- a/modules/webform/form_builder_webform.components.inc
+++ b/modules/webform/form_builder_webform.components.inc
@@ -140,7 +140,6 @@ function _form_builder_webform_form_builder_types_email() {
     ),
   );
   $fields['email']['default'] = _form_builder_webform_default('email');
-  $fields['email']['default']['#webform_component']['type'] = 'email';
   $fields['email']['default'] = _form_builder_webform_form_builder_load_email($fields['email']['default']);
 
   $fields['email']['default']['#title'] = t('New e-mail');
@@ -245,7 +244,6 @@ function _form_builder_webform_form_builder_types_file() {
   );
 
   $fields['file']['default'] = _form_builder_webform_default('file');
-  $fields['file']['default']['#webform_component']['type'] = 'file';
   $fields['file']['default'] = _form_builder_webform_form_builder_load_file($fields['file']['default']);
   $fields['file']['default']['#title'] = t('New file');
 
@@ -645,6 +643,109 @@ function _form_builder_webform_form_builder_preview_alter_markup($form_element)
  * @} End of "defgroup form-builder-webform-markup-callbacks"
  */
 
+
+/**
+ * @defgroup form-builder-webform-number-callbacks Callbacks for the Number component
+ * @{
+ */
+
+/**
+ * Implements _form_builder_webform_form_builder_types_component().
+ */
+function _form_builder_webform_form_builder_types_number() {
+  $fields = array();
+
+  $fields['number'] = array(
+    'title' => t('Number'),
+    'properties' => array(
+      'title',
+      'description',
+      'required',
+      'key',
+      'title_display',
+      'default_value',
+      'field_prefix',
+      'field_suffix',
+      // Number-specific properties.
+      // TODO: Implement the number type support when possible through Webform.
+      //'number_type',
+      'min',
+      'max',
+      'step',
+      'decimals',
+      'point',
+      'separator',
+      'integer',
+      'excludezero',
+    ),
+  );
+
+  $fields['number']['default'] = _form_builder_webform_default('number');
+  $fields['number']['default']['#title'] = t('New number');
+
+  return $fields;
+}
+
+/**
+ * Implements _form_builder_webform_form_builder_map_component().
+ */
+function _form_builder_webform_form_builder_map_number() {
+  return array(
+    'form_builder_type' => 'number',
+    'properties' => array(
+      'maxlength' => array(
+        'storage_parents' => array('extra', 'maxlength'),
+      ),
+      'field_prefix' => array(
+        'storage_parents' => array('extra', 'field_prefix'),
+      ),
+      'field_suffix' => array(
+        'storage_parents' => array('extra', 'field_suffix'),
+      ),
+      'number_type' => array(
+        'form_parents' => array('display', 'type'),
+        'storage_parents' => array('extra', 'type'),
+      ),
+      'min' => array(
+        'form_parents' => array('validation', 'min'),
+        'storage_parents' => array('extra', 'min'),
+      ),
+      'max' => array(
+        'form_parents' => array('validation', 'max'),
+        'storage_parents' => array('extra', 'max'),
+      ),
+      'step' => array(
+        'form_parents' => array('validation', 'step'),
+        'storage_parents' => array('extra', 'step'),
+      ),
+      'decimals' => array(
+        'form_parents' => array('display', 'decimals'),
+        'storage_parents' => array('extra', 'decimals'),
+      ),
+      'point' => array(
+        'form_parents' => array('display', 'point'),
+        'storage_parents' => array('extra', 'point'),
+      ),
+      'separator' => array(
+        'form_parents' => array('display', 'separator'),
+        'storage_parents' => array('extra', 'separator'),
+      ),
+      'integer' => array(
+        'form_parents' => array('validation', 'integer'),
+        'storage_parents' => array('extra', 'integer'),
+      ),
+      'excludezero' => array(
+        'form_parents' => array('analysis', 'excludezero'),
+        'storage_parents' => array('extra', 'excludezero'),
+      ),
+    ),
+  );
+}
+
+/**
+ * @} End of "defgroup form-builder-webform-number-callbacks"
+ */
+
 /**
  * @defgroup form-builder-webform-pagebreak-callbacks Callbacks for the Pagebreak component
  * @{
@@ -1002,12 +1103,74 @@ function form_builder_webform_property_time_hourformat_form(&$form_state, $form_
  */
 
 /**
+ * Helper function; Generate a configuration form based on a map.
+ */
+function _form_builder_webform_mapped_form(&$form_state, $form_type, $element, $property) {
+  $form = array();
+  if ($component_type = $element['#webform_component']['type']) {
+    if ($map = form_builder_webform_component_invoke($component_type, 'form_builder_map')) {
+      $property_group = isset($map['properties'][$property]['property_group']) ? $map['properties'][$property]['property_group'] : reset($map['properties'][$property]['form_parents']);
+      $form = _form_builder_webform_build_edit_form($component_type, $element, $property, $property_group, $map['properties'][$property]['form_parents'], $map['properties'][$property]['storage_parents']);
+    }
+  }
+  return $form;
+}
+
+/**
+ * Helper function; Save an element to a Webform component based on a map.
+ */
+function _form_builder_webform_save_mapped_component($component, $element) {
+  if ($map = form_builder_webform_component_invoke($component['type'], 'form_builder_map')) {
+    foreach ($map['properties'] as $property => $property_map) {
+      if (isset($element['#' . $property]) && isset($property_map['storage_parents'])) {
+        _form_builder_webform_save_mapped_component_value($component, $element['#' . $property], $property_map['storage_parents']);
+      }
+    }
+  }
+  return $component;
+}
+
+/**
+ * Recursive function to set the value of a $component property.
+ */
+function _form_builder_webform_save_mapped_component_value(&$component, $value, $parents) {
+  $parent = array_shift($parents);
+  if (empty($parents)) {
+    $component[$parent] = $value;
+  }
+  else {
+    _form_builder_webform_save_mapped_component_value($component[$parent], $value, $parents);
+  }
+}
+
+/**
+ * Helper function; Alter a form element upon load based on a map.
+ */
+function _form_builder_webform_set_mapped_type($element) {
+  if ($map = form_builder_webform_component_invoke($element['#webform_component']['type'], 'form_builder_map')) {
+    // Keep the internal type of this element as the component type. For example
+    // this may match an $element['#type'] of 'webform_date' and set the
+    // $element['#form_builder']['element_type'] to simply 'date'.
+    $element['#form_builder']['element_type'] = $map['form_builder_type'];
+  }
+  return $element;
+}
+
+/**
  * Helper function; Generate a default FAPI element for any component type.
  */
 function _form_builder_webform_default($component_type, $merge_extras = array()) {
   $default_component = webform_component_invoke($component_type, 'defaults');
   $default_component['extra'] = isset($default_component['extra']) ? array_merge($default_component['extra'], $merge_extras) : $merge_extras;
   $default_element = webform_component_invoke($component_type, 'render', $default_component, NULL, FALSE);
+
+  // Set a bare-minimum component for identification of the component type.
+  $default_element['#webform_component']['type'] = $component_type;
+
+  // Call the loading function to make sure that the default element gets the
+  // same treatment as an existing one.
+  $default_element = _form_builder_webform_set_mapped_type($default_element);
+
   return $default_element;
 }
 
@@ -1017,7 +1180,7 @@ function _form_builder_webform_default($component_type, $merge_extras = array())
  * The returned form is derived from a subcomponent of the component form
  * provided by the Webform module.
  *
- * @param $type
+ * @param $component_type
  *   The webform component type to be edited.
  * @param $element
  *   A form array representing the element whose configuration form we are
@@ -1048,11 +1211,11 @@ function _form_builder_webform_default($component_type, $merge_extras = array())
  *   A form array that can be used to edit the specified part of the webform
  *   component represented by $element.
  */
-function _form_builder_webform_build_edit_form($type, $element, $property, $form_builder_property_group, $form_nested_keys, $component_nested_keys) {
+function _form_builder_webform_build_edit_form($component_type, $element, $property, $form_builder_property_group, $form_nested_keys, $component_nested_keys) {
   // The Webform module stores existing component data as part of the passed-in
   // element. If the component doesn't exist yet, initialize a default
   // component.
-  $defaults_function = '_webform_defaults_' . $type;
+  $defaults_function = '_webform_defaults_' . $component_type;
   $component = isset($element['#webform_component']) ? $element['#webform_component'] : $defaults_function();
 
   // The most up-to-date configuration data stored by Form Builder for the
@@ -1064,7 +1227,7 @@ function _form_builder_webform_build_edit_form($type, $element, $property, $form
 
   // Build the entire _webform_edit_file() form based on the current state of
   // the component, and obtain the slice of it that we want.
-  $edit_function = '_webform_edit_' . $type;
+  $edit_function = '_webform_edit_' . $component_type;
   $form = $edit_function($component);
   $form = drupal_array_get_nested_value($form, $form_nested_keys);
 
diff --git a/modules/webform/form_builder_webform.module b/modules/webform/form_builder_webform.module
index bb5cee9..31ed651 100644
--- a/modules/webform/form_builder_webform.module
+++ b/modules/webform/form_builder_webform.module
@@ -106,6 +106,8 @@ function form_builder_webform_save_node($node) {
  * Save the contents of a form component into Webform's database tables.
  */
 function form_builder_webform_save_component($node, $element_id, $form) {
+  module_load_include('inc', 'form_builder_webform', 'form_builder_webform.components');
+
   $element = form_builder_get_element($form, $element_id);
   $type = isset($element['#webform']['type']) ? $element['#webform']['type'] : $element['#form_builder']['element_type'];
 
@@ -166,7 +168,10 @@ function form_builder_webform_save_component($node, $element_id, $form) {
     $component['value'] = NULL;
   }
 
-  // Save any specific settings.
+  // Set all properties based on property maps.
+  $component = _form_builder_webform_save_mapped_component($component, $element);
+
+  // Allow each component to set any specific settings that can't be mapped.
   if ($saved_component = form_builder_webform_component_invoke($type, 'form_builder_save', $component, $element)) {
     $component = $saved_component;
   }
@@ -188,6 +193,20 @@ function form_builder_webform_cancel(&$form, &$form_state) {
 }
 
 /**
+ * Implements hook_form_builder_property_groups().
+ */
+function form_builder_webform_form_builder_property_groups($form_type) {
+  $groups = array();
+  if ($form_type == 'webform') {
+    $groups['analysis'] = array(
+      'weight' => 4,
+      'title' => t('Analysis'),
+    );
+  }
+  return $groups;
+}
+
+/**
  * Implements hook_form_builder_types().
  *
  * Define the fields within webforms that are editable.
@@ -213,8 +232,20 @@ function form_builder_webform_form_builder_properties($form_type) {
 
   if ($form_type == 'webform') {
     $components = webform_components();
-    foreach ($components as $type => $component) {
-      if ($additional_properties = form_builder_webform_component_invoke($type, 'form_builder_properties')) {
+    foreach ($components as $component_type => $component) {
+      // Components providing a map to automatically list properties.
+      if ($map = form_builder_webform_component_invoke($component_type, 'form_builder_map')) {
+        foreach ($map['properties'] as $property_name => $property_map) {
+          if (isset($property_map['form_parents'])) {
+            $properties[$property_name] = array(
+              'form' => '_form_builder_webform_mapped_form',
+            );
+          }
+        }
+      }
+
+      // Individual components manually providing properties.
+      if ($additional_properties = form_builder_webform_component_invoke($component_type, 'form_builder_properties')) {
         $properties = array_merge($properties, $additional_properties);
       }
     }
@@ -270,6 +301,8 @@ function form_builder_webform_form_builder_load($form_builder_type, $form_builde
  * Recursive helper function to populate #form_builder['element_id'] values.
  */
 function form_builder_webform_load_process(&$form, $node, $pid = 0) {
+  module_load_include('inc', 'form_builder_webform', 'form_builder_webform.components');
+
   foreach (element_children($form) as $key) {
     $cid = webform_get_cid($node, $key, $pid);
     $form[$key]['#form_builder'] = array(
@@ -278,8 +311,13 @@ function form_builder_webform_load_process(&$form, $node, $pid = 0) {
 
     // Add any component-specific loading. Note that all components are
     // invoked here because the component type isn't yet known.
-    foreach (webform_components() as $type => $info) {
-      if ($element = form_builder_webform_component_invoke($type, 'form_builder_load', $form[$key])) {
+    if (isset($form[$key]['#webform_component']['type'])) {
+      $component_type = $form[$key]['#webform_component']['type'];
+
+      // Set the internal type based on any mappings.
+      $form[$key] = _form_builder_webform_set_mapped_type($form[$key]);
+
+      if ($element = form_builder_webform_component_invoke($component_type, 'form_builder_load', $form[$key])) {
         $form[$key] = $element;
       }
     }
@@ -381,14 +419,14 @@ function _form_builder_remove_conditional_form_element_pre_render(&$form) {
  * default implementation of the callback on behalf of the component, the
  * result obtained from that is returned.
  *
- * @param $type
+ * @param $component_type
  *   The component type as a string.
  * @param $callback
  *   The callback to execute.
  * @param ...
  *   Any additional parameters required by the $callback.
  */
-function form_builder_webform_component_invoke($type, $callback) {
+function form_builder_webform_component_invoke($component_type, $callback) {
   $args = func_get_args();
 
   // First try invoking the callback in the webform component itself.
@@ -398,9 +436,9 @@ function form_builder_webform_component_invoke($type, $callback) {
   }
 
   // Otherwise look for a default implementation provided by this module.
-  $type = array_shift($args);
+  $component_type = array_shift($args);
   $callback = array_shift($args);
-  $function = '_form_builder_webform_' . $callback . '_' . $type;
+  $function = '_form_builder_webform_' . $callback . '_' . $component_type;
   module_load_include('inc', 'form_builder_webform', 'form_builder_webform.components');
   if (function_exists($function)) {
     return call_user_func_array($function, $args);
