【问题标题】:Can Google Maps/Places 'autocomplete' API be used via AJAX?Google Maps/Places 'autocomplete' API 可以通过 AJAX 使用吗?
【发布时间】:2011-10-11 19:46:05
【问题描述】:

我正在尝试使用 Google Places 自动完成 API 在 Web 应用程序上使用企业数据预先填写表单,以简化数据输入。 API 非常简单,但它似乎不想接受 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.
});

我在控制台中得到了这个:

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.

这难道不是 API 的用途吗?任何人都知道一种解决方法,或者我可以发送一些额外的参数来使它工作吗?

更新:

这是此调用的 API 文档的链接。父文档实际上甚至有 JavaScript JSON 解析示例。真的很困惑为什么会在服务器端关闭它。

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

【问题讨论】:

  • 伙计,我碰到了这个问题。我很沮丧,你不能通过浏览器 AJAX 请求调用它。它使得必须通过服务器传递它的速度要慢得多。关于你如何解决它的任何更新?

标签: javascript jquery json google-api xmlhttprequest


【解决方案1】:

Google 可能只允许通过其自己的 Javascript API 调用此 API,您从 maps.google.com 提供的 Javascript 文件加载该 API。缺少 Access-Control-Allow-Origin 标头表明您不应通过 Javascript 使用 API。

或者,您可以简单地编写一个服务器端代理函数,该函数调用 Google API 并将结果转发给您自己的 $.getJSON 调用,但这可能违反服务条款。

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

(免责声明:我尚未阅读此特定函数调用的 API 规范)

【讨论】:

  • API 文档编写方式的所有内容都向我暗示,这确实是应该使用的方式。我将使用 API 文档的链接更新问题。
【解决方案2】:

要进行这样的跨域 AJAX 调用,您应该使用带有回调的 JSONP。但是,Google doesn't provide a JSONP interface for Autocomplete

您也许可以改用this Autocomplete class,但似乎无法设置下拉菜单的样式。

编辑可能有办法做到这一点。查看geo-autocomplete jQuery Plugin。它有twodemos。不过,我还没有给它一个适当的外观。

【讨论】:

【解决方案3】:

这是一个跨域请求。默认情况下,浏览器会阻止来自跨域站点的响应。您需要使用 jsonp 作为数据类型。只需谷歌相同,您就可以看到如何使用 jquery API 完成它。堆栈溢出也有这些问题。

在同源策略下,从 server1.example.com 提供的网页无法正常连接到 server1.example.com 以外的服务器或与之通信。 HTML 元素是一个例外。利用元素的开放策略,一些页面使用它们来检索对来自其他来源的动态生成的 JSON 格式数据进行操作的 Javascript 代码。这种使用模式称为 JSONP。

请注意,Google Places 不兼容 JSONP,因此我使用了 Google Places JavaScript API。

【讨论】:

  • 您找到从 JS API 访问原始数据的方法了吗?我想自己过滤和设置下拉菜单的样式,这在直接使用 Web 服务时是可能的,但 JS API 似乎隐藏了这一点。
  • 不,我不需要。无论如何,如果您仍然需要这样做并且无法使用 js 完成,那么您可能应该有一个 localuri,当您需要获取数据并且您的服务器联系谷歌以获取必要的 json 并将其发送回客户端时,您应该联系它,从而避免跨域源策略
  • 对。但是,似乎有办法做到这一点。我将编辑我的答案。
【解决方案4】:

您可以使用 PHP 绕过此问题。

在您的 PHP 脚本中使用 file_get_contents 来查询 URL,如下所示:

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

然后,您可以对 PHP 脚本使用 AJAX 请求,这将有效地绕过跨域约束返回结果。

【讨论】:

    【解决方案5】:

    有两种方法可以访问 Google Maps Autocomplete API。

    第一个是通过google.maps.places.Autocomplete 类。这提供了 Javascript 中所有必要的实现。但是,您可以完全控制样式。使用 pac-containerpac-item CSS 类。

    第二个是通过Autocomplete Web Service。由于same origin policy(没有JSONP API),这无法通过浏览器访问。这是访问自动完成结果的最灵活方式。

    【讨论】:

      【解决方案6】:

      您可以截获google.maps.places.Autocomplete 功能返回的JSONP 结果,并根据需要使用它们。

      基本上,您在 head 元素上重新定义 appendChild 方法,然后监视 Google 自动完成代码插入 DOM 以用于 JSONP 的 javascript 元素。添加 javascript 元素后,您将覆盖 Google 定义的 JSONP 回调,以便访问原始自动完成数据。

      这是一个 hack,在这里(我正在使用 jQuery,但这个 hack 没有必要工作):

      //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);
      };
      

      【讨论】:

        【解决方案7】:

        使用 Google Maps Javascript API 中的 Places 库: Javascript Places Autocomplete

        Places API 与 Maps API 不同。

        【讨论】:

          【解决方案8】:

          这是一个代码 sn-p,供以后遇到这种情况的读者使用。

          使用“Places API”而不是“Maps API”,这段代码 sn-p 用 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;
              });
          }
          

          在“place_changed”的自动完成上放置一个监听器(他们从列表中选择了一些东西),然后用返回的数据填充输入。

          所有这些都列在Place Library Google page 上。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-11-09
            • 2017-01-23
            • 2017-09-12
            • 2017-06-12
            • 1970-01-01
            • 2020-05-04
            • 2011-07-14
            • 1970-01-01
            相关资源
            最近更新 更多