Обновлено
Google выпустила Автозаполнение Google Адресов , которое решает именно эту проблему.
Внизу страницы добавьте туда:
<script defer async src="//maps.googleapis.com/maps/api/js?libraries=places&key=(key)&sensor=false&callback=googPlacesInit"></script>
Где (key)
- ваш ключ API.
Мы настроили наш код так, чтобы вы пометили некоторые поля для обработки заголовка и заполнились этим заголовком, например:
<input name=Address placeholder=Address />
<input name=Zip placeholder=Zip />
и т.д.
Затем вы инициализируете его (до того, как обычно загружается API Google Places, так как он будет обрабатываться асинхронно) с помощью:
GoogleAddress.init('#billing input', '#shipping input');
Или что угодно. В этом случае он привязывает адрес типа к любому входу, имеющему name = Address в тегах #billing и #shipping, и заполняет соответствующие поля внутри этих тегов для City, State, Zip и т. Д. При выборе адреса.
Настройка класса:
var GoogleAddress = {
AddressFields: [],
//ZipFields: [], // Not in use and the support code is commented out, for now
OnSelect: [],
/**
* @param {String} field Pass as many arguments as you like, each a selector to a set of inputs that should use Google
* Address Typeahead via the Google Places API.
*
* Mark the inputs with name=Address, name=City, name=State, name=Zip, name=Country
* All fields are optional; you can for example leave Country out and everything else will still work.
*
* The Address field will be used as the typeahead field. When an address is picked, the 5 fields will be filled in.
*/
init: function (field) {
var args = $.makeArray(arguments);
GoogleAddress.AddressFields = $.map(args, function (selector) {
return $(selector);
});
}
};
Приведенный выше фрагмент сценария собирается выполнить асинхронный вызов функции с именем googPlacesInit
, поэтому все остальное будет заключено в функцию с таким именем:
function googPlacesInit() {
var fields = GoogleAddress.AddressFields;
if (
// If Google Places fails to load, we need to skip running these or the whole script file will fail
typeof (google) == 'undefined' ||
// If there's no input there's no typeahead so don't bother initializing
fields.length == 0 || fields[0].length == 0
)
return;
Настройте событие автозаполнения и учтите тот факт, что мы всегда используем несколько полей адреса, но Google хочет выгрузить весь адрес в один вход. Конечно, есть способ предотвратить это должным образом, но я еще не нашел его.
$.each(fields, function (i, inputs) {
var jqInput = inputs.filter('[name=Address]');
var addressLookup = new google.maps.places.Autocomplete(jqInput[0], {
types: ['address']
});
google.maps.event.addListener(addressLookup, 'place_changed', function () {
var place = addressLookup.getPlace();
// Sometimes getPlace() freaks out and fails - if so do nothing but blank out everything after comma here.
if (!place || !place.address_components) {
setTimeout(function () {
jqInput.val(/^([^,]+),/.exec(jqInput.val())[1]);
}, 1);
return;
}
var a = parsePlacesResult(place);
// HACK! Not sure how to tell Google Places not to set the typeahead field's value, so, we just wait it out
// then overwrite it
setTimeout(function () {
jqInput.val(a.address);
}, 1);
// For the rest, assign by lookup
inputs.each(function (i, input) {
var val = getAddressPart(input, a);
if (val)
input.value = val;
});
onGoogPlacesSelected();
});
// Deal with Places API blur replacing value we set with theirs
var removeGoogBlur = function () {
var googBlur = jqInput.data('googBlur');
if (googBlur) {
jqInput.off('blur', googBlur).removeData('googBlur');
}
};
removeGoogBlur();
var googBlur = jqInput.blur(function () {
removeGoogBlur();
var val = this.value;
var _this = this;
setTimeout(function () {
_this.value = val;
}, 1);
});
jqInput.data('googBlur', googBlur);
});
// Global goog address selected event handling
function onGoogPlacesSelected() {
$.each(GoogleAddress.OnSelect, function (i, fn) {
fn();
});
}
Анализ результата в каноническую улицу 1, улицу 2, город, штат / провинцию, почтовый индекс не является тривиальным. Google различает эти населенные пункты разными тегами в зависимости от того, где вы находитесь, и в качестве предупреждения, например, в Африке есть места, которые не соответствуют вашим ожиданиям в отношении того, как выглядит адрес. Вы можете разбить адреса в мире на 3 категории:
США идентичны - весь США и несколько стран, которые используют аналогичную систему адресации
Официальные адреса - Великобритания, Австралия, Китай, в основном развитые страны - но то, как их части адреса являются тегами, имеет значительную разницу:
Нет формальных адресов - в неразвитых районах нет названий улиц, не говоря уже о номерах улиц, иногда даже нет названия города / города и, конечно, почтового индекса. В этих местах вам действительно нужно местоположение GPS, которое не обрабатывается этим кодом.
Этот код пытается справиться только с первыми двумя случаями.
function parsePlacesResult(place) {
var a = place.address_components;
var p = {};
var d = {};
for (var i = 0; i < a.length; i++) {
var ai = a[i];
switch (ai.types[0]) {
case 'street_number':
p.num = ai.long_name;
break;
case 'route':
p.rd = ai.long_name;
break;
case 'locality':
case 'sublocality_level_1':
case 'sublocality':
d.city = ai.long_name;
break;
case 'administrative_area_level_1':
d.state = ai.short_name;
break;
case 'country':
d.country = ai.short_name;
break;
case 'postal_code':
d.zip = ai.long_name;
}
}
var addr = [];
if (p.num)
addr.push(p.num);
if (p.rd)
addr.push(p.rd);
d.address = addr.join(' ');
return d;
}
/**
* @param input An Input tag, the DOM element not a jQuery object
* @paran a A Google Places Address object, with props like .city, .state, .country...
*/
var getAddressPart = function(input, a) {
switch(input.name) {
case 'City': return a.city;
case 'State': return a.state;
case 'Zip': return a.zip;
case 'Country': return a.country;
}
return null;
}
Старый ответ
ArcGis / ESRI имеет ограниченное решение для ввода текста, которое функционально, но возвращает ограниченные результаты только после небольшого ввода. Здесь есть демо:
http://www.esri.com/services/disaster-response/wildlandfire/latest-news-map.html
Например, вы могли бы набрать 1600 Pennsylvania Ave в надежде получить белый дом к тому времени, когда вы наберете "1600 Penn", но до того, как он ответит этим адресом, придется пройти до "1600 pennsylvania ave, вашингтон, округ Колумбия". Тем не менее, это может принести небольшую пользу пользователям в экономии времени.