diff --git a/css/exposed_filters.css b/css/exposed_filters.css
new file mode 100644
index 0000000..c2fb7fa
--- /dev/null
+++ b/css/exposed_filters.css
@@ -0,0 +1,7 @@
+.exposed-proximity-radius .form-type-select,
+.exposed-proximity-radius .form-type-textfield {
+  float: left;
+}
+.exposed-proximity-radius .form-type-select {
+  padding-top: 3px;
+}
diff --git a/geofield.info b/geofield.info
index 2cd4dad..f09e262 100644
--- a/geofield.info
+++ b/geofield.info
@@ -14,3 +14,7 @@ files[] = views/geofield.views.inc
 files[] = views/handlers/geofield_handler_sort.inc
 files[] = views/handlers/geofield_handler_field.inc
 files[] = views/handlers/geofield_handler_filter.inc
+files[] = views/handlers/geofield_handler_proximity_filter.inc
+files[] = views/handlers/geofield_handler_proximity_string_filter.inc
+
+stylesheets[all][] = css/exposed_filters.css
diff --git a/views/geofield.views.inc b/views/geofield.views.inc
index f685b8b..e605c39 100644
--- a/views/geofield.views.inc
+++ b/views/geofield.views.inc
@@ -46,6 +46,21 @@ function geofield_field_views_data($field) {
           'real_field' => $table_name,
         ),
       );
+
+      //Text Proximity Search
+      $data[$table_name]['field_geofield_proximity'] = array(
+        'group' => 'Content',
+        'title' => $table_data[$field_name]['title'] . ' (' . $table_name . ': Text proximity search.)',
+        'title short' => $table_data[$field_name]['title short'] . ' (' . $table_name . ': Text proximity search.)',
+        'help' => $table_data[$field_name]['help'],
+        'filter' => array(
+          'field' => 'field_geofield_proximity',
+          'table' => $table_name,
+          'handler' => 'geofield_handler_proximity_filter',
+          'field_name' => $field['field_name'],
+          'real_field' => $table_name,
+        ),
+      );
     }
   }
   return $data;
@@ -73,3 +88,15 @@ function geofield_radius_options() {
     '3444' => t('Nautical Miles'),
   );
 }
+
+/**
+ * Validate proximity search filter to ensure that the distance is set
+ */
+function geofield_proximity_validate($form, &$form_state) {
+  $prox = $form_state['values']['field_geofield_proximity'];
+
+  if(!empty($prox['value']) && empty($prox['radius']['dist'])) {
+    form_set_error('field_geofield_proximity][radius][dist', t('If a search is made, the radius must be set as well.'));
+  }
+  
+}
diff --git a/views/handlers/geofield_handler_proximity_filter.inc b/views/handlers/geofield_handler_proximity_filter.inc
new file mode 100644
index 0000000..b06266a
--- /dev/null
+++ b/views/handlers/geofield_handler_proximity_filter.inc
@@ -0,0 +1,204 @@
+<?php
+
+/**
+ * @file
+ * Text proximity search implementation.
+ */
+
+//TODO: Allow this to also work as an argument
+
+class geofield_handler_proximity_filter extends views_handler_filter {
+  var $always_multiple = TRUE;
+  var $no_operator = TRUE;
+  function option_definition() {
+    $options = parent::option_definition();
+
+    $options['value']['default'] = array();
+    $options['expose']['contains'] = array(
+      'radius' => array(
+        'dist' => array('default' => ''),
+        'radius_of_earth' => array('default' => '6371'),
+      ),
+      'expose_distance' => array('default' => FALSE),
+    );
+
+    return $options;
+  }
+
+  function value_form(&$form, &$form_state) {
+
+    $form['value'] = array(
+      '#tree' => TRUE,
+    );
+
+    if (!empty($form_state['exposed'])) {
+      $identifier = $this->options['expose']['identifier'];
+    }
+    else {
+      $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']);
+    }
+
+    if($form_state['exposed'] && $this->options['expose']['expose_distance']) {
+      //Add ablity to put distance selection right here
+      $form['value']['value'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Origin'),
+        '#size' => 20,
+        '#default_value' => $this->value,
+        '#title_display' => 'invisible',
+      );
+
+      $form['value']['radius'] = array(
+        '#type'       => 'fieldset',
+        '#title'      => t('Radius'),
+        '#tree'       => TRUE,
+        '#attributes' => array(
+          'class'     => array('exposed-proximity-radius'),
+        ),
+      );
+      $form['value']['radius']['dist'] = array(
+        '#type'          => 'textfield',
+        '#title'         => t('Distance'),
+        '#default_value' => (!empty($this->options['expose']['radius']['dist'])) ? $this->options['expose']['radius']['dist'] : '',
+        '#size'          => 4,
+        '#title_display' => 'invisible',
+      );
+
+      $form['value']['radius']['radius_of_earth'] = array(
+        '#type'          => 'select',
+        '#title'         => t('Unit of Measurement'),
+        '#options'       => geofield_radius_options(),
+        '#default_value' => (!empty($this->options['expose']['radius']['unit'])) ? $this->options['expose']['radius']['unit'] : '6371',
+        '#title_display' => 'invisible',
+      );
+
+      $form['#validate'][] = 'geofield_proximity_validate';
+
+    }
+    else {
+      //TODO: Add auto complete using google places
+      $form['value'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Origin'),
+        '#size' => 20,
+        '#default_value' => $this->value,
+      );
+    }
+
+    if(!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) {
+      $form_state['input'][$identifier] = $this->value;
+    }
+
+    if(!isset($form['value'])) {
+      //Ensure something is set
+      $form['value'] = array(
+        '#type' => 'value',
+        '#value' => NULL,
+      );
+    }
+  }
+
+  /**
+   * Add other exposed form options
+   */
+  function expose_form(&$form, &$form_state) {
+    parent::expose_form($form, $form_state);
+
+    //FIXME: Add option to allow for this title to be set to a different word
+    $form['expose']['radius'] = array(
+      '#type'       => 'fieldset',
+      '#title'      => t('Radius'),
+      '#tree'       => TRUE,
+      '#attributes' => array(
+        'class'     => array('exposed-proximity-radius'),
+      ),
+    );
+
+    $form['expose']['radius']['dist'] = array(
+      '#type'          => 'textfield',
+      '#title'         => t('Distance'),
+      '#default_value' => (!empty($this->options['expose']['radius']['dist'])) ? $this->options['expose']['radius']['dist'] : '',
+      '#size'          => 4,
+      '#title_display' => 'invisible',
+    );
+
+    $form['expose']['radius']['radius_of_earth'] = array(
+      '#type'          => 'select',
+      '#title'         => t('Unit of Measurement'),
+      '#options'       => geofield_radius_options(),
+      '#default_value' => (!empty($this->options['expose']['radius']['unit'])) ? $this->options['expose']['radius']['unit'] : '6371',
+      '#title_display' => 'invisible',
+    );
+
+    $form['expose']['expose_distance'] = array(
+      '#type'          => 'checkbox',
+      '#title'         => t('Show distance and units in exposed filter'),
+      '#default_value' => !empty($this->options['expose']['expose_distance']),
+      '#description'   => t('Checking this will add the distance and unit of measurement form items to the exposed filter allowing end users to change their values.'),
+    );
+  }
+
+  function expose_options() {
+    parent::expose_options();
+    $this->options['expose']['dist'] = '';
+    $this->options['expose']['radius_of_earth'] = '6371';
+    $this->options['expose']['expose_distance'] = FALSE;
+  }
+
+  function query() {
+    if(!empty($this->value['value'])) {
+      //TODO: Allow for geocoder handler to be specified
+      $geocoded = geocoder('google', $this->value['value']);
+      if($geocoded) {
+        $this->value['lat']  = $geocoded->coords[1];
+        $this->value['long'] = $geocoded->coords[0];
+
+        $lat_alias = $this->query->add_field($this->table_alias, $this->definition['field_name'] . '_lat');
+        $lon_alias = $this->query->add_field($this->table_alias, $this->definition['field_name'] . '_lon');
+        $this->ensure_my_table();
+        $field = "$this->table_alias.$this->real_field";
+
+        //If exposed, use the submitted values
+        if($this->options['expose']['expose_distance']) {
+          $radius = $this->value['radius']['radius_of_earth'];
+          $dist = $this->value['radius']['dist'];
+        }
+        else {
+          $radius = $this->options['expose']['radius']['radius_of_earth'];
+          $dist = $this->options['expose']['radius']['dist'];
+        }
+
+        $haversine = geofield_haversine($this->value['lat'], $this->value['long'], $this->table_alias . '.' . $lat_alias, $this->table_alias . '.' . $lon_alias, $radius);
+
+        $this->query->add_where_expression($this->options['group'], $haversine . ' <= ' . $dist);
+      }
+    }
+  }
+
+  function accept_exposed_input($input) {
+    if(empty($this->options['exposed'])) {
+      return TRUE;
+    }
+    //rewrite input value
+    if(!empty($this->options['expose']['identifier'])) {
+      $value = &$input[$this->options['expose']['identifier']];
+      if(!is_array($value)) {
+        $value = array(
+          'value' => $value,
+        );
+      }
+      
+      //Right now this shouldn't get hit as there's a validate function to ensure distance is also set
+      //Only accept input if the distance is set when the value is set
+      if(is_array($value) && !empty($value['value']) && isset($value['radius']) && empty($value['radius']['dist']))
+      {
+        return FALSE;
+      }
+    }
+    return parent::accept_exposed_input($input);
+  }
+
+  function value_submit($form, &$form_state) {
+    $form_state['values']['options']['value'] = $form['value']['#value'];
+  }
+}
