Javascript 在自动完成选择时解析 Google 地图中的 address_components
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8082405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parsing address_components in Google Maps upon autocomplete select
提问by Victor
I have the following code to parse the country
when the autocomplete list is selected:
我有以下代码来解析country
选择自动完成列表的时间:
$('#spot_address').autocomplete({
// This bit uses the geocoder to fetch address values
source: function(request, response) {
geocoder.geocode( {'address': request.term }, function(results, status) {
// Get address_components
for (var i = 0; i < results[0].address_components.length; i++)
{
var addr = results[0].address_components[i];
var getCountry;
if (addr.types[0] == 'country')
getCountry = addr.long_name;
}
response($.map(results, function(item) {
return {
label: item.formatted_address,
value: item.formatted_address,
latitude: item.geometry.location.lat(),
longitude: item.geometry.location.lng(),
country: getCountry
}
}));
})
},
// This bit is executed upon selection of an address
select: function(event, ui) {
// Get values
$('#spot_country').val(ui.item.country);
$('#spot_lat').val(ui.item.latitude);
$('#spot_lng').val(ui.item.longitude);
var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
marker.setPosition(location);
map.setCenter(location);
},
// Changes the current marker when autocomplete dropdown list is focused
focus: function(event, ui) {
var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
marker.setPosition(location);
map.setCenter(location);
}
});
However, the code above doesn't work, and when the country is parsed, only the first result of the autocomplete is parsed no matter what, which is significant with the array results[0]
because it only fetches the first result.
但是,上面的代码不起作用,并且在解析国家/地区时,无论如何都只解析自动完成的第一个结果,这对数组很重要,results[0]
因为它只获取第一个结果。
I tried to move it to the select
function, but ui
in select
only contains formatted_address
, longitude
and latitude
, but not the address_components
.
我试图把它移动到select
的功能,但ui
在select
只包含formatted_address
,longitude
和latitude
,但不是address_components
。
What must I do to send the correct country
when the autocomplete list item is selected?
country
选择自动完成列表项时,我必须做什么才能发送正确的信息?
Many thanks.
非常感谢。
采纳答案by Victor
Below is the full working code:
以下是完整的工作代码:
$('#spot_address').autocomplete({
// This bit uses the geocoder to fetch address values
source: function(request, response) {
geocoder.geocode( {'address': request.term }, function(results, status) {
response($.map(results, function(item) {
// Get address_components
for (var i = 0; i < item.address_components.length; i++)
{
var addr = item.address_components[i];
var getCountry;
if (addr.types[0] == 'country')
getCountry = addr.long_name;
}
return {
label: item.formatted_address,
value: item.formatted_address,
latitude: item.geometry.location.lat(),
longitude: item.geometry.location.lng(),
country: getCountry
}
}));
})
},
// This bit is executed upon selection of an address
select: function(event, ui) {
// Get values
$('#spot_country').val(ui.item.country);
$('#spot_lat').val(ui.item.latitude);
$('#spot_lng').val(ui.item.longitude);
var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
marker.setPosition(location);
map.setCenter(location);
},
// Changes the current marker when autocomplete dropdown list is focused
focus: function(event, ui) {
var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
marker.setPosition(location);
map.setCenter(location);
}
});
回答by William Entriken
General solution:
一般解决方案:
var address_components = results[0].address_components;
var components={};
jQuery.each(address_components, function(k,v1) {jQuery.each(v1.types, function(k2, v2){components[v2]=v1.long_name});});
Now your components
looks like this:
现在你components
看起来像这样:
street_number: "1100",
route: "E Hector St",
locality: "Conshohocken",
political: "United States",
administrative_area_level_3: "Whitemarsh"…
administrative_area_level_1: "Pennsylvania"
administrative_area_level_2: "Montgomery"
administrative_area_level_3: "Whitemarsh"
country: "United States"
locality: "Conshohocken"
political: "United States"
postal_code: "19428"
route: "E Hector St"
street_number: "1100"
Which you can query like this:
您可以这样查询:
components.country
回答by Alex Cheremisin
Here is my solution in typescript
这是我在打字稿中的解决方案
interface AddressComponent {
long_name: string;
short_name: string;
types: Array<string>;
}
interface Address {
street_number?: string;
street_name?: string;
city?: string;
state?: string;
country?: string;
postal_code?: string;
}
export class GoogleAddressParser {
private address: Address = {};
constructor(private address_components: Array<AddressComponent>) {
this.parseAddress();
}
private parseAddress() {
if (!Array.isArray(this.address_components)) {
throw Error('Address Components is not an array');
}
if (!this.address_components.length) {
throw Error('Address Components is empty');
}
for (let i = 0; i < this.address_components.length; i++) {
const component: AddressComponent = this.address_components[i];
if (this.isStreetNumber(component)) {
this.address.street_number = component.long_name;
}
if (this.isStreetName(component)) {
this.address.street_name = component.long_name;
}
if (this.isCity(component)) {
this.address.city = component.long_name;
}
if (this.isCountry(component)) {
this.address.country = component.long_name;
}
if (this.isState(component)) {
this.address.state = component.long_name;
}
if (this.isPostalCode(component)) {
this.address.postal_code = component.long_name;
}
}
}
private isStreetNumber(component: AddressComponent): boolean {
return component.types.includes('street_number');
}
private isStreetName(component: AddressComponent): boolean {
return component.types.includes('route');
}
private isCity(component): boolean {
return component.types.includes('locality');
}
private isState(component): boolean {
return component.types.includes('administrative_area_level_1');
}
private isCountry(component): boolean {
return component.types.includes('country');
}
private isPostalCode(component): boolean {
return component.types.includes('postal_code');
}
result(): Address {
return this.address;
}
}
Usage:
用法:
const address = new GoogleAddressParser(results[0].address_components).result();
回答by ChrisRich
Elaborating on @Full Decent's answer here a version for lodash:
详细阐述@Full Decent 的回答,这里是 lodash 的一个版本:
_.each(address_components, function(k, v1) {
_.each(address_components[v1].types, function(k2, v2){
components[address_components[v1].types[v2]] = address_components[v1].long_name
});
});
回答by Ahmed Ali Thabet
Here I made my own solution, as I wanted to get the city name and there may be more than one format for this, for example, the city name in some regions can be under the name of
这里我自己做了一个解决方案,因为我想获取城市名称,并且可能有不止一种格式,例如,某些地区的城市名称可以在以下名称下
(locality, sublocality , sublocality_level_1, sublocality_level_2, sublocality_level_3
or sublocality_level_4)
so I made this function
所以我做了这个功能
getAddressObject(address_components) {
var ShouldBeComponent = {
home: ["street_number"],
postal_code: ["postal_code"],
street: ["street_address", "route"],
region: [
"administrative_area_level_1",
"administrative_area_level_2",
"administrative_area_level_3",
"administrative_area_level_4",
"administrative_area_level_5"
],
city: [
"locality",
"sublocality",
"sublocality_level_1",
"sublocality_level_2",
"sublocality_level_3",
"sublocality_level_4"
],
country: ["country"]
};
var address = {
home: "",
postal_code: "",
street: "",
region: "",
city: "",
country: ""
};
address_components.forEach(component => {
for (var shouldBe in ShouldBeComponent) {
if (ShouldBeComponent[shouldBe].indexOf(component.types[0]) !== -1) {
address[shouldBe] = component.long_name;
}
}
});
console.log(address);
return address;
}
回答by Yom S.
Here's an ES6 and jQuery-less solution (based on William Entriken's post), making use of the native reduce
function and destructuring assignmentsyntax to unpack properties from objects, into distinct variables:
这是一个 ES6 和 jQuery-less 解决方案(基于William Entriken 的帖子),利用本机reduce
函数和解构赋值语法将对象的属性解包为不同的变量:
const address = address_components.reduce((seed, { long_name, types }) => {
types.forEach(t => {
seed[t] = long_name;
});
return seed;
}, {});
Or, the one-liner version (for what it's worth):
或者,单线版本(物有所值):
const address = address_components.reduce((seed, { long_name, types }) => (types.forEach(t => seed[t] = long_name), seed), {});
Which you can then use like:
然后你可以使用它:
address.street_number
address.city
回答by LeoLozes
In an AngularJS controller, it could be like this:
在 AngularJS 控制器中,它可能是这样的:
function NewController() {
var vm = this;
vm.address = null;
vm.placeService = null;
activate();
function activate() {
vm.placeService = new google.maps.places.PlacesService(document.getElementById("map"));
}
function getAddressComponent(address, component, type) {
var element = null;
angular.forEach(address.address_components, function (address_component) {
if (address_component.types[0] == component) {
element = (type == 'short') ? address_component.short_name : address_component.long_name;
}
});
return element;
}
function getAddressDetail(addressId) {
var request = {
placeId: addressId
};
vm.placeService.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
vm.address = {
countryCode: getAddressComponent(place, 'country', 'short'),
countryName: getAddressComponent(place, 'country', 'long'),
cityCode: getAddressComponent(place, 'locality', 'short'),
cityName: getAddressComponent(place, 'locality', 'long'),
postalCode: getAddressComponent(place, 'postal_code', 'short'),
streetNumber: getAddressComponent(place, 'street_number', 'short')
};
console.log(vm.address);
}
});
}
}
回答by Noel McKeown
This worked for me, in AngularJS;
这对我有用,在 AngularJS 中;
// Function converts GPS co-ordinates to a locality name
function showLocation(LatLng) {
geocoder.geocode({'latLng': LatLng}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
console.log(results[0]);
var myLocation;
for (var i = 0; i < results[0].address_components.length; i++) {
var addr = results[0].address_components[i];
var getCountry;
var getAdministrative;
var getLocality;
if (addr.types[0] == 'locality') {
getLocality = addr.long_name;
console.log(getLocality);
myLocation = getLocality+ ', ';
}
if (addr.types[0] == 'administrative_area_level_1') {
getAdministrative = addr.long_name;
console.log(getAdministrative);
myLocation += getAdministrative + ', ';
}
if (addr.types[0] == 'country') {
getCountry = addr.long_name;
console.log(getCountry);
myLocation += getCountry;
}
}
$scope.locality = myLocation;
console.log(myLocation);
}
})
};
回答by stephen.hanson
I've been using the following approach:
我一直在使用以下方法:
var city = getAddressComponent(place, 'locality', 'long_name');
var state = getAddressComponent(place, 'administrative_area_level_1', 'short_name');
var postalCode = getAddressComponent(place, 'postal_code', 'short_name');
var country = getAddressComponent(place, 'country', 'long_name');
function getAddressComponent(place, componentName, property) {
var comps = place.address_components.filter(function(component) {
return component.types.indexOf(componentName) !== -1;
});
if(comps && comps.length && comps[0] && comps[0][property]) {
return comps[0][property];
} else {
return null;
}
}
回答by user3795286
Country is always last in array that is returned from Geocoder.
国家/地区始终位于从 Geocoder 返回的数组中的最后。
Here is my solution -
这是我的解决方案 -
geocoder.geocode( {'address': request.term }, function(results, status) {
var location_country =
results[0].address_components[results[0].address_components.length - 1].long_name;
});
Hope this helps.
希望这可以帮助。