Reputation: 906
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
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