没有整页刷新,GMaps4Rails和Turbolinks无法加载

时间:2012-12-10 19:23:24

标签: ruby-on-rails google-maps-api-3 gmaps4rails

我正在使用gmaps4rails在“客户”节目页面上加载地图。我已经集成了turbolinks以使应用程序更加一致,但是现在我遇到了一个问题,我必须刷新页面以显示地图的地图。我得到的只是一个空白的地图框架。刷新页面时,地图会正确显示。

我尝试添加gem'jquery-turbolinks',但问题仍然存在。

在视图中:

<%= gmaps("map_options" => {:container_class => "map_container_renamed", "zoom" => 15, "auto_zoom" => false},"markers" => { "data" => @json }) %>

在application.js

//= require jquery
//= require turbolinks
//= require jquery.turbolinks
//= require jquery_ujs
//= require twitter/bootstrap
//= require_tree .

地图空白here的页面来源的要点。

6 个答案:

答案 0 :(得分:24)

修复程序最终我需要一个完整的页面加载来刷新脚本。

添加

'data-no-turbolink' => true

转到地图页面的链接。

例如,如果我有一个客户的索引页面,并且我有一个客户端在显示页面上的位置的地图,那么转到显示页面的链接将格式如下:

<%= link_to 'View Client', client, class: "btn", 'data-no-turbolink' => true %>

这将导致html和javascript的完全刷新,而不仅仅是更改的html。

答案 1 :(得分:17)

技术背景

数据-NO-的TurboLink

请注意,只需将属性data-no-turbolink="true"添加到链接即可停止该链接的turbolink。点击该链接会加载整个页面,而不是用turbolinks替换内容。

但是有几种方法可以使用带有gmaps4rails 的turbolink和来抑制turbolinks。

Turbolinks Callbacks

使用turbolinks获取内容的关键是使用提供的回调。在这种情况下,必须告诉gmaps4rails在turbolinks加载新页面时执行地图加载。

通常,可以使用$(document).on('page:load', function ... ),例如Railscast #390中所示。

JavaScript的同源政策

gmap4rails gem包含的google api script请求来自Google静态服务器的其他脚本。但是如果动态链接动态地包含api,则单原始策略会阻止对谷歌静态服务器的请求。

单一来源政策本身是一件有用的事情。虽然有几种方法可以绕过它,但这似乎并不是一件很自然的事情。相反,正确的方式&#34;这样做是为了证明&#34;网页确实想要执行远程脚本(google api)并且恶意脚本不请求远程脚本。这是通过在html树中包含直接请求google api的脚本标记来完成的。

直接在html树中包含google api脚本标记只能在第一次请求时使用turbolinks,因为所有后来的更改都会通过turbolinks动态注入到树中。这意味着,当使用turbolinks时,即使在没有显示地图的页面上也必须包含google api。

解决方案1(推荐):使用fork for gmaps4rails

我做了一个request,希望增加Turbolinks对gmaps4rails的支持。

演示

如果您愿意,请先查看此演示,了解gmaps4rails与turbolinks的使用情况:

如何在项目中使用它

您可以尝试这一点,并通过将分支添加到您的Gemfile来检查它是否适用于您的项目:

# Gemfile
# ...
gem 'turbolinks'
gem 'gmaps4rails', '~> 2.0.1', git: 'https://github.com/fiedl/Google-Maps-for-Rails.git'
# ...

此外,您需要修改布局文件以在html头中包含api:

<!-- app/views/layouts/application.html.erb -->
<html>
  <head>
    ...
    <%= stylesheet_link_tag    "application", :media => "all" %>
    <%= javascript_include_tag "application" %>
    <%= gmaps4rails_api_script_tags  #   <-- THIS IS NEW ----------------- %>
    <%= csrf_meta_tags %>
  </head>
  <body>
    ...
    <%= yield %>
    <%= yield :scripts %>
  </body>
</html>

如果出于某种原因,你不想使用这个分支,我会看到两种方法可以将gmaps4rails与turbolinks一起使用:

解决方案2:手动执行

基本上与fork(解决方案1)做同样的事情,可以手动将api脚本添加到布局文件中的头部。然后,当通过turbolinks加载页面时,可以使用javascript配置和激活地图。

这通常用于在gmaps4rails wiki中与UJS一起使用: https://github.com/apneadiving/Google-Maps-for-Rails/wiki/Using-with-UJS

解决方案3:手动包含api静态

如果您不想全局添加api脚本,有一种方法可以绕过单源策略并动态加载api。

我准备了一个要点https://gist.github.com/fiedl/6573175

您必须添加一个执行两项操作的javascript文件:

  1. 加载google maps api本身。
  2. 加载由api。
  3. 加载的静态文件

    您可以通过在浏览器中打开api script并从底部的getScript调用中复制网址来查找静态文件的网址。

    但是:这样做会将静态API请求修复到您的语言环境,如果您的应用在国际上使用,这可能不是一件好事。

答案 2 :(得分:5)

我无法在重新访问已经由turbolinks管理的页面时填充地图画布,尤其是在使用后退按钮时。我通过为turbolinks事件page:load添加一个侦听器来修复此问题,以映射初始化。

<强> map.js.coffee

google.maps.event.addDomListener(window, 'load', @_setup)
google.maps.event.addDomListener(window, 'page:load', @_setup)

<强> application.js.coffee

//= require jquery
//= require jquery.turbolinks

答案 3 :(得分:0)

可以在此Github issue中找到,您可以在所有网页中加入Google脚本。这解决了Turbolinks没有为新导航的页面执行gmaps4rails javascripts的问题。

请注意,gmaps4rails gem有javascript dependencies,即:

<script src="//maps.google.com/maps/api/js?v=3.13&amp;sensor=false&amp;libraries=geometry" type="text/javascript"></script>
<script src='//google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.14/src/markerclusterer_packed.js' type='text/javascript'></script>

您可以通过修改app/views/layouts/application.html.erb

将它们添加到您的所有网页

<强> application.html.erb

....
<head>
...
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>

  # insert the following two lines
  <script src="//maps.google.com/maps/api/js?v=3.13&amp;sensor=false&amp;libraries=geometry" type="text/javascript"></script>
  <script src='//google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.14/src/markerclusterer_packed.js' type='text/javascript'></script>

</head>
...

另外,不要忘记通过编辑app/assets/javascripts/application.js

将源代码添加到资产管道中

<强>的application.js

添加:

//= require gmaps/google

现在,无需刷新页面即可加载地图。

答案 4 :(得分:0)

我遇到了同样的问题,但我不想关闭turbolinks,我无法正确使用turbolink DOM听众。

在解决另一个问题并重构我的javascript时,我偶然解决了这个问题。

这是我的functions.js

var init_map = function (allMarkers) {
handler = Gmaps.build('Google');
handler.buildMap({ provider: {maxZoom:17, minZoom:5}, internal: {id: 'map'}}, function(){
  markers = handler.addMarkers(allMarkers());
  handler.bounds.extendWith(markers);

   handler.fitMapToBounds();
});
};

var marker_check = function(){...};

var init_autocomplete = function () {...};


//function to call google maps functions

var init_google_api = function(function_name){
  $(document).ready(function(){
  google.maps.event.addDomListener(window, "load", function_name );
});
};

由于我也使用谷歌地方图书馆我有几个功能,我可以用 init_google_api()

打电话

在我想要地图的每个视图中,我只需要一个

<%= javascript_tag do %>
   init_google_api(init_map(marker_check));
<% end %>

在视图的最后。修复了一切+保持代码干燥,因为想要多个地图等。

如果我没有弄错,这种方法绕过了turbolink问题,因为每次调用一个视图时,它都会执行init_google_api函数和作为参数传入的函数(这就是我使用函数表达式的原因)。因此,每次调用函数时都会运行代码。

答案 5 :(得分:0)

您可以直接从Google地图网址

使用回调
<script src="https://maps.googleapis.com/maps/api/js
 ?callback=yourInitFunction
 &key=&sensor=false">

但请注意,在调用此脚本之前,必须先定义init函数。

以下是我的进展方式。我有一个帮助器生成Gmaps脚本标记,其中包含对正确函数的回调(+加载其他gmaps脚本)

# view/your_view.html.erb
<script>
function onGmapsInit() {
    // Your code here. You can also define this function in your assets/js directly.
}
</script>
<%= gmap_scripts(callback: 'onGmapsInit') %>

我的助手

# helpers/maps_helper.rb
module MapsHelper
  GMAPS_V3_URL = 'https://maps.googleapis.com/maps/api/js'

  def gmap_scripts(options = {})
    callback = options.delete(:callback)
    gmaps_v3_options = {
      src: "#{GMAPS_V3_URL}?#{callback ? "callback=#{callback}&" : ''}key=&sensor=false"
    }
    gmaps_utility_options = {
      src: '//google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.14/src/markerclusterer_packed.js'
    }
    capture do
      concat content_tag(:script, nil, gmaps_v3_options)
      concat content_tag(:script, nil, gmaps_utility_options)
    end
end

什么? Turbolinks?这吃东西吗?

我正在使用Turbolinks 5,正如您在此代码中所看到的,您甚至不需要

$(document).on('ready turbolinks:load')