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!:)

Другие вопросы по тегам