admin管理员组

文章数量:1201362

I'm trying to use the Google Places autocomplete API to pre-fill a form on a web application with Establishment data to ease data-entry. The API is pretty straightforward, but it doesn't seem to want to accept the XHR.

$.getJSON("",{
  input: input.term,
  sensor: false,
  types: 'establishment',
  location: '40.01496,-105.27029',
  radius: 10000,
  key: Config.googleplaceskey
},function(places_response){
    //Some other code.
});

I get this in the console:

XMLHttpRequest cannot load ;sensor=false&types=establishment&location=40.01496%2C-105.27029&radius=10000&key=AIzaSyDKzUgcLklQE_U5494vHq_SzrFakNHugaQ. Origin http://localhost:8086 is not allowed by Access-Control-Allow-Origin.

Is this somehow not what the API is meant for? Anyone know a workaround, or some kind of extra parameter(s) I could send to make it work?

Update:

Here's the link to the API documentation for this call. The parent docs actually even have JavaScript JSON-parsing examples. Really confusing why this would be shut down on the server side.

.html

I'm trying to use the Google Places autocomplete API to pre-fill a form on a web application with Establishment data to ease data-entry. The API is pretty straightforward, but it doesn't seem to want to accept the XHR.

$.getJSON("https://maps.googleapis.com/maps/api/place/autocomplete/json",{
  input: input.term,
  sensor: false,
  types: 'establishment',
  location: '40.01496,-105.27029',
  radius: 10000,
  key: Config.googleplaceskey
},function(places_response){
    //Some other code.
});

I get this in the console:

XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/autocomplete/json?input=At&sensor=false&types=establishment&location=40.01496%2C-105.27029&radius=10000&key=AIzaSyDKzUgcLklQE_U5494vHq_SzrFakNHugaQ. Origin http://localhost:8086 is not allowed by Access-Control-Allow-Origin.

Is this somehow not what the API is meant for? Anyone know a workaround, or some kind of extra parameter(s) I could send to make it work?

Update:

Here's the link to the API documentation for this call. The parent docs actually even have JavaScript JSON-parsing examples. Really confusing why this would be shut down on the server side.

http://code.google.com/apis/maps/documentation/places/autocomplete.html

Share Improve this question edited Jul 26, 2011 at 1:27 woodardj asked Jul 23, 2011 at 21:48 woodardjwoodardj 3131 gold badge2 silver badges12 bronze badges 1
  • 1 Man, I'm bumping this question. I'm pretty bummed that you can't call this via a browser AJAX request. It makes it so much slower to have to pass it through a server. Any updates on how you got around it? – Tyler Brock Commented Sep 20, 2011 at 3:48
Add a comment  | 

8 Answers 8

Reset to default 3

Here is a code snippet for future readers who come across this scenario.

Using the "Places API" rather than the "Maps API", this code snippet fills in my form elements (including the input that is used to autocomplete) with returned data from Google.

/* Use google place API to auto complete the address field and populate form inputs */
function addressAutoComplete(){
    var planAddress = document.getElementById('mps_planaddress'),
        planCity = document.getElementById('mps_plancity'),
        planCounty = document.getElementById('mps_plancounty'),
        planZip = document.getElementById('mps_planzip'),
        planSub = document.getElementById('mps_plansubdivision'),
        options = {
            componentRestrictions: {country: 'us'}
    };
    autocomplete = new google.maps.places.Autocomplete(planAddress, options);
    // After the user selects the address
    google.maps.event.addListener(autocomplete, 'place_changed', function() {
        planSub.focus();
        var place = autocomplete.getPlace();
        planAddress.value = place.name;
        planCity.value = place.address_components[2].long_name;
        planCounty.value = place.address_components[3].long_name;
        planZip.value = place.address_components[6].long_name;
    });
}

Put a listener on the autocomplete for "place_changed" (they chose something from the list) and then fill in the inputs with the data returned.

All of this is listed on the Place Library Google page.

To make cross-domain AJAX calls like this, you should use JSONP with a callback. However, Google doesn't provide a JSONP interface for Autocomplete.

You might be able to use this Autocomplete class instead, though it doesn't seem possible to style the dropdown.

EDIT There may be a way to do this. Check out the geo-autocomplete jQuery Plugin. It has two demos. I haven't given this a proper look over yet however.

There are two ways to access the Google Maps Autocomplete API.

The first is via the google.maps.places.Autocomplete class. This provides all the necessary implementation in Javascript. However, you have complete control over styling. Use the pac-container and pac-item CSS classes.

The second is via the Autocomplete Web Service. This is not accessible via the browser because of same origin policy (there is no JSONP API). This is the most flexible way to access Autocomplete results.

The Google probably allows this API only called through its own Javascript API which you load from maps.google.com served Javascript file. The lack of Access-Control-Allow-Origin header tells that you should not use the API otherwise through Javascript.

Alternatively you can simply write a server-side proxy function which calls Google API and passes the result forward to your own $.getJSON call, but this would be probably against the Terms of Service.

http://www.daniweb.com/web-development/php/code/216729

(disclaimer: I have not read the API spec for this particular function call)

You can intercept the JSONP results that are returned by the google.maps.places.Autocomplete functionality and use them as you see fit.

Basically you redefine the appendChild method on the head element, and then monitor the javascript elements that the Google autocomplete code inserts into the DOM for JSONP. As javascript elements are added, you override the JSONP callbacks that Google defines in order to get access to the raw autocomplete data.

It's a bit of a hack, here goes (I'm using jQuery but it's not necessary for this hack to work):

//The head element, where the Google Autocomplete code will insert a tag 
//for a javascript file.
var head = $('head')[0];  
//The name of the method the Autocomplete code uses to insert the tag.
var method = 'appendChild';  
//The method we will be overriding.
var originalMethod = head[method];

head[method] = function () {
  if (arguments[0] && arguments[0].src && arguments[0].src.match(/GetPredictions/)) {  //Check that the element is a javascript tag being inserted by Google.
    var callbackMatchObject = (/callback=([^&]+)&|$/).exec(arguments[0].src);  //Regex to extract the name of the callback method that the JSONP will call.
    var searchTermMatchObject = (/\?1s([^&]+)&/).exec(arguments[0].src);  //Regex to extract the search term that was entered by the user.
    var searchTerm = unescape(searchTermMatchObject[1]);
    if (callbackMatchObject && searchTermMatchObject) {
      var names = callbackMatchObject[1].split('.');  //The JSONP callback method is in the form "abc.def" and each time has a different random name.
      var originalCallback = names[0] && names[1] && window[names[0]] && window[names[0]][names[1]];  //Store the original callback method.
      if (originalCallback) {
        var newCallback = function () {  //Define your own JSONP callback
          if (arguments[0] && arguments[0][3]) {
            var data = arguments[0][4];  //Your autocomplete results
            //SUCCESS! - Limit results here and do something with them, such as displaying them in an autocomplete dropdown.
          }
        }

        //Add copy all the attributes of the old callback function to the new callback function. This prevents the autocomplete functionality from throwing an error.
        for (name in originalCallback) {  
          newCallback[name] = originalCallback[name];
        }
        window[names[0]][names[1]] = newCallback;  //Override the JSONP callback
      }
    }

  //Insert the element into the dom, regardless of whether it was being inserted by Google.
  return originalMethod.apply(this, arguments);
};

This is a cross domain request. Browsers by default block responses from cross domain sites. You need to use jsonp as the datatyoe. Just google the same and you can see how it can be done using the jquery API. Stack overflow has questions around these too.

Under the same origin policy, a web page served from server1.example.com cannot normally connect to or communicate with a server other than server1.example.com. An exception is the HTML element. Taking advantage of the open policy for elements, some pages use them to retrieve Javascript code that operates on dynamically-generated JSON-formatted data from other origins. This usage pattern is known as JSONP.

Note that Google Places is not JSONP compliant so I used the Google Places JavaScript API instead.

Use the Places Library from the Google Maps Javascript API: Javascript Places Autocomplete

The Places API is different from the Maps API.

You can bypass this issue by using PHP.

In your PHP script use file_get_contents to query the URL like this:

$suggestions = json_decode(file_get_contents('https://maps.googleapis.com/maps/api/place/autocomplete/json?input=blabla&sensor=false&types=establishment&radius=10000')

You can then just use an AJAX request to your PHP script which will return the results effectively bypassing the cross domain constraint.

本文标签: javascriptCan Google MapsPlaces 39autocomplete39 API be used via AJAXStack Overflow