Rails 4, turbolinks и coffeescript
Простите, если я немного запутался, я выхожу на новый уровень в своем программировании и учусь на ходу. Основная концепция, с которой я борюсь:
В моем приложении на Rails 4 я использую Leaflet (библиотеку JS для отображения) и вызываю часть своего собственного кода. Короче говоря, я не смог заставить Leaflet и Turbolinks хорошо играть вместе, поэтому для страниц на моем сайте, которые нуждаются в Leaflet, я отключил Turbolinks, кроме того, я загружаю специфичный для страницы Coffeescript.
Теперь я решил, что хочу добавить кнопку возврата. Использование будет происходить следующим образом - со страницы, которая использует Leaflet, пользователь может щелкнуть по части карты и перейти на страницу, которая использует Turbolinks (если это имеет значение). На странице Turbolinks у меня есть кнопка "Назад", чтобы вернуть вас к карте Leaflet.
Однако, когда я возвращаюсь на страницу Leaflet, мой coffeescript либо не запускается, либо запускается не вовремя (я получаю несколько ошибок, которых не было при первом запуске). Я предполагаю, что мне нужно было бы добавить другое событие в начале Coffeescript или выбрать другое событие, но я просто не уверен, каким оно должно быть.
Я никоим образом не намерен не использовать Turbolinks на странице Leaflet, если у вас есть предложение о том, как заставить его работать, и это помогает заставить работать кнопку возврата.:)
_navbar.html.erb
<li><%= link_to("By grid", grid_path, data: {turbolinks: false}) %></li>
grid.html.erb
... code for layout goes here ...
<% content_for :header do %>
<%= javascript_include_tag "leaflet" %>
<% end %>
<% content_for :javascript do %>
<%= javascript_include_tag "leaflet-maps/#{filename}" %>
<% end %>
leaflet-maps/grid.coffee
$ ->
document.addEventListener 'page:restore', ->
app.init()
return
... rest of coffeescript goes here ...
... here is how the link is getting called
layer.on 'click', (e) ->
window.location.href='/show?grid='+feature.id
return
show.html.erb
<%= link_to "Back", :back %>
Обновить
grid.coffee
- полный код
ready = ->
#--------------------------------------------------
# Build tooltip with plant name
#--------------------------------------------------
onEachFeature = (feature, layer) ->
if feature.properties and feature.properties.grid_name
layer.bindTooltip feature.properties.grid_name
layer.on 'click', (e) ->
window.location.href='/show?grid='+feature.id
return
return
#--------------------------------------------------
# Variables
#--------------------------------------------------
L.Icon.Default.imagePath = '/assets'
gridStyle = {
"color": "#ff7800",
}
neCorner = L.latLng([47.635103, -122.320525])
swCorner = L.latLng([47.634083, -122.321129])
#--------------------------------------------------
# Set view and load Google Maps
#--------------------------------------------------
map = L.map("map", zoomSnap: .25)
map.fitBounds([swCorner, neCorner])
map.invalidateSize(false)
map.options.maxZoom = 22
map.options.bounceAtZoomLimits = true
googleLayer = L.gridLayer.googleMutant(type: 'roadmap').addTo(map)
map.addLayer googleLayer
#--------------------------------------------------
# Get Ajax data
#--------------------------------------------------
$.ajax
dataType: 'text'
url: 'grid.json'
success: (data) ->
L.geoJSON(JSON.parse(data), style: gridStyle, onEachFeature: onEachFeature ).addTo map
error: ->
alert "Failed to load AJAX data"
document.addEventListener 'turbolinks:load', ready()
document.addEventListener 'DOMContentLoaded', ready()
1 ответ
Таким образом, есть два места, где вы можете сбиться с пути. Первый здесь:
$ ->
document.addEventListener 'page:restore', ->
app.init()
Это говорит о том, что... "когда веб-страница генерирует событие DOMContentLoaded, тогда, когда что-то еще генерирует page:restore
Затем запустите мой код JavaScript. "
Давайте начнем с DOMContentLoaded
, Это браузеры событий, генерируемые по умолчанию и используемые каркасом jQuery для запуска прослушивателей событий. Вы можете прочитать больше о jQuery's .ready()
функционировать здесь.
page:restore
Событие НЕ является стандартным событием, но было пользовательским событием, используемым в Turbolinks Classic (версия <5.0, устарела по состоянию на февраль 2016 года), которое, я полагаю, вы используете, так как упомянули Rails 4.
В любом случае, размещение обоих слушателей друг над другом, вероятно, не то, что вы хотите сделать. Что вы могли бы сделать, это определить функцию для запуска на обоих ready
а также page:restore
...
function ready() {
// All of the setup you want to do...
}
document.addEventListener("turbolinks:load", ready());
document.addEventListener("DOMContentLoaded", ready());
(Извините, я понимаю, что вы пишете CoffeeScript. Это не мое варенье. Надеюсь, мой JavaScript в порядке...)
Это один Я вижу еще одну возможность для улучшения.
layer.on 'click', (e) ->
То, что вы говорите, "когда документ загружен, слушайте клики на layer
объект, а затем сделать это ".
Я не совсем уверен, что layer
и если это зависит от Leaflet, я, вероятно, не смогу вам помочь. Однако на самом деле есть более гибкий способ написать это.
$(document).on("click","layer", function() {
// do things with the layer
});
Это может показаться идентичным, но есть небольшая разница. Он говорит: "Каждый раз, когда я нажимаю на документ, если я случайно нажимаю на слой, сделайте это".
Это более устойчиво, потому что ваша строка JavaScript всегда может найти document
когда он запускается. Если твой layer
не рендерится к моменту запуска строки кода, он никогда не поймает эти клики.
Удачной JavaScripting!:)