diff --git a/location.inc b/location.inc
index af90ac3..c77b484 100644
--- a/location.inc
+++ b/location.inc
@@ -402,6 +402,38 @@ function location_get_provinces($country = 'us') {
 
 // @@@ New in 3.x, document.
 /**
+ * Fetch the cities for a country.
+ */
+function location_get_cities($country = 'us') {
+  static $cities = array();
+  location_standardize_country_code($country);
+  if (isset($cities[$country])) {
+    return $cities[$country];
+  }
+  if ($cache = cache_get("cities:$country", 'cache_location')) {
+    $cities[$country] = $cache->data;
+    return $cities[$country];
+  }
+  location_load_country($country);
+
+  // Get all of the cities from the zipcodes table.
+  $cities_array = array();
+  $result = db_query("
+    SELECT DISTINCT CONCAT(city, ',', state) AS city FROM {zipcodes}
+  ");
+  while ($current_city = db_fetch_array($result)) {
+    $cities_array[$current_city['city']] = $current_city['city'];
+  }
+
+  $cities[$country] = $cities_array;
+  cache_set("cities:$country", $cities[$country], 'cache_location');
+  return $cities[$country];
+}
+
+
+
+// @@@ New in 3.x, document.
+/**
  * Get the translated name of a country code.
  */
 function location_country_name($country = 'us') {
diff --git a/location.module b/location.module
index c0789e0..729dcee 100644
--- a/location.module
+++ b/location.module
@@ -33,6 +33,12 @@ function location_menu() {
     'page callback' => '_location_autocomplete',
     'type' => MENU_CALLBACK,
   );
+  $items['location/autocomplete_city'] = array(
+    'access arguments' => array('access content'),
+    'page callback' => '_location_autocomplete_city',
+    'file' => 'location.inc',
+    'type' => MENU_CALLBACK,
+  );
 
   $items['admin/settings/location'] = array(
     'title' => 'Location',
@@ -609,9 +615,12 @@ function location_locationapi(&$obj, $op, $a3 = NULL, $a4 = NULL, $a5 = NULL) {
           );
 
         case 'city':
+          drupal_add_js(drupal_get_path('module', 'location') .'/location_autocomplete.js');
+          $country = $a5['country'] ? $a5['country'] : variable_get('location_default_country', 'us');
           return array(
             '#type'           => 'textfield',
             '#title'          => t('City'),
+            '#autocomplete_path' => 'location/autocomplete_city/'. $country,
             '#default_value'  => $obj,
             '#size'           => 64,
             '#maxlength'      => 64,
@@ -944,6 +953,49 @@ function _location_autocomplete($country, $string = '') {
 }
 
 /**
+ * Create a list of cities from a given country.
+ *
+ * @param $country
+ *   String. The country code
+ * @param $string
+ *   String (optional). The city name typed by user
+ * @return
+ *   Javascript array. List of cities
+ */
+function _location_autocomplete_city($country, $string = '') {
+  $counter = 0;
+  $string   = strtolower($string);
+  $string   = '/^'. $string .'/';
+  $matches  = array();
+
+  if (strpos($country, ',') !== FALSE) {
+    // Multiple countries specified.
+    $cities = array();
+    $country = explode(',', $country);
+    foreach($country as $c) {
+      $cities = $cities + location_get_cities($c);
+    }
+  }
+  else {
+    $cities = location_get_cities($country);
+  }
+
+  if (!empty($cities)) {
+    while (list($code, $name) = each($cities)) {
+      if ($counter < 5) {
+        if (preg_match($string, strtolower($name))) {
+          $matches[$name] = $name;
+          ++$counter;
+        }
+      }
+    }
+  }
+  echo drupal_to_js($matches);
+  return;
+}
+
+
+/**
  * Epsilon test.
  * Helper function for seeing if two floats are equal.  We could use other functions, but all
  * of them belong to libraries that do not come standard with PHP out of the box.
diff --git a/location_autocomplete.js b/location_autocomplete.js
index 66f8171..f8008a3 100644
--- a/location_autocomplete.js
+++ b/location_autocomplete.js
@@ -31,4 +31,31 @@ Drupal.behaviors.location = function(context) {
       Drupal.behaviors.autocomplete(document);
     }
   }).addClass('location-processed');
+  $('select.location_auto_city:not(.location-processed)', context).change(function(e) {
+    var obj = this;
+    var input = null;
+    var result = this.className.match(/(location_auto_join_[^ ]*)/);
+    if (result) {
+      input = $('.location_auto_city.' + result)
+    }
+    else {
+      // No joining class found, fallback to searching the immediate area.
+      input = $('.location_auto_city', $(this).parents('fieldset:first, .views-exposed-form:first'))
+    }
+
+    if (input && input.length) {
+      //Unbind events on province field and empty its value
+      input.unbind().val('');
+      input.each(function(i) {
+        //Get the (hidden) *-autocomplete input element
+        var input_autocomplete = $('#' + this.id + '-autocomplete');
+        // Update autocomplete url
+        input_autocomplete.val(input_autocomplete.val().substr(0, input_autocomplete.val().lastIndexOf('/') + 1) + $(obj).val());
+        // Mark as not processed.
+        input_autocomplete.removeClass('autocomplete-processed');
+      });
+      // Reprocess.
+      Drupal.behaviors.autocomplete(document);
+    }
+  }).addClass('location-processed');  
 };
