Add more markers to markerCluster without removing previous - ruby-on-rails

I build a map and add markers. When I'm calling AJAX , Some more records are coming from db and updating the location to map without reloading the map. But the problem is it is making new cluster for new records.
Here is code :
var marker, i;
var markers=[]
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map,
icon: locations[i][4]
});
google.maps.event.addListener(marker, 'mouseover', (function (marker, i) {
return function () {
infowindow.setContent("<img src="+locations[i][5]+" width='100%'><br> <strong>"+locations[i][0]+"</strong>");
infowindow.open(map, marker);
}
})(marker, i));
// assuming you also want to hide the infowindow when user mouses-out
marker.addListener('mouseout', function() {
infowindow.close();
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent("<img src="+locations[i][5]+" width='100%'><br> <strong>"+locations[i][0]+"</strong>");
infowindow.open(map, marker);
}
})(marker, i));
markers.push(marker);
}
var markerCluster = new MarkerClusterer(map, markers,{
imagePath: 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m'
});

You can Add markers
var markers = []
var marker = new google.maps.Marker({position: center});
markers.push(marker);
markerClusterer.addMarkers(markers);
Note that here I have added only one.
You can remove all markers
markerClusterer.clearMarkers();
markers = [];
Note that for tidiness I have also unset the markers array here.
you can go through
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/docs/reference.html

Related

iOS - Google Maps Places onclick conflicts with map onclick

I have a project created with ionic. In here I have a Google Map with a places search box.
I have included the Google Map library like so:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=SOMEKEY&libraries=places" defer></script>
Now in my TypeScript code I have the following
// init the google map
initMap() {
var centerOfMap;
var draggableMarker = false;
this.mapHasBeenInitialized = true;
this.isStaticLocation = false;
centerOfMap = new google.maps.LatLng(this.locationService.gpsLat, this.locationService.gpsLong);
draggableMarker = true;
var options = {
center: centerOfMap,
zoom: 11,
fullscreenControl: false,
disableDefaultUI: true, // dont allow default zoom/sattelite/street view
gestureHandline: 'cooperative' // disable moving map with one finger
};
this.map = new google.maps.Map(this.googleMap.nativeElement, options);
this.marker = new google.maps.Marker({
position: centerOfMap,
map: this.map,
draggable: draggableMarker
});
if(!this.isStaticLocation) {
var searchBox = new google.maps.places.SearchBox(this.googleInput.nativeElement);
// add the searchbar to the google map
this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(this.googleInput.nativeElement);
// Bias the SearchBox results towards current map's viewport
this.map.addListener('bounds-changed', () => {
searchBox.setBounds(this.map.getBounds());
});
searchBox.addListener('places_changed', () => {
var places = searchBox.getPlaces();
if(places.length == 0) {
return;
}
var bounds = new google.maps.LatLngBounds();
places.forEach(place => {
if(!place.geometry) {
console.log("returned place contains no geometry");
return;
}
this.setMarkerLocation(place);
if(place.geometry.viewport) {
bounds.union(place.geometry.viewport);
} else {
bounds.extends(place.geometry.location);
}
});
this.map.fitBounds(bounds);
});
}
if(draggableMarker) {
google.maps.event.addListener(this.marker, 'dragend', (event)=>{
this.getMarkerLocation();
});
}
google.maps.event.addListener(this.map, 'click', (event: any)=> {
var clickedLocation = event.latLng;
this.marker.setPosition(clickedLocation);
this.getMarkerLocation();
});
// neccessary for reload. Made async to trick loading process
setTimeout(()=> {
google.maps.event.trigger(this.googleMap.nativeElement, 'resize');
this.map.setCenter(centerOfMap);
}, 100);
}
// function to set the location marker on a different spot
setMarkerLocation(place: any) {
this.marker.setMap(null);
this.marker = new google.maps.Marker({
position: place.geometry.location,
map: this.map,
draggable: true
});
this.getMarkerLocation();
}
getMarkerLocation() {
var currLoc = this.marker.getPosition();
this.locationService.setGoogleMapsLocation(currLoc.lat(), currLoc.lng());
this.locationChanged = true;
}
And this code works like a charm in the browser and on Android. Basically what the code does is whenever someone taps on the map, the marker position changes to their tap location.
When a person searches for a Place, the places dropdown will show over the map. On android, when you tap a place in this dropdown, the marker will go to the selected place (f.e. australia).
On iOS however, the marker will position itself on the location where the person tapped and will totally ignore the tap on the place dropdown.
So when I'm in Europe and I type in 'Australia' and select 'Australia' from my dropdown, on Android I'll go to australia but on iOS I'll stay somewhere in Europe wherever the dropdown was positioned.

automatic geolocation in ruby

I jus started learn ruby on rails and currently I am creating my first rails app. And I ran into some problems. In my app, I would like to get user's position (latitude, longitude). So I can put the button "find me" and return user's locations. But I would like to load my page and show my position (latitude, longitude), don't press any buttons. And then use lat and lng in my controllers. How can I do this?
Add the below script in your view page.You may go ahead and modify this as needed as to show/customise messages and buttons.Remember to have a dedicated div with id="map-canvas" to show you map on the page.
I have used geocomplete.js to show map and allow user to enter places from search box .You may remove the scripts using geocomplete if not needed.
<script type="text/javascript">
// Enable the visual refresh
// google.maps.visualRefresh = true;
var map;
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: '<p>You are here!</p>'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}//initialize ends
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = '<p>Unable to find the current location</p>';
} else {
var content = '<p Your browser doesn\'t support geolocation.</p>';
}
var options = {
map: map,
zoom: 5,
position: new google.maps.LatLng(60, 105),
content: content
};
var marker = new google.maps.Marker({
position: new google.maps.LatLng(60, 105),
map: map,
animation: google.maps.Animation.DROP,
title: 'Sorry,we were unable to find your location'
});
marker.setAnimation(google.maps.Animation.BOUNCE);
var infowindow = new google.maps.InfoWindow(options);
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
infowindow.open(map,marker);
map.setCenter(options.position);
}//handleNoGeolocation ends
//load the page and execute above scripts
$(document).ready(function(){
$('#map-canvas').html("<p class='text-center text-alert'>Loading map...</p>").show(3000);
//load the map after 2 seconds
setTimeout('initialize()', 3000);
// $("#geocomplete").geocomplete({
// map: ".map-canvas-guest"
// });
//you may use this or remove this section using geocomplete.js if not needed.
$("#geocomplete").geocomplete();
$("#geocomplete").geocomplete(mapOptions).bind("geocode:result", function(event, result){
console.log(result.formatted_address);
//use this user entered address and you may call ajax here as well
})
})//document ends
</script>

Trying to eliminate closure error in google map eventListener

I have a google map with a load of markers on it, each corresponding to a different post in the html. Each marker id is the same as each post id. Inside the map initialize = function() {... I have the following code (I'm using gon to pass info from rails to javascript):
for (m = 0; m < gon.markers.length; m++) {
marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(gon.markers[m].lat, gon.markers[m].lng),
icon: image,
infowindow: gon.markers[m].infowindow,
id: gon.markers[m].id
});
google.maps.event.addListener(marker, 'mouseover', function() {
var image = $("#map-canvas").data('marker2');
this.setIcon(image);
// console.log("marker.id: " + marker.id);
// console.log("this.id" + this.id);
$('#' + marker.id).css('background', 'red');
});
google.maps.event.addListener(marker, 'mouseout', function() {
var image = $("#map-canvas").data('marker1');
this.setIcon(image);
$('#' + marker.id).css('background', 'white');
});
markers[markers.length] = marker;
}
Uncommenting the console.log lines demonstrates that it is the classic closure problem (marker.id always has the same value no matter which marker is hovered on).
My question is, how do I code it properly so it does as intended? I just can't get the code right now matter what I try. I've tried stuff like this but is just doesn't work:
marker.on('mouseover', noticeHover(marker.id));
function noticeHover(id) {
var image = $("#map-canvas").data('marker2');
this.setIcon(image);
$('#' + id).css('background', 'gainsboro');
}
Wrap the entire code that handles the marker-creation into a function and pass the items inside the loop as argument to this function:
for (m = 0; m < gon.markers.length; m++) {
//anonymous,self-executing function
(function(props){
var goo = google.maps,
marker = new goo.Marker({
map: map,
position: new goo.LatLng(props.lat,
props.lng),
icon: image,
infowindow: props.infowindow,
id: props.id
});
goo.event.addListener(marker, 'mouseover', function() {
var image = $("#map-canvas").data('marker2');
this.setIcon(image);
$('#' + marker.id).css('background', 'red');
});
goo.event.addListener(marker, 'mouseout', function() {
var image = $("#map-canvas").data('marker1');
this.setIcon(image);
$('#' + marker.id).css('background', 'white');
});
markers.push(marker);
}(
gon.markers[m]//pass current loop-item as argument
));
}

Drag and update location - how to do this?

I'm trying to follow the information on your wiki, stackExchange, etc to make this work.
The idea is to create a new location for the user. The app displays a map, put a marker on the 0,0 location and then the user drag this marker to any place and the form is updated with the new lat and log. Seems trivial and there's doc in the wiki, but I could not make it work.
I'm using gem version 2.1.2 and Rails 4.1. I had success showing maps, markers, etc, but I cannot make the callback and others functions to work. I'm using this doc to try: https://github.com/apneadiving/Google-Maps-for-Rails/wiki/Javascript-goodies#drop-a-marker-and-update-fields-attribute-in-a-form
Follow my view code:
handler = Gmaps.build('Google');
handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
markers = handler.addMarkers(
[
{
"lat": 0,
"lng": 0,
draggable: true
}
]
);
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
// Callback function
var markersArray = [];
var marker = handler.getMap().markers[0];
if (marker) {
// Move existing marker when editing a previously stored location
google.maps.event.addListener(marker.serviceObject, 'dragend', function() {
updateFormLocation(this.getPosition());
});
}
// On click, clear markers, place a new one, update coordinates in the form
google.maps.event.addListener(handler.getMap().serviceObject, 'click', function(event) {
clearOverlays();
placeMarker(event.latLng);
updateFormLocation(event.latLng);
});
});
// Other functions
// Update form attributes with given coordinates
function updateFormLocation(latLng) {
$('#centre_latitude').val(latLng.lat());
$('#centre_longitude').val(latLng.lng());
$('#centre_gmaps_zoom').val(handler.getMap().serviceObject.getZoom());
}
// Add a marker with an open infowindow
function placeMarker(latLng) {
var marker = new google.maps.Marker({
position: latLng,
map: handler.getMap().serviceObject,
draggable: true
});
markersArray.push(marker);
// Set and open infowindow
var infowindow = new google.maps.InfoWindow({
content: '<div class="popup"><h2>Awesome!</h2><p>Drag me and adjust the zoom level.</p>'
});
infowindow.open(handler.getMap().serviceObject, marker);
// Listen to drag & drop
google.maps.event.addListener(marker, 'dragend', function() {
updateFormLocation(this.getPosition());
});
}
// Removes the overlays from the map, including the ones loaded with the map itself
function clearOverlays() {
for (var i = 0; i < markersArray.length; i++ ) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
for (var i = 0; i < handler.getMap().markers.length; i++ ) {
handler.getMap().clearMarker(handler.getMap().markers[i]);
}
}
Then I get an error:
TypeError: undefined is not an object (evaluating 'handler.getMap().markers[0]')
Also, the marker is not draggable...
Is there any complete example of how to do this?
Thanks all!
There are many errors in your code. Hard to explain one by one.
Here is a solution suggestion.
Basically when you use
handler.getMap()
its already a google maps object, so dont do:
handler.getMap().serviceObject
I think I found a solution. Follows the code
handler = Gmaps.build('Google');
handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
markers = handler.addMarkers(
[
{
"lat": 0,
"lng": 0,
}
]
,{ draggable: true}
);
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
// Move existing marker
google.maps.event.addListener(markers[0].serviceObject, 'dragend', function() {
updateFormLocation(this.getPosition());
});
});
// Update form attributes with given coordinates
function updateFormLocation(latLng) {
$('#latitude').val(latLng.lat());
$('#longitude').val(latLng.lng());
}
Now the marker is draggable and I can update the correct field in the form.
Any other approaches are welcome.

Document name in geoxml3

My kml is as under
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Car Parks</name>
<description>Car Parks</description>
<Folder>
<name>Data Objects</name>
<open>1</open>
<description>data objects</description>
<Placemark id="CP11">
<name>CP11</name>
<description>CP11</description>
<styleUrl>#0-normal</styleUrl>
<Point>
<coordinates>4.878205,52.371968,0</coordinates>
</Point>
</Placemark>
</Folder>
</Document>
</kml>
My javascript is as under
geoXml = new geoXML3.parser({
createMarker: createMarker
});
createMarker:function(placemark, doc) {
var markerOptions = {
optimized: false
};
// Create the marker on the map
var marker = new google.maps.Marker(markerOptions);
if (!doc) {
doc.markers.push(marker);
}
google.maps.event.addListener(marker, 'click', function()
{
// I want to access the document name here of 'car Parks'
alert(doc.Document);
});
}
How can I get document name in marker click event of the marker? Basically when I click the marker on the map, I want to know the type of marker the user has clicked on.
There is an optional placemark parse function
pmParseFn
Which is passed a reference to the xml DOM for its associated placemark. example using it
It isn't really designed for your purpose, but if your KML format is fixed, you can get the <name> of the <Document> tag by doing this:
var map;
var geoXml = null;
function initialize() {
var latlong = new google.maps.LatLng(59.32, 13.48);
var googlemaps_options = {
zoom: 18,
center: latlong,
mapTypeId: google.maps.MapTypeId.SATELLITE,
streetViewControl: false
}
map = new google.maps.Map(document.getElementById('map_canvas'), googlemaps_options);
geoXml = new geoXML3.parser({
createMarker: createMarker,
pmParseFn: parsePlacemark,
map:map
});
geoXml.parse("http://www.geocodezip.com/geoxml3_test/SO_20140306_name.kml");
}
// Custom placemark parse function
function parsePlacemark (node, placemark) {
var addressNodes = node.parentNode.parentNode.getElementsByTagName('name');
var address = null;
if (addressNodes && addressNodes.length && (addressNodes.length > 0)) {
placemark.docName = geoXML3.nodeValue(addressNodes[0]);
}
}
function createMarker(placemark, doc) {
var markerOptions = {
optimized: false,
position: placemark.latlng,
map: map
};
// Create the marker on the map
var marker = new google.maps.Marker(markerOptions);
if (!doc) {
doc.markers.push(marker);
}
google.maps.event.addListener(marker, 'click', function()
{
// I want to access the document name here of 'car Parks'
alert(placemark.docName);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
working example
working example with 2 different KML files

Resources