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'); };