1

我正在使用 Turbolinks 和 Google Maps 4 Rails。出于性能原因,我试图让所有 javascript 加载异步。

如果我来自同一网站的另一个页面,我发现地图页面加载正确。但如果我只是在浏览器中输入地址并转到地图页面,我会收到两个错误:

Uncaught ReferenceError: Gmaps is not defined

Uncaught ReferenceError: jQuery is not defined

这是我的设置:

在我的脑海里(在哈姆里)

%script{ src:'//maps.google.com/maps/api/js?v=3.13&sensor=true&libraries=geometry', type:'text/javascript' }
-# http://www.rickypai.com/blog/2013/02/22/web-dev-gotchas-with-rails-4-0-turbolinks/
- if Settings.ASYNC_JAVASCRIPT
    = render 'layouts/async_javascript', path: 'application'
- else
    = javascript_include_tag 'application', data_turbolinks_track: true

_async_javascript.html.erb

<%# http://railscasts.com/episodes/369-client-side-performance?view=asciicast %>
<script type="text/javascript">
    (function() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.src = '<%= j javascript_path(path) %>';
        var other = document.getElementsByTagName('script')[0];
        other.parentNode.insertBefore(script, other);
    }) ();
</script>

应用程序.js

//= require modernizr
//= require jquery
//= require jquery.turbolinks
//= require google.maps.infobox
//= require google.maps.richmarker
//= require google.maps.markerclusterer
//= require gmaps/google
...
//= require turbolinks

最后,在体内(以haml)

- present @location, LocationPresenter do |p|
    = render 'map_coffee', id: 'l_map', markers: [p.marker].to_json, lat: p.latitude, lng: p.longitude

_map.coffee.html.haml

:coffee
    class RichMarkerBuilder extends Gmaps.Google.Builders.Marker

        create_marker: ->
            options = _.extend @marker_options(), @rich_marker_options()
            @serviceObject = new RichMarker options

        rich_marker_options: ->
            marker = document.createElement 'div'
            marker.setAttribute 'class', 'marker_container'
            marker.innerHTML = @args.marker
            _.extend @marker_options(), { content: marker }

        create_infowindow: ->
            return null unless _.isString @args.infowindow

            boxText = document.createElement 'div'
            boxText.setAttribute 'class', 'infowindow_container'
            console.log @args
            boxText.innerHTML = @args.infowindow
            @infowindow = new InfoBox(@infobox(boxText))

            @bind_infowindow()

        infobox: (boxText)->
            content: boxText
            pixelOffset: new google.maps.Size(0, 0)
            boxStyle:
                width: '280px'


    handler = Gmaps.build 'Google', { builders: { Marker: RichMarkerBuilder }, markers: { maxRandomDistance: null } }

    handler.buildMap
        provider: {}
        internal:
            id: '#{id}'
    , ->
        json = #{markers}
        if json
            markers = handler.addMarkers json
            handler.bounds.extendWith markers
            handler.fitMapToBounds()
            if json.length == 1
                handler.getMap().setZoom #{Settings.LOCATIONS_DEFAULT_ZOOM}
        else
            handler.map.centerOn { lat: #{lat}, lng: #{lng} }
            handler.getMap().setZoom #{Settings.LOCATIONS_DEFAULT_ZOOM}

有谁知道如何正确设置?我发现有很多关于此的文档,这令人惊讶,因为 Turbolinks 是 Rails 4 的标准。任何帮助将不胜感激!

对于那些也在为此苦苦挣扎的人,我会在了解如何执行此操作后立即更新 Gmaps4Rails wiki!

4

1 回答 1

2

我想出的最好的方法(也是最干净的)是将javascript添加到资产管道中。这将确保 JQuery 可用。所以在一些咖啡脚本文件中是这样的:

$('#map').mappy()

在哪里定义 JQuery 插件 Mappy,如下所示:

(($, window) ->

    class Mappy
        # defaults:
        constructor: (el, options) ->
            @$el = $(el)
            # @options = $.extend({}, @defaults, options)

            @id         = @$el.attr 'id'
            @lat        = @$el.data 'lat'
            @lng        = @$el.data 'lng'
            @markers    = @$el.data 'markers'
            @handler    = Gmaps.build 'Google', { builders: { Marker: RichMarkerBuilder }, markers: { maxRandomDistance: null } }

            @handler.buildMap
                provider: {}
                internal:
                    id: @id
            , =>
                json = @markers
                if json
                    markers = @handler.addMarkers json
                    @handler.bounds.extendWith markers
                    @handler.fitMapToBounds()
                    if json.length == 1
                        @handler.getMap().setZoom $.LOCATIONS_DEFAULT_ZOOM
                else
                    @handler.map.centerOn { lat: @lat, lng: @lng }
                    @handler.getMap().setZoom $.LOCATIONS_DEFAULT_ZOOM


    class RichMarkerBuilder extends Gmaps.Google.Builders.Marker

        create_marker: ->
            options = _.extend @marker_options(), @rich_marker_options()
            @serviceObject = new RichMarker options

        rich_marker_options: ->
            marker = document.createElement 'div'
            marker.setAttribute 'class', 'marker_container'
            marker.innerHTML = @args.marker
            _.extend @marker_options(), { content: marker }

        create_infowindow: ->
            return null unless _.isString @args.infowindow

            boxText = document.createElement 'div'
            boxText.setAttribute 'class', 'infowindow_container'
            console.log @args
            boxText.innerHTML = @args.infowindow
            @infowindow = new InfoBox(@infobox(boxText))

            @bind_infowindow()

        infobox: (boxText)->
            content: boxText
            pixelOffset: new google.maps.Size(0, 0)
            boxStyle:
                width: '280px'

    $.fn.extend mappy: (option, args...) ->
        @each ->
            $this = $(this)
            data = $this.data('mappy')

            if !data
                $this.data 'mappy', (data = new Mappy(this, option))

            if typeof option == 'string'
                data[option].apply(data, args)

) window.jQuery, window

然后通过在你的haml中做这样的事情来使数据可用

- present @location, LocationPresenter do |p|
     #map{ data: {  markers: [p.marker].to_json, lat: p.latitude, lng: p.longitude } }
于 2013-11-12T00:07:21.400 回答