diff --git a/geocoder.module b/geocoder.module
index eab57bf..0d8154c 100644
--- a/geocoder.module
+++ b/geocoder.module
@@ -1,5 +1,7 @@
 <?php
 
+define('GEOCODER_DUMMY_WKT', 'POINT(0, 0)');
+
 /**
  * The Geocode API call.
  * @example:
@@ -12,17 +14,15 @@ function geocoder() {
   $args = func_get_args();
   $processor_name = array_shift($args);
   $processor = ctools_get_plugins('geocoder', 'geocoder_handler', $processor_name);
-  $geometry = call_user_func_array($processor['callback'],$args);
+  $geometry = call_user_func_array($processor['callback'], $args);
 
   return $geometry;
 }
 
-
-
 /**
  * Implements hook_menu().
  */
-function  geocoder_menu() {
+function geocoder_menu() {
   // Admin settings for the site.
   $items['admin/config/content/geocoder'] = array(
     'title' => 'Geocoder settings',
@@ -36,9 +36,6 @@ function  geocoder_menu() {
   return $items;
 }
 
-
-
-
 /**
  * Return a list of all handlers that might geocoder something for you.
  */
@@ -51,7 +48,7 @@ function geocoder_handler_info($field_type = NULL) {
   }
   if ($field_type) {
     $field_handlers = $handlers;
-    foreach($field_handlers as $i => $handler) {
+    foreach ($field_handlers as $i => $handler) {
       if (!isset($handler['field_types']) || !in_array($field_type, $handler['field_types'])) {
         unset($field_handlers[$i]);
       }
@@ -79,7 +76,7 @@ function geocoder_supported_field_types() {
     }
   }
 
-	return $supported;
+  return $supported;
 }
 
 function geocoder_load_geophp() {
@@ -87,7 +84,7 @@ function geocoder_load_geophp() {
 
   if (!$static_cache) {
     $path = libraries_get_path('geoPHP');
-    $file = $path.'/geoPHP.inc';
+    $file = $path . '/geoPHP.inc';
     if (file_exists($file)) {
       if (include_once($file)) {
         $static_cache = $file;
@@ -98,7 +95,6 @@ function geocoder_load_geophp() {
   return $static_cache;
 }
 
-
 /**
  * Implementation of hook_ctools_plugin_api().
  */
@@ -208,8 +204,8 @@ function geocoder_field_widget_settings_form($this_field, $instance) {
     '#required' => TRUE,
   );
 
-  drupal_add_js(array('geocoder_widget_settings' => array('handlers' => $handlers_by_type, 'types' => $field_types)),'setting');
-  drupal_add_js(drupal_get_path('module','geocoder').'/geocoder.admin.js','file');
+  drupal_add_js(array('geocoder_widget_settings' => array('handlers' => $handlers_by_type, 'types' => $field_types)), 'setting');
+  drupal_add_js(drupal_get_path('module', 'geocoder') . '/geocoder.admin.js', 'file');
 
   return $form;
 }
@@ -224,43 +220,37 @@ function geocoder_field_widget_settings_form_callback($form, $form_state) {
 function geocoder_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) {
   $element = $base;
 
-  $element['wkt'] = array(
-   '#type' => 'hidden',
-   '#element_validate' => array('geocoder_widget_validate'),
-  );
-  $element['geocoder_target'] = array(
-   '#type' => 'hidden',
-   '#value' => $instance['field_name'],
-  );
-  $element['geocoder_source'] = array(
-   '#type' => 'hidden',
-   '#value' => isset($instance['widget']['settings']['geocoder_field']) ? $instance['widget']['settings']['geocoder_field'] : '',
-  );
-  $element['geocoder_handler'] = array(
-   '#type' => 'hidden',
-   '#value' => isset($instance['widget']['settings']['geocoder_handler']) ? $instance['widget']['settings']['geocoder_handler'] : '',
-  );
-
+  // Add validation callback.
+  if (isset($element['#element_validate'])) {
+    $element['#element_validate'][] = 'geocoder_widget_validate';
+  }
+  else {
+    $element['#element_validate'] = array('geocoder_widget_validate');
+  }
+  // Store the current values of the fields as en element property.
+  $element['#geocoder_previous_values'] = $items;
   return $element;
 }
 
-
+/**
+ * Validation callback for the geocoder_field_widget_form form.
+ *
+ * We cannot geocode the field's value here since others fields have not been
+ * validated (or even processed) yet.
+ */
 function geocoder_widget_validate($element, &$form_state) {
-  // To validate, we simply run through the form fields, looking for items with geocoder_source and geocoder_target properties
-
-  // Walk the form_state values, applying all instances of geocoder source and target operations
-  foreach ($form_state['values'] as &$field) {
-    geocoder_widget_validate_walkthrough($field, $form_state);
+  // Get previously set value (or dummy).
+  $values = !empty($element['#geocoder_previous_values']) ? $element['#geocoder_previous_values'] : FALSE;
+
+  if (!count($values)) {
+    // setup a dummy value
+    $values = array(
+      'wkt' => GEOCODER_DUMMY_WKT,
+    );
   }
 
-  if (isset($form_state['field']['#parents'])) {
-    //Walk through the fields that are under parents and match up and sources and targets there
-    foreach ($form_state['field']['#parents'] as $parent => $parent_data) {
-      foreach ($form_state['values'][$parent] as &$field) {
-        geocoder_widget_validate_walkthrough($field, $form_state, $parent);
-      }
-    }
-  }
+  // Set the form value
+  form_set_value($element, $values, $form_state);
 }
 
 /**
@@ -289,83 +279,55 @@ function geocoder_widget_parse_field($item, $type) {
  */
 function geocoder_widget_parse_addressfield($field_item) {
   $address = '';
-  if (!empty($field_item['premise']))                 $address .= $field_item['premise'].',';
-  if (!empty($field_item['thoroughfare']))            $address .= $field_item['thoroughfare'].',';
-  if (!empty($field_item['locality']))                $address .= $field_item['locality'].',';
-  if (!empty($field_item['administrative_area']))     $address .= $field_item['administrative_area'].',';
-  if (!empty($field_item['sub_administrative_area'])) $address .= $field_item['sub_administrative_area'].',';
-  if (!empty($field_item['country']))                 $address .= $field_item['country'].',';
-  if (!empty($field_item['postal_code']))             $address .= $field_item['postal_code'].',';
+  if (!empty($field_item['premise']))                 $address .= $field_item['premise'] . ',';
+  if (!empty($field_item['thoroughfare']))            $address .= $field_item['thoroughfare'] . ',';
+  if (!empty($field_item['locality']))                $address .= $field_item['locality'] . ',';
+  if (!empty($field_item['administrative_area']))     $address .= $field_item['administrative_area'] . ',';
+  if (!empty($field_item['sub_administrative_area'])) $address .= $field_item['sub_administrative_area'] . ',';
+  if (!empty($field_item['country']))                 $address .= $field_item['country'] . ',';
+  if (!empty($field_item['postal_code']))             $address .= $field_item['postal_code'] . ',';
 
   return $address;
 }
 
-function geocoder_widget_validate_walkthrough(&$field, $form_state, $parent = NULL) {
-  if (is_array($field)) {
-    // Set the language based on the form state.
-    $lang = isset($form_state['values']['language']) ? $form_state['values']['language'] : LANGUAGE_NONE;
-
-    // If default language is set but content isnt translatable it is still 'und' on the fields.
-    if (!isset($field[$lang])) $lang = LANGUAGE_NONE;
-
-    if (!empty($field[$lang][0]) && is_array($field[$lang][0]) && (!empty($field[$lang][0]['geocoder_source']) && !empty($field[$lang][0]['geocoder_target']) && !empty($field[$lang][0]['geocoder_handler']))) {
-      // We found a source/target/handler set, let's do this.
-
-      // Can only have one handler
-      $handler = geocoder_get_handler($field[$lang][0]['geocoder_handler']);
-
-      $values = array();
-      foreach ($field[$lang][0]['geocoder_source'] as $source) {
-        // If the source is a name or text, then there is only one value
-        if (($source == 'title' || $source == 'name') && isset($form_state['values'][$source])) {
-          $main = $form_state['values'][$source];
-        }
-        else {
-          // get the field info
-          $field_info = field_info_field($source);
-          if (isset($parent) && isset($form_state['values'][$parent][$source][$lang])) {
-            foreach ($form_state['values'][$parent][$source][$lang] as $delta => $item) {
-              $values[$delta][] = geocoder_widget_parse_field($item, $field_info['type']);
-            }
+/**
+ * Implements hook_field_attach_presave().
+ *
+ * Geocoding for the geocoder widget is done here to ensure that only validated
+ * and fully processed fields values are accessed.
+ */
+function geocoder_field_attach_presave($entity_type, $entity) {
+  // Loop over any geofield using our geocode widget
+  $entity_info = entity_get_info($entity_type);
+  $bundle_name = empty($entity_info['entity keys']['bundle']) ? $entity_type : $entity->{$entity_info['entity keys']['bundle']};
+  foreach (field_info_instances($entity_type, $bundle_name) as $field_instance) {
+    if ($field_instance['widget']['type'] === 'geocoder') {
+      // Required settings
+      if (isset($field_instance['widget']['settings']['geocoder_handler']) && isset($field_instance['widget']['settings']['geocoder_field'])) {
+        $handler = geocoder_get_handler($field_instance['widget']['settings']['geocoder_handler']);
+        $field_name = is_array($field_instance['widget']['settings']['geocoder_field']) ? reset($field_instance['widget']['settings']['geocoder_field']) : $field_instance['widget']['settings']['geocoder_field'];
+        $field_info = field_info_field($field_name);
+        // Get values for the data to be geocoded.
+        $langcode = field_language($entity_type, $entity, $field_name);
+        $items = field_get_items($entity_type, $entity, $field_name, $langcode);
+        if (count($items)) {
+          // Check for existing geocoded data.
+          $values = field_get_items($entity_type, $entity, $field_instance['field_name'], $langcode);
+          if ($values === FALSE) {
+            $values = array();
           }
-          elseif (!isset($parent) && isset($form_state['values'][$source][$lang])) {
-            foreach ($form_state['values'][$source][$lang] as $delta => $item) {
-              $values[$delta][] = geocoder_widget_parse_field($item, $field_info['type']);
+          foreach ($items as $delta => $item) {
+            // Geocode (or re-geocode in case of a change) any value from our source field.
+            try {
+              $geometry = call_user_func($handler['field_callback'], $field_info, $item);
             }
+            catch (Exception $e) {
+              drupal_set_message($e->getMessage(), 'error');
+            }
+            $values[$delta] = ($geometry instanceof Geometry ) ? geofield_get_values_from_geometry($geometry) : NULL;
           }
-        }
-      }
-      // To avoid any conflicts, default to text.
-      $field_object = isset($field_info) ? $field_info : array('type' => 'text');
-
-      if (isset($main) && empty($values)) {
-        $item = array('value' => $main);
-        try {
-          $geometry = call_user_func($handler['field_callback'], $field_object, $item);
-        }
-        catch(Exception $e) {
-          drupal_set_message($e->getMessage(),'error');
-          return;
-        }
-
-        if ($geometry) {
-          // There is only one record here so we can use 0
-          $field[$lang][0] = geofield_get_values_from_geometry($geometry);
-        }
-      }
-      else {
-        foreach ($values as $delta => $value) {
-          try {
-            $geometry = call_user_func($handler['field_callback'], $field_object, $item);
-          }
-          catch(Exception $e) {
-            drupal_set_message($e->getMessage(),'error');
-            return;
-          }
-
-          if ($geometry) {
-            $field[$lang][$delta] = geofield_get_values_from_geometry($geometry);
-          }
+          // Filter out any exisitng geofield value without a value in the source field
+          $entity->{$field_instance['field_name']}[$langcode] = array_intersect_key($values, $items);
         }
       }
     }
