diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..948542f
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,11 @@
+{
+    "name": "drupal/geocoder",
+    "description": "Provides the geocoder module.",
+    "type": "drupal-module",
+    "license": "GPL-2.0+",
+    "minimum-stability": "dev",
+    "require": {
+        "willdurand/geocoder": "~2.7",
+        "guzzle/guzzle": "~3.8"
+    }
+}
diff --git a/geocoder.info.yml b/geocoder.info.yml
index c28bea1..1565279 100644
--- a/geocoder.info.yml
+++ b/geocoder.info.yml
@@ -1,6 +1,5 @@
 name: Geocoder
 type: module
 description: Converts strings into lat/lon.
-version: 8.1-dev
 core: 8.x
 package: Geo
diff --git a/geocoder.module b/geocoder.module
index 567e09f..0e99926 100644
--- a/geocoder.module
+++ b/geocoder.module
@@ -1,8 +1,23 @@
 <?php
 
 /**
- * Implements hook_composer_json_alter().
+ * Geocodes the given string.
+ *
+ * @param $searchstring
+ *   A string representing a location to be geocoded, e.g. an address.
+ * @return \Geocoder\Result\ResultInterface|\Geocoder\ResultInterface|NULL
+ *   The determined geocode if geocoding was successful, NULL otherwise.
  */
-function geocoder_composer_json_alter(&$json) {
-  $json['require']['willdurand/geocoder'] = '2.7.0';
+function geocoder_geocode($searchstring) {
+  $adapter = new \Geocoder\HttpAdapter\GuzzleHttpAdapter();
+  $geocoder = new \Geocoder\Geocoder();
+  $geocoder->registerProvider(new \Geocoder\Provider\OpenStreetMapProvider($adapter));
+
+  try {
+    $geocode = $geocoder->geocode($searchstring);
+    return $geocode;
+  } catch (Exception $e) {
+    watchdog_exception('geocoder', $e);
+  }
+  return NULL;
 }
diff --git a/geocoder_geofield/geocoder_geofield.info.yml b/geocoder_geofield/geocoder_geofield.info.yml
new file mode 100644
index 0000000..431ae65
--- /dev/null
+++ b/geocoder_geofield/geocoder_geofield.info.yml
@@ -0,0 +1,8 @@
+name: Geocoder Geofield Integration
+type: module
+description: Populate geofields using geocoder.
+core: 8.x
+package: Geo
+dependencies:
+  - geocoder
+  - geofield
diff --git a/geocoder_geofield/geocoder_geofield.module b/geocoder_geofield/geocoder_geofield.module
new file mode 100644
index 0000000..7a129a0
--- /dev/null
+++ b/geocoder_geofield/geocoder_geofield.module
@@ -0,0 +1,352 @@
+<?php
+
+/**
+ * Returns a list of functions for formatting field values into search strings
+ * for the geocoder.
+ *
+ * @param $name
+ *   Set to a field name to only retrieve the respective callback name.
+ * @return mixed
+ *   The respective callback name if $name is specified, the complete list of
+ *   callback functions keyed by field names otherwise.
+ */
+function geocoder_geofield_searchstring_callbacks($name = FALSE) {
+  $callbacks = &drupal_static(__FUNCTION__);
+  if (!isset($callbacks)) {
+    $callbacks = array(
+      'addressfield' => 'geocoder_geofield_format_addressfield',
+      'string' => 'geocoder_geofield_format_textfield',
+      'address' => 'geocoder_geofield_format_address',
+    );
+  }
+  if ($name !== FALSE) {
+    return isset($callbacks[$name]) ? $callbacks[$name] : NULL;
+  }
+  return $callbacks;
+}
+
+/**
+ * Returns a list of available source fields for geocoding on the given entity
+ * type and bundle.
+ *
+ * Availability is determined by checking whether we know how to convert a
+ * respective field value into a searchstring.
+ *
+ * @see geocoder_geofield_searchstring_callbacks
+ *
+ * @param $entity_type_id
+ *   The target entity type id.
+ * @param $bundle
+ *   The target bundle name.
+ * @return \Drupal\Core\Field\FieldDefinitionInterface[]
+ *   List of field definitions.
+ */
+function geocoder_geofield_get_available_source_fields($entity_type_id, $bundle) {
+  $available_types = array_keys(geocoder_geofield_searchstring_callbacks());
+
+  $field_list = Drupal::entityManager()
+    ->getFieldDefinitions($entity_type_id, $bundle);
+
+  return array_filter($field_list, function (\Drupal\Core\Field\FieldDefinitionInterface $definition) use ($available_types) {
+    return in_array($definition->getType(), $available_types);
+  });
+}
+
+/**
+ * Maps an array of FieldDefinitionInterface objects to a list of name-label
+ * pairs, e.g. for use in form input options.
+ *
+ * @param \Drupal\Core\Field\FieldDefinitionInterface[] $field_list
+ *   List of field definitions.
+ * @return array
+ *   List of field definitions.
+ */
+function geocoder_geofield_map_fields_to_options(array $field_list) {
+  $options = array();
+  foreach ($field_list as $definition) {
+    $options[$definition->getName()] = $definition->getLabel();
+  }
+  return $options;
+}
+
+/**
+ * Implements hook_field_widget_third_party_settings_form().
+ */
+function geocoder_geofield_field_widget_third_party_settings_form(\Drupal\Core\Field\WidgetInterface $plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $form_mode, $form, \Drupal\Core\Form\FormStateInterface $form_state) {
+  if (geocoder_geofield_widget_is_supported($plugin)) {
+    $element['enabled'] = array(
+      '#type' => 'checkbox',
+      '#title' => Drupal::translation()
+        ->translate('Use Geocoder to automatically set location from text.'),
+      '#default_value' => $plugin->getThirdPartySetting('geocoder_geofield', 'enabled', FALSE),
+    );
+
+    $source_fields = geocoder_geofield_get_available_source_fields($field_definition->getTargetEntityTypeId(), $field_definition->getTargetBundle());
+    $source_options = geocoder_geofield_map_fields_to_options($source_fields);
+    $element['source'] = array(
+      '#title' => Drupal::translation()->translate('Source field'),
+      '#type' => 'select',
+      '#options' => $source_options,
+      '#states' => array(
+        'invisible' => array(
+          ':input[name="fields[field_geofield][settings_edit_form][third_party_settings][geocoder_geofield][enabled]"]' => array('checked' => FALSE),
+        ),
+      ),
+      '#default_value' => $plugin->getThirdPartySetting('geocoder_geofield', 'source', key($source_options)),
+    );
+    return $element;
+  }
+}
+
+/**
+ * Implements hook_field_widget_settings_summary_alter().
+ */
+function geocoder_geofield_field_widget_settings_summary_alter(&$summary, $context) {
+  if (geocoder_geofield_widget_is_supported($context['widget'])) {
+    $enabled = $context['widget']->getThirdPartySetting('geocoder_geofield', 'enabled', FALSE);
+    if ($enabled) {
+      $summary[] = Drupal::translation()
+        ->translate('Geocoding from %source is enabled.', array(
+          '%source' => $context['widget']->getThirdPartySetting('geocoder_geofield', 'source'),
+        ));
+    }
+    else {
+      $summary[] = Drupal::translation()
+        ->translate('Geocoding is not enabled.');
+    }
+  }
+}
+
+/**
+ * Check whether geocoding is supported for a given widget.
+ *
+ * @param \Drupal\Core\Field\WidgetInterface $widget_obj
+ * @return bool|string
+ */
+function geocoder_geofield_widget_is_supported(\Drupal\Core\Field\WidgetInterface $widget_obj) {
+  try {
+    return geocoder_geofield_geocoder_value_callback($widget_obj);
+  } catch (InvalidArgumentException $e) {
+    return FALSE;
+  }
+}
+
+/**
+ * Determines a callback function which converts a geocode into the proper value
+ * format for the given widget type.
+ *
+ * @param \Drupal\Core\Field\WidgetInterface $widget_obj
+ *   The target widget type.
+ * @return callable
+ *   The value function callback.
+ * @throws Exception
+ *   If the widget type is invalid.
+ */
+function geocoder_geofield_geocoder_value_callback(\Drupal\Core\Field\WidgetInterface $widget_obj) {
+  if ($widget_obj instanceof \Drupal\geofield\Plugin\Field\FieldWidget\GeofieldDefaultWidget) {
+    return 'geocoder_geofield_wkt_value';
+  }
+  if ($widget_obj instanceof \Drupal\geofield\Plugin\Field\FieldWidget\GeofieldLatLonWidget) {
+    return 'geocoder_geofield_lat_lon_value';
+  }
+  if ($widget_obj instanceof \Drupal\geofield\Plugin\Field\FieldWidget\GeofieldBoundsWidget) {
+    return 'geocoder_geofield_bounds_value';
+  }
+  throw new InvalidArgumentException("Geocoder: unknown widget type.");
+}
+
+/**
+ * @param \Geocoder\Result\ResultInterface $geocode
+ *   The new geocode.
+ * @return string
+ *   WKT formatted string.
+ */
+function geocoder_geofield_wkt_value(\Geocoder\Result\ResultInterface $geocode) {
+  return \Drupal::service('geofield.wkt_generator')
+    ->WktBuildPoint(array(
+      round($geocode->getLongitude(), 7),
+      round($geocode->getLatitude(), 7)
+    ));
+}
+
+/**
+ * @param \Geocoder\Result\ResultInterface $geocode
+ *   The new geocode.
+ * @return array
+ *   Array of coordinate values, keyed by lat and lon.
+ */
+function geocoder_geofield_lat_lon_value(\Geocoder\Result\ResultInterface $geocode) {
+  return array(
+    'lon' => round($geocode->getLongitude(), 7),
+    'lat' => round($geocode->getLatitude(), 7)
+  );
+}
+
+/**
+ * @param \Geocoder\Result\ResultInterface $geocode
+ *   The new geocode.
+ * @return array|string
+ *   Array of bounds, keyed by top, bottom, left and right.
+ */
+function geocoder_geofield_bounds_value(\Geocoder\Result\ResultInterface $geocode) {
+  $bounds = $geocode->getBounds();
+  return array(
+    'top' => $bounds['south'],
+    'bottom' => $bounds['bottom'],
+    'left' => $bounds['west'],
+    'right' => $bounds['east'],
+  );
+}
+
+/**
+ * Implements hook_field_widget_form_alter().
+ */
+function geocoder_geofield_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
+  if (geocoder_geofield_widget_is_supported($context['widget']) && $context['widget']->getThirdPartySetting('geocoder_geofield', 'enabled', FALSE)) {
+    // Keep track of widget settings in form state. This is primarily done to
+    // make sure we reuse the wrapper id when rebuilding the form.
+    $target_field_name = $context['items']->getFieldDefinition()->getName();
+    $state_key = array('geocoder_geofield', $target_field_name);
+    if (!($settings = $form_state->get($state_key, FALSE))) {
+      // Field definition objects for source and target fields.
+      $target_field = $context['items']->getFieldDefinition();
+      $source_field_name = $context['widget']->getThirdPartySetting('geocoder_geofield', 'source');
+      $source_field = \Drupal\field\Entity\FieldConfig::loadByName($target_field->getTargetEntityTypeId(), $target_field->getTargetBundle(), $source_field_name);
+
+      $settings = array(
+        'wrapper_id' => \Drupal\Component\Utility\Html::getUniqueId('geocoder-wrapper'),
+        'target' => $target_field,
+        'geocoder value callback' => geocoder_geofield_geocoder_value_callback($context['widget']),
+        'source' => $source_field,
+        'searchstring callback' => geocoder_geofield_searchstring_callbacks($source_field->getType()),
+      );
+      $form_state->set($state_key, $settings);
+    }
+
+    // Stop now if the source field is not in the current form (e.g. hidden).
+    if (!isset($context['form'][$settings['source']->getName()])) {
+      return;
+    }
+
+    // Wrap value element into div for ajax replacement.
+    $element['value']['#prefix'] = '<div id="' . $settings['wrapper_id'] . '">';
+    $element['value']['#suffix'] = '</div>';
+
+    // Attach submit button for updating value from source field.
+    $element['geocoder_update'] = array(
+      '#type' => 'submit',
+      '#submit' => array('geocoder_geofield_ajax_submit'),
+      '#value' => Drupal::translation()
+        ->translate('Update @target_field from @source_field', array(
+          '@target_field' => $settings['target']->getLabel(),
+          '@source_field' => $settings['source']->getLabel(),
+        )),
+      '#ajax' => array(
+        'callback' => 'geocoder_geofield_ajax_update',
+        'wrapper' => $settings['wrapper_id'],
+        'method' => 'replaceWith',
+        'effect' => 'fade',
+      ),
+      '#geocoder_settings' => $settings,
+      // Only validate the address field, as that's the only value we need.
+      '#limit_validation_errors' => array(array($settings['source']->getName())),
+    );
+  }
+}
+
+/**
+ * Submit handler for the "geocoder_update" button.
+ *
+ * Geocodes the source field value, updates the respective geofield input value,
+ * and triggers a form rebuild.
+ */
+function geocoder_geofield_ajax_submit($form, \Drupal\Core\Form\FormStateInterface $form_state) {
+  $settings = $form_state->getTriggeringElement()['#geocoder_settings'];
+  if ($settings == FALSE) {
+    throw new LogicException('Invalid AJAX submit handler call.');
+  }
+
+  $value = $form_state->getValue($settings['source']->getName());
+  $searchstring = call_user_func($settings['searchstring callback'], $value);
+
+  if ($geocode = geocoder_geocode($searchstring)) {
+    // Translate geocoded values into value format corresponding to the
+    // respective geofield widget.
+    $value = call_user_func($settings['geocoder value callback'], $geocode);
+
+    // Change the user input to reflect the coordinates of the geocoded address.
+    // This seems to only work properly if we update the raw user input. If we
+    // only change the form "values" instead then the rebuilt form elements
+    // do not reflect the new coordinates.
+    // @todo Figure out whether this can be solved in a more elegant way.
+    $user_input = $form_state->getUserInput();
+    $user_input[$settings['target']->getName()][0]['value'] = $value;
+    $form_state->setUserInput($user_input);
+
+    $form_state->setRebuild(TRUE);
+  }
+  else {
+    drupal_set_message(\Drupal::translation()
+      ->translate("Address was not found: %address", array(
+        '%address' => $searchstring,
+      )), "error");
+  }
+}
+
+/**
+ * Ajax callback handler. Returns the updated form element after geocoding.
+ */
+function geocoder_geofield_ajax_update($form, \Drupal\Core\Form\FormStateInterface $form_state) {
+  $target_field_name = $form_state->getTriggeringElement()['#geocoder_settings']['target']->getName();
+  return $form[$target_field_name]['widget'][0]['value'];
+}
+
+/**
+ * Format an "addressfield" value into a search string for geocoding.
+ *
+ * @param $addresses
+ *   The addressfield value to be geocoded.
+ * @return string
+ *   A search string for geocoding.
+ */
+function geocoder_geofield_format_addressfield($addresses) {
+  $address = $addresses[0];
+  // @todo Custom addressfield handler which formats address for geocoding. Should consider how to get best results.
+  $address = addressfield_generate($address, array('address'), array('mode' => 'render'));
+  $searchstring = drupal_render($address);
+  // @todo Move to custom addressfield handler.
+  $searchstring = strip_tags($searchstring);
+  $searchstring = trim(preg_replace('/\s+/', ' ', $searchstring));
+  return $searchstring;
+}
+
+/**
+ * Format a "text" field value into a search string for geocoding.
+ *
+ * @param $text
+ *   The text field value.
+ * @return string
+ *   A search string for geocoding.
+ */
+function geocoder_geofield_format_textfield($text) {
+
+  //geocoder expects a string
+  $string = $text[0]['value'];
+
+  return $string;
+}
+
+/**
+ *
+ * @param $text
+ *   The text field value.
+ * @return string
+ *   A search string for geocoding.
+ */
+function geocoder_geofield_format_address($text) {
+
+  //geocoder expects a string
+  $string = $text[0]['address_line1'].' '.$text[0]['address_line2'].', '.$text[0]['locality'].' '.$text[0]['postal_code'];
+
+  return $string;
+}
diff --git a/src/Form/APIKeysForm.php b/src/Form/APIKeysForm.php
index 85a1f06..ce2446b 100644
--- a/src/Form/APIKeysForm.php
+++ b/src/Form/APIKeysForm.php
@@ -21,6 +21,13 @@ class APIKeysForm extends ConfigFormBase {
   /**
    * {@inheritdoc}.
    */
+  protected function getEditableConfigNames() {
+    return array('geocoder.google');
+  }
+
+  /**
+   * {@inheritdoc}.
+   */
   public function buildForm(array $form, FormStateInterface $form_state) {
     $config = $this->config('geocoder.google');
 
diff --git a/src/Plugin/Field/FieldWidget/GeocoderDefaultWidget.php b/src/Plugin/Field/FieldWidget/GeocoderDefaultWidget.php
new file mode 100644
index 0000000..0e97d01
--- /dev/null
+++ b/src/Plugin/Field/FieldWidget/GeocoderDefaultWidget.php
@@ -0,0 +1,143 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\geocoder_geofield\Plugin\Field\FieldWidget\Geocoder_geofieldDefaultWidget.
+ */
+
+namespace Drupal\geocoder_geofield\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Form\FormStateInterface;
+use Symfony\Component\Validator\ConstraintViolationInterface;
+
+/**
+ * Widget implementation of the 'geocoder_default' widget.
+ *
+ * @FieldWidget(
+ *   id = "geocoder_widget",
+ *   label = @Translation("Geocoder"),
+ *   field_types = {
+ *     "string"
+ *   },
+ * )
+ */
+class GeocoderDefaultWidget extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array(
+      'destination_field' => "",
+      'placeholder' => "",
+      'geocoder_engine' => "",
+    ) + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+
+    $entityFieldDefinitions = \Drupal::entityManager()->getFieldDefinitions($this->fieldDefinition->entity_type, $this->fieldDefinition->bundle);
+
+    $options = array();
+    foreach ($entityFieldDefinitions as $id => $definition) {
+      if ($definition->getType() == 'geofield') {
+        $options[$id] = $definition->getLabel();
+      }
+    }
+
+    $elements['destination_field'] = array(
+      '#type' => 'select',
+      '#title' => $this->t('Destination Geo Field'),
+      '#default_value' => $this->getSetting('destination_field'),
+      '#required' => TRUE,
+      '#options' => $options,
+    );
+
+    $elements['placeholder'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Placeholder'),
+      '#default_value' => $this->getSetting('placeholder'),
+      '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
+    );
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $summary[] = $this->t('Destination Geofield: !destination', array('!destination' => $this->getSetting('destination_field')));
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $main_widget = $element + array(
+      '#type' => 'textfield',
+      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
+      '#placeholder' => $this->getSetting('placeholder'),
+      '#attributes' => array('class' => array('geocoder-source')),
+    );
+
+    $element['value'] = $main_widget;
+
+    $source_field_id = 'edit-' . str_replace('_', '-', $items->getFieldDefinition()->getName()) . '-' . $delta . '-value';
+    $destination_field_id = 'edit-' . str_replace('_', '-', $this->getSetting('destination_field')) . '-wrapper';
+    $google_api_key = \Drupal::config('geocoder.google')->get('api_key');
+
+    $element['#attached'] = array(
+      'library' => array(
+        array('system', 'jquery.ui.autocomplete'),
+      ),
+      'js' => array(
+        'sites/all/libraries/geocoder-js/dist/geocoder.js',
+        drupal_get_path('module', 'geocoder') . '/js/geocoderWidget.js',
+        array(
+          'data' => array(
+            'geocoder' => array(
+              'engine' => 'google',
+              'api_key' => $google_api_key,
+              'fields' => array(
+                array(
+                  'sourceField' => $source_field_id,
+                  'destinationField' => $destination_field_id,
+                  'sourceType' => 'geofield',
+                )
+              ),
+            ),
+          ),
+          'type' => 'setting',
+        ),
+      ),
+    );
+
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
+    if ($violation->arrayPropertyPath == array('format') && isset($element['format']['#access']) && !$element['format']['#access']) {
+      // Ignore validation errors for formats if formats may not be changed,
+      // i.e. when existing formats become invalid. See filter_process_format().
+      return FALSE;
+    }
+    return $element;
+  }
+}
diff --git a/src/Plugin/Field/FieldWidget/GeocoderWidget.php b/src/Plugin/Field/FieldWidget/GeocoderWidget.php
deleted file mode 100644
index d104e18..0000000
--- a/src/Plugin/Field/FieldWidget/GeocoderWidget.php
+++ /dev/null
@@ -1,143 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\geocoder\Plugin\Field\FieldWidget\GeocoderWidget.
- */
-
-namespace Drupal\geocoder\Plugin\Field\FieldWidget;
-
-use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Core\Field\WidgetBase;
-use Drupal\Core\Form\FormStateInterface;
-use Symfony\Component\Validator\ConstraintViolationInterface;
-
-/**
- * Plugin implementation of the 'geocoder_default' widget.
- *
- * @FieldWidget(
- *   id = "geocoder_widget",
- *   label = @Translation("Geocoder"),
- *   field_types = {
- *     "string"
- *   },
- * )
- */
-class GeocoderWidget extends WidgetBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function defaultSettings() {
-    return array(
-      'destination_field' => "",
-      'placeholder' => "",
-      'geocoder_engine' => "",
-    ) + parent::defaultSettings();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function settingsForm(array $form, FormStateInterface $form_state) {
-    $elements = parent::settingsForm($form, $form_state);
-
-    $entityFieldDefinitions = \Drupal::entityManager()->getFieldDefinitions($this->fieldDefinition->entity_type, $this->fieldDefinition->bundle);
-
-    $options = array();
-    foreach ($entityFieldDefinitions as $id => $definition) {
-      if ($definition->getType() == 'geofield') {
-        $options[$id] = $definition->getLabel();
-      }
-    }
-
-    $elements['destination_field'] = array(
-      '#type' => 'select',
-      '#title' => $this->t('Destination Geo Field'),
-      '#default_value' => $this->getSetting('destination_field'),
-      '#required' => TRUE,
-      '#options' => $options,
-    );
-
-    $elements['placeholder'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Placeholder'),
-      '#default_value' => $this->getSetting('placeholder'),
-      '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
-    );
-
-    return $elements;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function settingsSummary() {
-    $summary = array();
-    $summary[] = $this->t('Destination Geofield: !destination', array('!destination' => $this->getSetting('destination_field')));
-    $placeholder = $this->getSetting('placeholder');
-    if (!empty($placeholder)) {
-      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
-    }
-
-    return $summary;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
-    $main_widget = $element + array(
-      '#type' => 'textfield',
-      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
-      '#placeholder' => $this->getSetting('placeholder'),
-      '#attributes' => array('class' => array('geocoder-source')),
-    );
-
-    $element['value'] = $main_widget;
-
-    $source_field_id = 'edit-' . str_replace('_', '-', $items->getFieldDefinition()->getName()) . '-' . $delta . '-value';
-    $destination_field_id = 'edit-' . str_replace('_', '-', $this->getSetting('destination_field')) . '-wrapper';
-    $google_api_key = \Drupal::config('geocoder.google')->get('api_key');
-
-    $element['#attached'] = array(
-      'library' => array(
-        array('system', 'jquery.ui.autocomplete'),
-      ),
-      'js' => array(
-        'sites/all/libraries/geocoder-js/dist/geocoder.js',
-        drupal_get_path('module', 'geocoder') . '/js/geocoderWidget.js',
-        array(
-          'data' => array(
-            'geocoder' => array(
-              'engine' => 'google',
-              'api_key' => $google_api_key,
-              'fields' => array(
-                array(
-                  'sourceField' => $source_field_id,
-                  'destinationField' => $destination_field_id,
-                  'sourceType' => 'geofield',
-                )
-              ),
-            ),
-          ),
-          'type' => 'setting',
-        ),
-      ),
-    );
-
-    return $element;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
-    if ($violation->arrayPropertyPath == array('format') && isset($element['format']['#access']) && !$element['format']['#access']) {
-      // Ignore validation errors for formats if formats may not be changed,
-      // i.e. when existing formats become invalid. See filter_process_format().
-      return FALSE;
-    }
-    return $element;
-  }
-}
