diff --git a/field_conditional_state.admin.inc b/field_conditional_state.admin.inc
index 0ebfc2b..a4f5891 100644
--- a/field_conditional_state.admin.inc
+++ b/field_conditional_state.admin.inc
@@ -307,7 +307,7 @@ function field_conditional_state_settings_form_submit($form, $form_state) {
   foreach ($fcs_states['existing_groups'] as $id) {
     if (!empty($values['control_field-new-' . $id]) && !empty($values['trigger_state-new-' . $id])) {
       $trigger_value = 1;
-      if($values['trigger_state-new-' . $id] == 'value' || $values['trigger_state-new-' . $id] == '!value') {
+      if ($values['trigger_state-new-' . $id] == 'value' || $values['trigger_state-new-' . $id] == '!value') {
         $trigger_value = $values['trigger_value-new-' . $id];
       }
 
diff --git a/field_conditional_state.module b/field_conditional_state.module
index e0f1e0b..687d859 100644
--- a/field_conditional_state.module
+++ b/field_conditional_state.module
@@ -58,96 +58,137 @@ function _field_conditional_state_get_conditional_states($entity_type, $bundle,
 }
 
 /**
- * Returns a field suffix that will be appended to the fcs elements.
- *
- * To be able to differentiate between multiple instances
- * of one field in a form (field collections, etc)
- * it is necessary to create this suffix.
- *
- * @param array $element
- *   a form element
- *
- * @return string
- *   the suffix
+ * Returns the path to the actual input element within the $element array.
+ * 
+ * @return array
+ *   array with two keys:
+ *   -actual_element: "Path" to the actual input/select element within the array
+ *   -field_data: Path to the fields data (#entity_type, #bundle, #field_name)
  */
-function _field_conditional_state_get_field_suffix($element) {
-  static $processed_fields = array();
-  static $index_prefix = array();
-
-  $parent_id = $element['#entity_type'] . '__' . $element['#bundle'];
-
-  $parent_index = NULL;
-  if (!isset($processed_fields[$parent_id])) {
-    $processed_fields[$parent_id] = array();
-    $index_prefix[$parent_id] = count($index_prefix);
+function _field_conditional_state_get_element_parents($widget_type) {
+  $paths = array('actual_element' => array(), 'field_data' => array());
+  switch ($widget_type) {
+    case 'file_generic':
+    case 'image_image':
+      $paths['actual_element'] = array(0, 'upload');
+      $paths['field_data'] = array();
+      $paths['field_data'][] = 0;
+      break;
+
+    case 'number':
+    case 'text_textfield':
+      $paths['actual_element'] = array('value');
+      $paths['field_data'] = array('value');
+      break;
+
+    case 'url_external':
+      $paths['actual_element'] = array('value');
+      $paths['field_data'] = array();
+      break;
+
+    default:
+      // options_onoff, text_textarea
   }
 
-  if (!isset($processed_fields[$parent_id][$element['#field_name']])) {
-    $parent_index = $processed_fields[$parent_id][$element['#field_name']] = 0;
-  }
-  else {
-    $parent_index = ++$processed_fields[$parent_id][$element['#field_name']];
-  }
-  return $index_prefix[$parent_id] . $parent_index;
+  return $paths;
 }
 
-
 /**
- * Adds the #states to the form elements and prepares the validation.
+ * Finds the actual element and adds the #pre_render callback to it.
  *
  * @param array $element
  *   a form element
  * @param array $form_state
  *   the current form state
- * @param array $form
- *   the complete form
  *
  * @return array
  *   the processed element
  */
-function field_conditional_state_element_process($element, &$form_state, &$form) {
-  if (isset($element['#entity_type']) && isset($element['#bundle']) && isset($element['#field_name'])) {
-    /*
-     * An array containing the IDs generated by drupal_html_id
-     * keyed by their original form (as the argument of drupal_html_id)
-     */
-    $ids = &drupal_static(__FUNCTION__, array());
+function field_conditional_state_element_after_build($element, &$form_state) {
+  if (isset($element['#field_conditional_state_widget_type'])) {
 
-    $element['#field_conditional_state_id'] = _field_conditional_state_get_field_suffix($element);
+    // Mapping the entity_type, bundle and field_name to their actual HTML ID
+    // for later use in the #pre_render callback.
+    $ids = &drupal_static(__FUNCTION__, array());
 
-    if (empty($element['#pre_render'])) {
-      $element['#pre_render'] = array();
+    // Get the location of the actual input element
+    // and the location of the field information (#entity_type, etc).
+    $element_parents = _field_conditional_state_get_element_parents($element['#field_conditional_state_widget_type']);
+    $actual_element = &drupal_array_get_nested_value($element, $element_parents['actual_element']);
+    $field_data = drupal_array_get_nested_value($element, $element_parents['field_data']);
+
+    // Set the #pre_render callbacks based on the active states for the element.
+    // For the top level ($element), if a visible/invisible state is active
+    // and for the actual element ($actual_element), if another state is active.
+    $states = _field_conditional_state_get_conditional_states($field_data['#entity_type'], $field_data['#bundle'], $field_data['#field_name']);
+    $visibility_state_active = FALSE;
+    $direct_state_active = FALSE;
+    // Check what kind of states are active.
+    foreach ($states as $state) {
+      if (in_array($state['state'], array('visible', 'invisible'))) {
+        $visibility_state_active = TRUE;
+      }
+      else {
+        $direct_state_active = TRUE;
+      }
+      if ($direct_state_active && $visibility_state_active) {
+        break;
+      }
     }
-    $element['#pre_render'][] = '_field_conditional_state_add_states';
 
-    $original_id = $element['#field_name'] . '_field_conditional_state_control_' . $element['#field_conditional_state_id'];
-    $ids[$original_id] = drupal_html_id($original_id);
-    $element['#prefix'] = '<div ' . drupal_attributes(array('id' => $ids[$original_id])) . '>';
-    $element['#suffix'] = "</div>";
+    // Add the #pre_render callbacks.
+    if ($visibility_state_active) {
+      if (empty($element['#pre_render'])) {
+        $element['#pre_render'] = array();
+      }
+      $element['#pre_render'][] = '_field_conditional_state_add_visibility_states';
+      $element['#entity_type'] = $field_data['#entity_type'];
+      $element['#bundle'] = $field_data['#bundle'];
+      $element['#field_name'] = $field_data['#field_name'];
+    }
+    if ($direct_state_active) {
+      if (empty($actual_element['#pre_render'])) {
+        $actual_element['#pre_render'] = array();
+      }
+      $actual_element['#pre_render'][] = '_field_conditional_state_add_direct_states';
+      $actual_element['#entity_type'] = $field_data['#entity_type'];
+      $actual_element['#bundle'] = $field_data['#bundle'];
+      $actual_element['#field_name'] = $field_data['#field_name'];
+    }
 
+    $ids[$field_data['#entity_type'] . '__' . $field_data['#bundle'] . '__' . $field_data['#field_name']] = $actual_element['#id'];
   }
+
   return $element;
 }
 
 /**
  * Pre-render callback.
  *
- * Adds the #states to the element and wraps it
- * into another element if necessary.
+ * Adds the #states visible and invisible to the element
  */
-function _field_conditional_state_add_states($element) {
+function _field_conditional_state_add_visibility_states($element) {
   $states = _field_conditional_state_get_conditional_states($element['#entity_type'], $element['#bundle'], $element['#field_name']);
-  _field_conditional_state_build_states_array($element, $states);
-
-  $is_dependent = isset($element['#states']) && count($element['#states']);
-  if ($is_dependent) {
-    if (empty($element['#type'])) {
-      // Adds a container with the given ID to elements that are dependent
-      // and where the ID would otherwise not be rendered.
-      $element['#prefix'] = '<div ' . drupal_attributes(array('id' => $element['#id'])) . '>';
-      $element['#suffix'] = '</div>';
-    }
-  }
+  _field_conditional_state_build_states_array($element, $states, array('visible', 'invisible'));
+
+  return $element;
+}
+
+/**
+ * Pre-render callback.
+ *
+ * Adds the #states enabled, disabled, required and optional to the element
+ */
+function _field_conditional_state_add_direct_states($element) {
+  $states = _field_conditional_state_get_conditional_states($element['#entity_type'], $element['#bundle'], $element['#field_name']);
+  $state_types = array(
+    'enabled',
+    'disabled',
+    'required',
+    'optional',
+  );
+  _field_conditional_state_build_states_array($element, $states, $state_types);
+
   return $element;
 }
 
@@ -269,50 +310,50 @@ function field_conditional_state_form_field_ui_field_overview_form_alter(&$form,
  * Implements hook_field_widget_form_alter().
  */
 function field_conditional_state_field_widget_form_alter(&$element, &$form_state, $context) {
-  // Number fields elements are located in $element['value']... Why?
-  if ($context['instance']['widget']['type'] == 'number') {
-    $element['value']['#process'][] = 'field_conditional_state_element_process';
-  }
-  else {
-    $element['#process'][] = 'field_conditional_state_element_process';
-  }
-
+  $element['#after_build'][] = 'field_conditional_state_element_after_build';
+  $element['#field_conditional_state_widget_type'] = $context['instance']['widget']['type'];
 }
 
 /**
  * Adds the #states subarray to the given element based on the given conditions.
  */
-function _field_conditional_state_build_states_array(&$element, $groups) {
+function _field_conditional_state_build_states_array(&$element, $groups, $state_types) {
   if (count($groups) > 0) {
 
-    // See description in field_conditional_state_element_process.
-    $ids = &drupal_static('field_conditional_state_element_process');
+    // See description in field_conditional_state_element_after_build
+    $ids = &drupal_static('field_conditional_state_element_after_build');
 
     $element['#states'] = array();
 
     foreach ($groups as $group) {
+      if (!in_array($group['state'], $state_types)) {
+        continue;
+      }
+
       if (empty($element['#states'][$group['state']])) {
         $element['#states'][$group['state']] = array();
       }
-      
+
       /*
-       * And conditions are added to the top level, but or/xor conditions are added into a second level
-       * so we have to distinguish there between 'and' and 'or/xor'
+       * And conditions are added to the top level,
+       * but or/xor conditions are added into a second level
+       * so we have to distinguish there between 'and' and 'or/xor'.
        */
-      switch($group['type']) {
+      switch ($group['type']) {
         case 'and':
           $current = &$element['#states'][$group['state']];
-        break;
+          break;
+
         case 'or':
         case 'xor':
           $current = &$element['#states'][$group['state']][];
           $current = array();
-          if($group['type'] == 'xor') {
+          if ($group['type'] == 'xor') {
             $current[] = 'xor';
           }
-        break;
+          break;
       }
-      
+
       foreach ($group['states'] as $state) {
         if ($state['trigger_state'] == 'value' || $state['trigger_state'] == '!value') {
           $trigger = array($state['trigger_state'] => $state['trigger_value']);
@@ -320,17 +361,18 @@ function _field_conditional_state_build_states_array(&$element, $groups) {
         else {
           $trigger = array($state['trigger_state'] => TRUE);
         }
-        
-        $control_id = $ids[$state['control_field'] . '_field_conditional_state_control_' . $element['#field_conditional_state_id']];
-        
-        if($group['type'] == 'and') {
-          // add condition to the top level
-          $current['#' . $control_id . ' input'] = $trigger;
-        } else {
-          // for or/xor conditions $current already points to the second level, 
-          // but each single condition gets its own third level within the array
+
+        $control_id = $ids[$group['entity_type'] . '__' . $group['bundle'] . '__' . $state['control_field']];
+        if ($group['type'] == 'and') {
+          // Add condition to the top level.
+          $current['#' . $control_id] = $trigger;
+        }
+        else {
+          // For or/xor conditions $current already points to the second level,
+          // but each single condition gets its own third level
+          // within the array.
           $tmp = &$current[];
-          $tmp['#' . $control_id . ' input'] = $trigger;
+          $tmp['#' . $control_id] = $trigger;
         }
       }
     }
