谷歌地图的导轨 - 更新标记与AJAX [英] Google Maps for Rails - update markers with AJAX

查看:218
本文介绍了谷歌地图的导轨 - 更新标记与AJAX的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个Web应用程序,我使用Ruby on Rails的。我们的指数是由搜索领域的地图和。您可以搜索的位置和地图更新的标记。

我想使用Ajax,以避免刷新页面。所以我加了远程:真正的的形式,一个的respond_to 在控制器和一个新的 sea​​rch.js.erb。我的 search.js.erb 渲染的部分 _googlemap.erb 包含脚本来初始化地图。

下面是我的问题。由于地图已经存在,这就像如果我想创建同一对象两次,这当然不行,是awfull。我想更新与新的地图只标记。但我不能找到一个方法来做到这一点。

我看到Gmaps4rails前版本集成了一个办法做到这一点( Gmaps.map.replaceMarkers(your_markers_json_array); ),但它似乎并没有现在的工作。当我使用它,我得到这个错误:类型错误:Gmaps.map未定义。我试着用 handler.replaceMarkers(); 但是这一次我有类型错误:handler.replaceMarkers不是一个函数

我是新来的Javascript和Rails的,但我想提高我的知识,我真的需要去与这个Web应用程序的其余部分。我一直在寻找一个解决方案无处不在互联网上,但徒劳无功。

这里 Live网站

请,有人能告诉我怎么能做到这一点,我在做什么错了?

在提前千恩万谢,

席琳

  

zones_controller.rb

 高清搜索
   respond_to代码做|格式|
     format.html.none做
      sea​​rch_params = PARAMS [:区] [搜索]
         坐标=地理coder.coordinates(search_params)。加入()
         @zones = Zone.search(
           ,{aroundLatLng=>坐标,
                  aroundRadius=>各地500公里500000 #Searches
                })
         如果coordinates.nil?
           @zones = Zone.search(PARAMS [搜索])
         ELSIF @ zones.empty?
           @zones = Zone.all
           闪光[:错误] =无区可以找到,请重试。
         结束
       build_map(@zones)
     结束

     format.js
   结束
结束

高清build_map(阵列)
  @hash = Gmaps4rails.build_markers(阵列)办|区,标记|
    marker.lat zone.latitude
    marker.lng zone.longitude
    marker.json({标题:zone.description,ID:zone.id})
    marker.infowindow render_to_string(:部分=>中/区域/ map_box,当地人:{区:区})
  结束
结束
 

  

search.html.erb

 < D​​IV ID =地图的风格=宽度:100%;高度:700像素;'>
< / DIV>
  <  - !开始谷歌地图 - >

<脚本类型=文/ JavaScript的ID =map_script>
   $(文件)。就绪(函数(){
     <%=渲染'GoogleMap的',哈希:@hash%>
   }); //文档就绪
< / SCRIPT>
 

  

  

_googlemap.erb

 处理程序= Gmaps.build('谷歌');
handler.buildMap({提供商:{
    disableDefaultUI:真正的,
    mapTypeId:google.maps.MapTypeId.TERRAIN
  },内部:{ID:'地图'}
}, 功能(){
  markers_json =<%=原hash.to_json%取代;
  标记= _.map(markers_json,功能(marker_json){

    标记= handler.addMarker(marker_json);
    handler.getMap()setZoom(4)。

    _.extend(标记,marker_json);

    marker.infowindow =新google.maps.InfoWindow({
      内容:marker.infowindow
    });

    返回标记;
  });

  handler.bounds.extendWith(标记);
  handler.fitMapToBounds();
});
 

  

search.js.erb

  $('#map_script)replaceWith(<%=渲染'GoogleMap的',哈希:@hash%>中)。
 

解决方案

为什么你不只是更新为新标记的地图吗?含义,而不是重新绘制整个地图的每个搜索后,只需通过删除所有标记和添加新的更新现有的地图上的标记。

我还没有验证的方法,但我想它应该工作,更高效:

创建一个应用程序/资产/ JavaScript的/ map.js 文件。您可以将地图相关的功能有。创建一个函数来更新您的地图上的标记在这个文件:

  

map.js

 (函数(){
  / * __markers将举行一个参考当前显示的所有标记
     在地图上,作为GMaps4Rails不会为你做。
     这会不会影响全局窗口对象,因为我们是嵌套
     在自执行匿名函数* /
  VAR __markers;

  功能updateMarkers(地图,markersData)
  {
    //删除当前标记
    map.removeMarkers(__标志);

    //增加每个标记到地图根据接收到的数据
    __markers = _.map(markersData,功能(markerJSON){
      标记= map.addMarker(markerJSON);
      map.getMap()setZoom(4)。 //不知道这应该是在这个迭代器!

      _.extend(标记,markerJSON);

      marker.infowindow =新google.maps.InfoWindow({
        内容:marker.infowindow
      });

      返回标记;
    });

    map.bounds.extendWith(__标志);
    map.fitMapToBounds();
  };

  //发布我们的窗口的方法。你或许应该有自己的空间
  window.updateMarkers = updateMarkers;
})();
 

此功能可用于初始化地图并对其进行更新。正如你不会(如果我的回答满足你)呈现地图的两倍,可以删除 _google_map.erb 键,把它的内容返回到 search.html .erb ,但使用我们刚刚创建的函数:

  

search.html.erb

 < D​​IV ID =地图的风格=宽度:100%;高度:700像素;'>
< / DIV>
  <  - !开始谷歌地图 - >

<脚本类型=文/ JavaScript的ID =map_script>
   $(文件)。就绪(函数(){
       mapHandler = Gmaps.build('谷歌');
       mapHandler.buildMap({提供商:{
           disableDefaultUI:真正的,
           mapTypeId:google.maps.MapTypeId.TERRAIN
         },内部:{ID:'地图'}
       }, 功能(){
         VAR markersData =<%=原@ hash.to_json%取代;
         updateMarkers(mapHandler,markersData);
       });
   }); //文档就绪
< / SCRIPT>
 

不要忘了var关键字声明变量的时候,否则最终会被全局,这是不好的^^
请注意,我故意留下 mapHandler 作为一个全局变量:您将需要访问您的处理程序,当有人使用搜索后,更新标记。这可能不是一个理想的事情,但这个问题不是关于重构你的code所以让我们保持这种方式。

所以,现在我的解决方案为您带来与在页面加载指定的标记初始化地图。换句话说,一切都没有改变!

不过你现在就允许重用这个 updateMarkers 函数来改变你的地图上显示的标记。这就是你 search.js.erb 脚本应该做的:

  

search.js.erb

 (函数(){
  VAR markersData =<%=原@ hash.to_json%取代;
  updateMarkers(mapHandler,markersData);
})();
 

这就是它!希望它会带你到你的项目的下一步:)

I am working on a web app and I use Ruby on Rails. Our index is made of a map and of a search field. You can search a location and the map updates its markers.

I would like to use Ajax to avoid refreshing the page. So I added remote: true to the form, a respond_to in the controller and a new search.js.erb. My search.js.erb renders a partial _googlemap.erb which contains the script to initialize the map.

Here is my problem. As the map already exists, it's like if I wanted to create the same object twice, which of course doesn't work and is awfull. I'd like to update only markers in the map with new ones. But I can't find a way to do it.

I saw the former version of Gmaps4rails integrated a way to do it ( Gmaps.map.replaceMarkers(your_markers_json_array); ) but it doesn't seem to work now. When I use it, I got this error: "TypeError: Gmaps.map is undefined". I tried with "handler.replaceMarkers();" but this time I have "TypeError: handler.replaceMarkers is not a function".

I am new to Javascript and to Rails, but I want to improve my knowledge and I really need to go on with the rest of this web app. I have been looking for a solution everywhere on the internet but in vain.

Live website here

Please, could someone tell me how I could do that and what I am doing wrong?

MANY thanks in advance,

Céline

zones_controller.rb

def search
   respond_to do |format|
     format.html.none do
      search_params = params[:zone][:search]
         coordinates = Geocoder.coordinates(search_params).join(",")
         @zones = Zone.search(
           "", { "aroundLatLng" => coordinates, 
                  "aroundRadius" => 500000  #Searches around 500 km
                })
         if coordinates.nil?
           @zones = Zone.search(params[:search])
         elsif @zones.empty?
           @zones = Zone.all
           flash[:error] = "No zone could be found. Please try again."
         end
       build_map(@zones)
     end

     format.js
   end
end

def build_map(array)
  @hash = Gmaps4rails.build_markers(array) do |zone, marker|
    marker.lat zone.latitude
    marker.lng zone.longitude
    marker.json({ title: zone.description, id: zone.id })
    marker.infowindow render_to_string(:partial => "/zones/map_box", locals: { zone: zone })
  end
end

search.html.erb

    <div id="map" style='width: 100%; height: 700px;'>
</div>
  <!-- Beginning Google maps -->

<script type="text/javascript" id="map_script">
   $(document).ready(function() {
     <%= render 'googlemap', hash: @hash %>
   }); // Document ready
</script>

_googlemap.erb

handler = Gmaps.build('Google');
handler.buildMap({ provider: {
    disableDefaultUI: true,
    mapTypeId: google.maps.MapTypeId.TERRAIN
  }, internal: {id: 'map'}
}, function(){
  markers_json = <%= raw hash.to_json %>;
  markers = _.map(markers_json, function(marker_json){

    marker = handler.addMarker(marker_json);
    handler.getMap().setZoom(4);

    _.extend(marker, marker_json);

    marker.infowindow = new google.maps.InfoWindow({
      content: marker.infowindow
    });

    return marker;
  });

  handler.bounds.extendWith(markers);
  handler.fitMapToBounds();
});

search.js.erb

$('#map_script').replaceWith("<%= render 'googlemap', hash: @hash %>");

解决方案

Why don't you just update the map with the new markers? Meaning, instead of re-rendering the whole map after each search, just update the markers on the existing map by removing all markers and adding the new ones.

I haven't verified the method, but I guess it should work and be more efficient:

Create a app/assets/javascript/map.js file. You can store your map-related functions there. Create a function to update your map's markers in this file:

map.js

(function() {
  /* __markers will hold a reference to all markers currently shown
     on the map, as GMaps4Rails won't do it for you.
     This won't pollute the global window object because we're nested
     in a "self-executed" anonymous function */
  var __markers;

  function updateMarkers(map, markersData) 
  {
    // Remove current markers
    map.removeMarkers(__markers);

    // Add each marker to the map according to received data
    __markers = _.map(markersData, function(markerJSON) {
      marker = map.addMarker(markerJSON);
      map.getMap().setZoom(4); // Not sure this should be in this iterator!

      _.extend(marker, markerJSON);

      marker.infowindow = new google.maps.InfoWindow({
        content: marker.infowindow
      });

      return marker;
    });

    map.bounds.extendWith(__markers);
    map.fitMapToBounds();
  };

  // "Publish" our method on window. You should probably have your own namespace
  window.updateMarkers = updateMarkers;
})();

This function can be used to initialize your map and to update it. As you will not (if my answer satisfies you) render the map twice, you can delete _google_map.erb and put its content back into search.html.erb, but using the function we've just created:

search.html.erb

    <div id="map" style='width: 100%; height: 700px;'>
</div>
  <!-- Beginning Google maps -->

<script type="text/javascript" id="map_script">
   $(document).ready(function() {
       mapHandler = Gmaps.build('Google');
       mapHandler.buildMap({ provider: {
           disableDefaultUI: true,
           mapTypeId: google.maps.MapTypeId.TERRAIN
         }, internal: {id: 'map'}
       }, function(){
         var markersData = <%= raw @hash.to_json %>;
         updateMarkers(mapHandler, markersData);
       });
   }); // Document ready
</script>

Please don't forget the var keyword when declaring variables, otherwise they will end up being globals, and that's bad ^^
Note that I have deliberately left mapHandler as a global variable: you will need access to your handler to update markers later when someone uses the search. This is probably not an ideal thing to do, but this question is not about refactoring your code so let's keep it this way.

So now my solution brings you a map that initializes with the given markers on page load. In other words, nothing has changed!

However you're now allowed to reuse this updateMarkers function to change the markers displayed on your map. That's what you search.js.erb script should do:

search.js.erb

(function() {
  var markersData = <%= raw @hash.to_json %>;
  updateMarkers(mapHandler, markersData);
})();

That's it! Hopefully it'll take you to the next step of your project :)

这篇关于谷歌地图的导轨 - 更新标记与AJAX的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆