更新
谷歌已經發布Google Places Autocomplete這正好解決了這個問題。
在頁面的底部,在那裏拋出這樣:
<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已經載典型,因爲那將土地異步)有:
GoogleAddress.init('#billing input', '#shipping input');
或什麼的。在這種情況下,它將地址typeahead綁定到#billing標記和#shipping標記中具有name = Address的任何輸入,並且在選擇地址時,它將填入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();
});
}
解析結果到規範化street1,STREET2,城市,州/省,郵政編碼/郵遞區號是不平凡的。谷歌根據你所處的世界的不同而區分了這些地點,並且作爲一個警告,例如在非洲,有些地方不符合你對地址的看法。你可以打破世界地址可分爲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賓夕法尼亞大道希望通過你輸入「總統一家」,但必須讓儘可能「1600賓夕法尼亞大道的時間去白宮,華盛頓特區「,然後再回復該地址。但是,它可以爲用戶節省時間帶來一點好處。
客戶端的服務器已經處於高負載狀態。更大的產品(如Google)對這些查詢採用邊緣緩存響應,我們的最佳情況會比較慢。它似乎是應該有答案的那些大問題之一。 –