Геокодирование jQuery для получения почтового адреса

#jquery #autocomplete #geocode #picker #street-address

#jquery #автозаполнение #геокодирование #средство выбора #street-address

Вопрос:

Я слаб в jQuery и Javascript. Я хотел бы взять этот существующий код и заставить его доставлять пользователям полный адрес в почтовом формате … например, в том, что вы помещаете в письмо или конверт FedEx.

Пользователь начинает вводить адрес в поле адреса, и запускается автозаполнение jQuery. Когда пользователь видит полный адрес, он затем нажимает на адрес, и я бы хотел, чтобы он затем распространил тестовое окно с выбором пользователей, но в почтовом формате.

Вот HTML-страница

 <!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>
  

Страница javascript для средства выбора адреса приведена ниже, а другие страницы JS являются текущими версиями

 /*
 * 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 amp;amp; 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 );
  

Ответ №1:

Я думаю, что использование этого плагина может быть излишним для вашей ситуации. Он включает в себя код для обработки карты и т.д., Который вам не нужен просто для автозаполнения адреса. Используя автозаполнение jQueryUI (от которого у вас уже была зависимость с помощью плагина), это занимает всего несколько строк кода.

Я бы использовал что-то вроде этого:

 $(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);
        }
    });
});
  

(Я пытался использовать jsfiddle или аналогичный для примера, но эти сервисы плохо работают с maps API).

Важными частями являются:

  • Используйте функцию в качестве source параметра для автозаполнения. В этой функции используйте google.maps.Geocoder для геокодирования входного адреса.
  • В обратном вызове для запроса геокодирования обновите параметры автозаполнения с помощью форматированного адреса.

После выбора пользователем адреса:

  • Разделите адрес запятой.
  • Возьмите первую часть адреса и объедините ее с последними частями.
  • Заполните #postal поле результирующей строкой.

Комментарии:

1. Ладно, чувак, ты справился! это именно то, что я пытался сделать!!

Ответ №2:

Для этого вам понадобится база данных адресов. Вероятно, вы можете купить один или, возможно, сможете найти похожий на: http://www2.royalmail.com/marketing-services/address-management-unit/address-data-products/postcode-address-file-paf?campaignid=paf_redirect

Было бы ужасной идеей запускать геокодер в функции автозаполнения, которая запускалась бы каждый раз, когда пользователь начинает вводить текст. На большинстве этих сайтов установлен суточный лимит на запросы геокода, в противном случае вам придется начать платить деньги.

Комментарии:

1. API карт Google имеет ограничение в 25 000 запросов в день. Возможно, операционной системе не нужно беспокоиться об этом ограничении. В любом случае, эта часть стратегии OP, похоже, выходит за рамки этого вопроса (на мой взгляд). Кроме того, OP, возможно, фактически заплатил за коммерческий ключ maps API, что делает этот вопрос совершенно спорным.

2. Да, я думал, что геокодирование Google Maps api на 1000 больше в день, чем мне когда-либо понадобится. Я ожидаю только около 10 применений в день … поэтому вместо того, чтобы заниматься созданием и получением большой базы данных, я надеялся использовать эту существующую.

3. Да, Эндрю был прав, я забегал вперед. Я поддерживаю исправление (по крайней мере, для сайтов с малым и средним трафиком).