Rob Hughes
Rob Hughes

Reputation: 906

Ruby on rails. Updating search results based on map position. Update with data from JSON

I am trying to dynamically update search results on my index page by moving the map. The search results should only show the results that are in the map bounds.

I can successfully return the bounds to the controller, and my server shows the updated results, I.E, displays only the results within these bounds, but I'm not sure how to reflect/update these results in the view.

I feel that I am missing something stupid, but after spending hours on this, I can't see it.

So far I have;

Gmaps callback:

google.maps.event.addListener(handler.getMap(), 'idle', function() {
        var bounds = handler.getMap().getBounds();
        drawItems(bounds);

Jquery for bounds :

function drawItems(theBounds) {
    var url = 'gigs.json/?sw_y=' + theBounds.getSouthWest().lng() +
                        '&sw_x=' + theBounds.getSouthWest().lat() +
                        '&ne_y=' + theBounds.getNorthEast().lng() +
                        '&ne_x=' + theBounds.getNorthEast().lat();
    $.get(url, function(newItemData) {
        handler.replace_markers(newItemData);
    });
}

This outputs something like:

/gigs.json....
sw_y=-148.84352170963916
sw_x=-13.80973371328428
ne_y=121.15647829036084
ne_x=87.24165143852134

Controller:

def index
    @loc_search  = true

    if (params[:sw_y] && params[:sw_x] && params[:ne_y] && params[:ne_x])
        bounds = [ [params[:sw_x].to_f, params[:sw_y].to_f],
                 [params[:ne_x].to_f, params[:ne_y].to_f] ]
        @gigs_within_bounds = Gig.within_bounding_box(bounds)
    else
        @gigs_within_bounds = Gig.all
    end


    if params[:search].present?
    @q = @gigs_within_bounds.where('date >= ?', Time.current.to_datetime).where(:filled => false).near(params[:search], 500, :order => 'distance' ).ransack(params[:q])
    else
    @q = @gigs_within_bounds.where('date >= ?', Time.current.to_datetime).where(:filled => false).ransack(params[:q])
    end

    @gigs = @q.result(distinct: true).page(params[:page]).per(20)
    @hash = Gmaps4rails.build_markers(@gigs) do |gig, marker|
      marker.infowindow render_to_string(:partial => "/gigs/infowindow", :locals => { :gig => gig}, :formats => [:html])
      marker.lat gig.latitude
      marker.lng gig.longitude
      marker.title gig.title
    end
  respond_to do |format|
        format.html # index.html.erb
        format.js
        format.json {
            @data = @gigs.collect {|v| {
                     :longitude => v.longitude,
                     :latitude => v.latitude,
            }
            return render :json => @data
        }}
    end
end

My server is successfully filtering as I move the map;

Eg.

Processing by GigsController#index as JSON
  Parameters: {"sw_y"=>"50.14085329036084", "sw_x"=>"-83.09701329217522", "ne_y"=>"-39.85914670963916", "ne_x"=>"55.2456675702868"}
Gig Load (0.3ms) etc etc etc...

I am just getting confused on how to update the search results with this data. Any help would be greatly appreciated, thanks.

EDIT:

I would like to add that I have a _map.js partial and index.js.erb for updating the map after searches.

_map.js.erb

 handler = Gmaps.build('Google', {
  markers: {
     randomize: true,
     maxRandomDistance: 10,
    clusterer: {
      maxZoom:  17,
      gridSize: 50,
    }
  }
});
    handler.buildMap({
      provider: {
        styles: mapStyle,
        minZoom: 2,
        maxZoom: 20,
      },
      internal: {id: 'map'}},
      function(){
      markers = handler.addMarkers(<%=raw @hash.to_json %>);
      handler.bounds.extendWith(markers);
      handler.fitMapToBounds();
    });

And index.js.erb

$('#gigs-list').html("<%= j render(partial: 'gigs') %>");
            $('#map').html('<%= escape_javascript render("map") %>');

I'm pretty sure I just need a way to submit the form/update the view with the new bounds parameters, as my server responds correctly to the map movement. When the server processes as html or js, the results get updated, but json no.

Upvotes: 0

Views: 398

Answers (1)

max
max

Reputation: 101976

You need to create a google.maps.LatLngBounds object and pass it to map.fitBounds (map being whatever variable holds a reference to the map).

$.get(url, function(newItemData) {
  var bounds = new google.maps.LatLngBounds({
    sw: { lat: sw_y, lng: sw_x }
    nw: { lat: ne_y, lng: ne_x }
  });
  handler.replace_markers(newItemData);
  map.fitBounds(bounds);
});

Another way to do this if you are plotting a bunch of markers and want the map fit the bounds dynamically around them is:

$.get(url, function(newItemData) {
  var bounds = new google.maps.LatLngBounds();
  var markers = $.map(newItemData, function(item){
    var marker = new google.maps.Marker({
      position: { lat: item["lat"], lng: item["lng"] },
      map: map,
      title: item["title"]
    });
    bounds.expand(marker.position);
    return marker;
  });

  map.fitBounds(bounds);
});

The advantage here is that the JSON response does not have to contain any info about the bounding box.

Upvotes: 1

Related Questions