简体   繁体   中英

jQuery Geocode to get Postal Address

I am weak on jQuery and Javascript. I would like to take this existing code and have it deliver the users full address in a postal format... like what you would put on a letter or fedex envelop.

User begins to type address in the address box and the jQuery auto complete kicks in. When user sees full address they then click on the address and I would like it to then propogate a test box with the users selection, but in the postal format.

Here is the HTML page

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title>Get Address Details</title>
        <script type="text/javascript" src="js/jquery-1.6.4.min.js"></script>
        <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
        <script src="js/jquery-ui-1.8.7.min.js"></script>
        <script src="js/jquery.ui.addresspicker.js"></script>
        <script type="text/javascript">
            $(document).ready(function () {
                $( "#address1" ).addresspicker({
                              elements: {
                                locality: '#city',
                                lat:      '#lat',
                                lng:      '#lng',
                                country:  '#country'
                              }
                            });
        });
        </script>

</head>

<body>

 <form action="submit.php" method="post">
      <fieldset style="width: 300px; margin-bottom: 100px;"><legend>begin typing address</legend>
      <label for="address1">Input Address: </label><input name="address1" id="address1" type="text"><br /></fieldset>
      <fieldset style="width: 300px; text-align: right;"><legend>see results here</legend>
      <label for="address2">Street Address: </label><input name="address2" id="address2" type="text"><br />

      <label for="lat">Lat: </label><input name="lat" id="lat" type="text"><br />

      <label for="lng">Lng: </label><input name="lng" id="lng" type="text"><br />

      <label for="city">City: </label><input name="city" id="city" type="text"><br />

      <label for="country">Country: </label><input name="country" id="country" type="text"><br /><br />

      <label for="postal">Postal Address: </label><textarea name="postal" id="postal" ></textarea><br />

      </fieldset>

</form>
</body>

</html>

The javascript page for the address picker is below, and the other JS pages are current versions

/*
 * jQuery UI addresspicker @VERSION
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Progressbar
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 *   jquery.ui.autocomplete.js
 */
(function( $, undefined ) {

$.widget( "ui.addresspicker", {
    options: {
      appendAddressString: "",
        mapOptions: {
          zoom: 5,
          center: new google.maps.LatLng(46, 2),
          scrollwheel: false,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        },
        elements: {
          map: false,
          lat: false,
          lng: false,
          locality: false,
          country: false
        },
      draggableMarker: true
    },

    marker: function() {
        return this.gmarker;
    },

    map: function() {
      return this.gmap;
    },

  updatePosition: function() {
    this._updatePosition(this.gmarker.getPosition());
  },

  reloadPosition: function() {
    this.gmarker.setVisible(true);
    this.gmarker.setPosition(new google.maps.LatLng(this.lat.val(), this.lng.val()));
    this.gmap.setCenter(this.gmarker.getPosition());
  },

  selected: function() {
    return this.selectedResult;
  },

    _create: function() {
      this.geocoder = new google.maps.Geocoder();
      this.element.autocomplete({
            source: $.proxy(this._geocode, this),
            focus:  $.proxy(this._focusAddress, this),
            select: $.proxy(this._selectAddress, this)
        });

        this.lat      = $(this.options.elements.lat);
        this.lng      = $(this.options.elements.lng);
        this.locality = $(this.options.elements.locality);
        this.country  = $(this.options.elements.country);
        if (this.options.elements.map) {
          this.mapElement = $(this.options.elements.map);
        this._initMap();
        }
    },

  _initMap: function() {
    if (this.lat && this.lat.val()) {
      this.options.mapOptions.center = new google.maps.LatLng(this.lat.val(), this.lng.val());
    }

    this.gmap = new google.maps.Map(this.mapElement[0], this.options.mapOptions);
    this.gmarker = new google.maps.Marker({
      position: this.options.mapOptions.center,
      map:this.gmap,
      draggable: this.options.draggableMarker});
    google.maps.event.addListener(this.gmarker, 'dragend', $.proxy(this._markerMoved, this));
    this.gmarker.setVisible(false);
  },

  _updatePosition: function(location) {
    if (this.lat) {
      this.lat.val(location.lat());
    }
    if (this.lng) {
      this.lng.val(location.lng());
    }
  },

  _markerMoved: function() {
    this._updatePosition(this.gmarker.getPosition());
  },

  // Autocomplete source method: fill its suggests with google geocoder results
  _geocode: function(request, response) {
    var address = request.term, self = this;
    this.geocoder.geocode( { 'address': address + this.options.appendAddressString}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        for (var i = 0; i < results.length; i++) {
          results[i].label =  results[i].formatted_address;
        };
      }
      response(results);
    })
  },

  _findInfo: function(result, type) {
    for (var i = 0; i < result.address_components.length; i++) {
      var component = result.address_components[i];
      if (component.types.indexOf(type) !=-1) {
        return component.long_name;
      }
    }
    return false;
  },

  _focusAddress: function(event, ui) {
    var address = ui.item;
    if (!address) {
      return;
    }

    if (this.gmarker) {
      this.gmarker.setPosition(address.geometry.location);
      this.gmarker.setVisible(true);

      this.gmap.fitBounds(address.geometry.viewport);
    }
    this._updatePosition(address.geometry.location);

    if (this.locality) {
      this.locality.val(this._findInfo(address, 'locality'));
    }

        if (this.address) {
      this.address.val(this._findInfo(address, 'address'));
    }
    if (this.country) {
      this.country.val(this._findInfo(address, 'country'));
    }
  },

  _selectAddress: function(event, ui) {
    this.selectedResult = ui.item;
  }
});

$.extend( $.ui.addresspicker, {
    version: "@VERSION"
});


// make IE think it doesn't suck
if(!Array.indexOf){
    Array.prototype.indexOf = function(obj){
        for(var i=0; i<this.length; i++){
            if(this[i]==obj){
                return i;
            }
        }
        return -1;
    }
}

})( jQuery );

I think use of that plugin may be overkill for your situation. It includes code to handle a map, etc. that you don't need just to autocomplete an address. Using jQueryUI autocomplete (which you already had a dependency on with the plugin) this only takes a few lines of code.

I would use something like this:

$(document).ready(function () {
    var geocoder = new google.maps.Geocoder();
    $("#address1").autocomplete({
        source: function (request, response) {
            geocoder.geocode({ address: request.term }, function (results, status) {
            if (status === google.maps.GeocoderStatus.OK) {
              response($.map(results, function(result) {
                if ($.inArray("street_address", result.types) >= 0) {
                    return result.formatted_address;
                }
              }));
            }
          });
        },
        select: function (event, ui) {
            var parts = ui.item.label.split(",")
                , address1 = parts[0]
                , address2 = parts.slice(1).join(",").trim();
            $("#postal").val(address1 + "\n" + address2);
        }
    });
});

(I tried to use jsfiddle or similar for an example but those services don't play nice with the maps API).

The important parts are:

  • Use a function as a source parameter to autocomplete. In that function, use a google.maps.Geocoder to geocode the input address.
  • In the callback for the geocoding request, update the autocomplete choices with the fomatted address.

After the user selects an address:

  • Split the address by comma.
  • Take the first piece of the address and combine it with the last parts.
  • Populate the #postal field with the resulting string.

You will need a database of addresses to do that. You can probably buy one or may be able to find one similar to: http://www2.royalmail.com/marketing-services/address-management-unit/address-data-products/postcode-address-file-paf?campaignid=paf_redirect

I would be a terrible idea to run a geocoder in an autocomplete function to be run each time a user starts typing. Most of these sites have a daily limit on geocode queries otherwise you have to start paying money.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM