Подтвердить что ты не робот

GMaps4Rails и Turbolinks не загружаются без обновления полной страницы

Я использую gmaps4rails для загрузки карты на странице показа клиентов. Я включил turbolinks, чтобы сделать приложение speadier все вместе, но теперь я сталкиваюсь с проблемой, когда мне нужно обновить страницу с помощью карты для отображения карты. Все, что я получаю, это пустой каркас карты. Когда я обновляю страницу, карта отображается правильно.

Я попытался добавить 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 .

Суть источника страницы, где карта пуста здесь.

4b9b3361

Ответ 1

Исправление закончилось тем, что мне нужна полная загрузка страницы для обновления скриптов.

Добавление

'data-no-turbolink' => true

к ссылке, которая идет на страницу карт.

Например, если у меня есть индексная страница клиентов, и у меня есть карта того, где живет клиент на странице показа, ссылка на страницу показа будет отформатирована следующим образом:

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

Это приведет к полному обновлению html и javascript, а не только к измененному html.

Ответ 2

Техническая информация

<Не h3 > данных нет-turbolink

Обратите внимание, что добавление атрибута data-no-turbolink="true" в ссылку отключает turbolinks для этой ссылки. Нажатие на эту ссылку загружает всю страницу, а не заменяет содержимое турбонауками.

Но существует несколько способов использования турбонасосов с gmaps4rails без подавления турбонасосов.

Обратные вызовы Turbolinks

Ключом к тому, чтобы что-то работать с turbolinks, является использование предоставленных обратных вызовов. В этом случае нужно сказать gmaps4rails, чтобы выполнить загрузку карты, когда turbolinks загрузила новую страницу.

В общем, можно использовать $(document).on('page:load', function ... ) как, например, показано в Railscast # 390.

Политика JavaScript одинакового происхождения

google api script, включенный в gmap4rails gem, запрашивает другой script с статического сервера google. Но если api динамически включается turbolinks, политика единого происхождения предотвращает запрос на статический сервер google.

Сама политика одного происхождения - полезная вещь. Хотя есть несколько способов обойти это, это, похоже, не является естественным делом. Вместо этого "правильный путь" заключается в том, чтобы "доказать", что веб-страница действительно хочет выполнить удаленный script (google api) и что удаленный script не запрашивается злонамеренным script. Это делается путем включения тега script, который запрашивает google api непосредственно в дереве html.

Включение тега google api script непосредственно в дерево html возможно только при первом запросе при использовании turbolinks, поскольку все последующие изменения динамически вставляются в дерево с помощью turbolinks. Это означает, что при использовании turbolinks приложение google api должно быть включено даже на страницы, на которых не отображается карта.

Решение 1 (рекомендуется): использовать fork для gmaps4rails

Я сделал запрос , надеясь добавить поддержку Turbolinks для gmaps4rails.

Demo

Если вы хотите, сначала посмотрите на эту демонстрацию, в которой показано использование gmaps4rails с turbolinks:

Как использовать это в своем проекте

Вы можете попробовать это и проверить, работает ли он для вашего проекта, добавив вилку в ваш Gemfile:

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

Кроме того, вам нужно изменить файл макета, чтобы включить api в html head:

<!-- 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.

Это демонстрируется в целом для использования с UJS в wiki gmaps4rails: https://github.com/apneadiving/Google-Maps-for-Rails/wiki/Using-with-UJS

Решение 3: Включите api statics вручную

Если вы не хотите добавлять скрипты api глобально, существует способ обойти политику единого происхождения и динамически загружать api.

Я подготовил для этого: https://gist.github.com/fiedl/6573175

Вам нужно добавить файл javascript, который выполняет две функции:

  • Загрузите Google Maps api самостоятельно.
  • Загрузите файл statics, который загружается api.

Вы можете узнать URL-адрес файла statics, открыв api script в браузере и скопировав URL-адрес из вызова getScript внизу,

Но: это исправляет статический запрос api для вашей локали, что, вероятно, не очень хорошо, если ваше приложение используется на международном уровне.

Ответ 3

У меня возникли проблемы с заполнением холста карты при просмотре страниц, которые уже управляются турбонауками, особенно при использовании кнопки "Назад". Я исправил проблему, добавив слушателя для события 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

Ответ 4

Как можно найти в этой проблеме Github, вы можете включить скрипты google на все ваши страницы. Это устраняет проблему, когда Turbolinks не выполняет javacripts gmaps4rails для новых навигационных страниц.

Обратите внимание, что gmaps4rails gem имеет javascript-зависимости, а именно:

<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

Теперь карта должна быть загружена без необходимости обновления страницы.

Ответ 5

У меня была такая же проблема, но я не хотел отключать turbolinks, и я не мог понять, что это слушатели DOM turbolink DOM.

При исправлении другой проблемы и рефакторинг моего javascript я решил это случайно.

Это мои функции. 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 );
});
};

Так как я использую также google places libary, у меня есть несколько функций, которые я могу вызвать с помощью init_google_api()

В каждой точке зрения, где мне нужны карты, я просто положил

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

В самом конце представления. Исправлено все + код сухих для того, чтобы иметь более одной карты и т.д.

Если я не ошибаюсь, этот подход затрагивает проблему turbolink, потому что каждый раз, когда вызывается представление, он выполняет функцию init_google_api и функцию, которая передается как параметр (поэтому я использую выражения функции). Таким образом, код запускается каждый раз, когда вызывается функция.

Ответ 6

Вы можете использовать обратный вызов непосредственно с URL-адреса карты google

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

Обратите внимание, что вы должны иметь определенные функции init перед тем, как вы вызываете этот script.

Вот как я продолжаю. У меня есть помощник, который генерирует тег Gmaps script с обратным вызовом правой функции (+ загрузка других скриптов 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 5, и, как вы можете видеть с помощью этого кода, вам даже не нужен

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