Ajax Load Google Map Markers - javascript

I have a google map which loads results on page load which is fine but I have an ajax search form which updates the results by ajax in a separate div but it doesn't update the map. I am trying to figure out how to update the map when the ajax call is completed but I am stuck. Any help would be greatly appreciated!
Here is the code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js"></script>
<script>
$(document).ready(function() {
var markersInfo = $('.ia-card').map(function() {
var info = {
id: $(this).data('map-id'),
address: $(this).data('map-address'),
title: $(this).data('map-title'),
price: $(this).data('map-price'),
latitude: $(this).data('map-latitude'),
longitude: $(this).data('map-longitude'),
html: "<img src=" + $(this).data('map-image') + ">",
link: $(this).data("map-link"),
contentHtml: "<div class='image'>" + "<img src=" + $(this).data('map-image') + ">" + "</div>" + '<b>' + $(this).data('map-title') + '</b><br>' + "<div class='changeprice'><div style='display: none;' class='currency-selector'></div>" + $(this).data('map-price') + "</div>" + "<br><a href='" + $(this).data("map-link") + "'>More>></a>"
};
return info;
}).get();
var distinctMarkerInfo = [];
markersInfo.forEach(function(item) {
if (!distinctMarkerInfo.some(function(distinct) {
return distinct.id == item.id;
})) distinctMarkerInfo.push(item);
});
initGoogleMap(distinctMarkerInfo);
// GMAP ON SEARCH RESULTS PAGE
function initGoogleMap(markersInfo) {
var mapOptions = {
// zoom: 2,
// center: new google.maps.LatLng(53.334430, -7.736673)
},
bounds = new google.maps.LatLngBounds(),
mapElement = document.getElementById('stm_map_results'),
map = new google.maps.Map(mapElement, mapOptions);
markerList = []; // create an array to hold the markers
var geocoder = new google.maps.Geocoder();
var iconBase = '../assets/images/';
$.each(markersInfo, function(key, val) {
var marker = new google.maps.Marker({
//map: map,
position: {lat: parseFloat(val.latitude), lng: parseFloat(val.longitude)},
title: val.title,
icon: iconBase + 'single.png',
info: new google.maps.InfoWindow({
content: val.contentHtml
})
});
markerList.push(marker); // add the marker to the list
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, marker);
});
loc = new google.maps.LatLng(val.latitude, val.longitude);
bounds.extend(loc);
});
map.fitBounds(bounds);
map.panToBounds(bounds);
var markerCluster = new MarkerClusterer(map, markerList, {
imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'
});
};
});
</script>
<div id="stm_map_results" style="width:100%; height:600px;"></div>

Since you are displaying markers via MarkerClusterer i would propose the following solution to update the map.
once the data is retrieved, clear the existing markets from map using
MarkerCluster.clearMarkers function
initialize a MarkerCluster with a new data
The below example demonstrates how to "refresh" markers on the map:
function placeMarkers(data){
var markers = data.map(function (item, i) {
return new google.maps.Marker({
position: { lat: item.lat, lng: item.lng }
});
});
//1.clear existing markers
if (markerCluster)
markerCluster.clearMarkers();
//2.init marker cluster
markerCluster = new MarkerClusterer(map, markers,
{ imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m' });
}
Demo

Related

Google Map, Users Create Markers, How do I save

I've got code to allow users to pin a marker on a map. What I am missing is how to save the markers so that when the map reloads, the markers are still there.
<script src="http://maps.googleapis.com/maps/api/js"></script>
<script>
var map;
var myCenter=new google.maps.LatLng(38.9047,-77.0164);
function initialize()
{
var mapProp = {
center:myCenter,
zoom:7,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
google.maps.event.addListener(map, 'click', function(event) {
placeMarker(event.latLng);
});
}
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map,
});
var infowindow = new google.maps.InfoWindow({
content: 'Latitude: ' + location.lat() + '<br>Longitude: ' + location.lng()
});
infowindow.open(map,marker);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
You could utilize google.maps.Data API for that purpose, the example below demonstrates how to save and load markers info via localStorage.
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map,
});
var infowindow = new google.maps.InfoWindow({
content: 'Latitude: ' + location.lat() + '<br>Longitude: ' + location.lng()
});
infowindow.open(map, marker);
//place marker info
map.data.add(new google.maps.Data.Feature({properties:{},geometry:new google.maps.Data.Point(location)}));
}
function saveMarker() {
map.data.toGeoJson(function (json) {
localStorage.setItem('geoData', JSON.stringify(json));
});
}
function clearMarkers() {
map.data.forEach(function (f) {
map.data.remove(f);
});
}
function loadMarkers(map) {
var data = JSON.parse(localStorage.getItem('geoData'));
map.data.addGeoJson(data);
}
Demo

Google Maps V3 infowindows displaying wrong content on pins

I am plotting addresses and having an issue with the infowindow showing the right content everytime. Sometimes it shows the right content in the infowindow when clicked and sometimes it shows the wrong information for that map pin.
var map = null;
var markersArray = [];
var markers = [];
var openedInfoWindow ="";
var geocoder = new google.maps.Geocoder();
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(64.85599578876611, -147.83363628361917),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mapInfoManual"),
mapOptions);
google.maps.event.addListener(map, 'zoom_changed', function() {
zoomChangeBoundsListener = google.maps.event.addListener(map, 'bounds_changed', function(event) {
if (this.getZoom() > 20) // Change max/min zoom here
this.setZoom(18);
google.maps.event.removeListener(zoomChangeBoundsListener);
});
});
addMarker();
}
function addMarker() {
var bounds = new google.maps.LatLngBounds();
for(i=0; i<markersArray.length; i++)
{
CodeAddress(markersArray[i]['address']);
var mytitle = (markersArray[i]['title']);
var myaddress = (markersArray[i]['displayaddress']);
var linkurl = (markersArray[i]['linkurl']);
}
setTimeout(function()
{
for(i=0; i<markers.length; i++)
{
var point = new google.maps.LatLng(markers[i]['lat'], markers[i]['lng']);
var marker = new google.maps.Marker({
position: point,
map: map
});
bounds.extend(point);
var infoWindowContent = "<div style='padding:2px;'><div style='margin-bottom:5px;font-weight:700;color:#033551;'>"+ mytitle +"</div><div style='margin-bottom:5px;'>" + myaddress + "</div><div><a href='" + linkurl + "/'>More Details</a></div></div>";
openInfoWindow(marker,infoWindowContent)
}
map.fitBounds(bounds);
},2500);
}
// Address To Marker
function CodeAddress(address)
{
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
markers.push({
'lat':lat,
'lng':lng,
'address':address
});
}
});
}
//Info Window
function openInfoWindow(marker,infoWindowContent)
{
var infowindow = new google.maps.InfoWindow({
content: '<div class="cityMapInfoPop">'+infoWindowContent+'</div>'
});
google.maps.event.addListener(marker, 'click', function() {
if(openedInfoWindow !="")
{
openedInfoWindow.close()
}
infowindow.open(map,marker);
openedInfoWindow = infowindow;
});
}
Variables that I pass in:
<script type="application/javascript">
markersArray.push({
"title":'<?php echo $maptitle;?>',
"address":'<?php echo $markerAddress;?>',
"displayaddress":'<?php echo $displayAddress;?>',
"linkurl":'<?php echo $addressUrl;?>'
});
</script>
Your issue is that geocoding is asynchronous. You loop through calling the geocoder on all your addresses, but the order the results are returned in is not predictable.
use function closure to associate the marker with the infowindow
use function closure to associate the address with the marker
use the results of the geocoder inside its callback function.
Note that if you have more that approximately 10 markers in your array you will run into the quota/rate limit of the geocoder.
proof of concept fiddle
code snippet:
var map = null;
var markersArray = [];
var markers = [];
var openedInfoWindow = "";
var geocoder = new google.maps.Geocoder();
var bounds = new google.maps.LatLngBounds();
markersArray.push({
"title": 'marker 0',
"address": 'New York,NY',
"displayaddress": 'New York, NY',
"linkurl": 'http://google.com'
});
markersArray.push({
"title": 'marker 1',
"address": 'Boston, MA',
"displayaddress": 'Boston, MA',
"linkurl": 'http://yahoo.com'
});
markersArray.push({
"title": 'marker 2',
"address": 'Newark,NJ',
"displayaddress": 'Newark, NJ',
"linkurl": 'http://mapquest.com'
});
google.maps.event.addDomListener(window, "load", initialize);
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(64.85599578876611, -147.83363628361917),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mapInfoManual"),
mapOptions);
google.maps.event.addListener(map, 'zoom_changed', function() {
zoomChangeBoundsListener = google.maps.event.addListener(map, 'bounds_changed', function(event) {
if (this.getZoom() > 20) // Change max/min zoom here
this.setZoom(18);
google.maps.event.removeListener(zoomChangeBoundsListener);
});
});
addMarker();
}
function addMarker() {
var bounds = new google.maps.LatLngBounds();
for (i = 0; i < markersArray.length; i++) {
CodeAddress(markersArray[i]);
}
}
// Address To Marker
function CodeAddress(markerEntry) {
var mytitle = (markerEntry['title']);
var myaddress = (markerEntry['displayaddress']);
var linkurl = (markerEntry['linkurl']);
geocoder.geocode({
'address': markerEntry['address']
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map
});
bounds.extend(marker.getPosition());
var infoWindowContent = "<div style='padding:2px;'><div style='margin-bottom:5px;font-weight:700;color:#033551;'>" + mytitle + "</div><div style='margin-bottom:5px;'>" + myaddress + "</div><div><a href='" + linkurl + "/'>More Details</a></div></div>";
openInfoWindow(marker, infoWindowContent);
markers.push(marker);
map.fitBounds(bounds);
} else {
alert("geocode failed: " + status);
}
});
}
//Info Window
function openInfoWindow(marker, infoWindowContent) {
var infowindow = new google.maps.InfoWindow({
content: '<div class="cityMapInfoPop">' + infoWindowContent + '</div>'
});
google.maps.event.addListener(marker, 'click', function() {
if (openedInfoWindow != "") {
openedInfoWindow.close();
}
infowindow.open(map, marker);
openedInfoWindow = infowindow;
});
}
html,
body,
#mapInfoManual {
height: 500px;
width: 500px;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?ext=.js"></script>
<div id="mapInfoManual" style="border: 2px solid #3872ac;"></div>
Since you didn't provide a working JSFiddle, it was rather difficult to figure out what your problem is. That said, you can look at this JSFiddle that I made for you to review what I'm doing, vs what you're doing.
Why are you using setTimeout() to place your markers? Also, you may have better results if you create an individual infoWindow per marker, instead of using a "global" infoWindow (which is what it looks like you're doing).
If you edit your post to add a working example of your problem, I can help further.
window.places = [{
title: "foo",
address: {
lat: parseFloat("64.85599578876611"),
lng: parseFloat("-147.83363628361917")
},
displayAddress: "101 BLVD",
linkURL: "google.com"
}, {
title: "bar",
address: {
lat: parseFloat("62.85599578876611"),
lng: parseFloat("-147.83363628361917")
},
displayAddress: "202 BLVD",
linkURL: "images.google.com"
}, ]
function initialize() {
"use strict";
var myLatlng = new google.maps.LatLng(window.places[0].address.lat, window.places[0].address.lng),
mapOptions = {
zoom: 4,
center: myLatlng
};
window.map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
$.each(window.places, function(i) {
var infowindow = new google.maps.InfoWindow({
content: "<div style='padding:2px;'><div style='margin-bottom:5px;font-weight:700;color:#033551;'>" + window.places[i].title + "</div><div style='margin-bottom:5px;'>" + window.places[i].displayAddress + "</div><div><a href='" + window.places[i].linkURL + "/'>More Details</a></div></div>"
}),
marker = new google.maps.Marker({
position: new google.maps.LatLng(window.places[i].address.lat, window.places[i].address.lng),
map: window.map,
title: window.places[i].title
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(window.map, marker);
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<div id="map-canvas"></div>

Google map Zoomed fully

Hi in my google map i just draw a one marker when map loads.But then map is zoomed fully in which is really confusing. but when i draw more than one markers map is centered properly and zoomed to a certain level. how can it overcome this.
i have got a loop inside my draw markers function and in that i get only one object that has coordinates. when i get more than one objects from 'markers' map is centered properly. but when it has a only one object to loop. markers gets drawn but map is not well centered and zoomed(zoomed in fully)
function drawMarkers(markerList) {
debugger;
var mapOptions = {
center: new google.maps.LatLng(-24.504710, 134.039231),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var currentLocation;
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
var infoWindow = new google.maps.InfoWindow();
var lat_lng = new Array();
var latlngbounds = new google.maps.LatLngBounds();
for (i = 0; i < markers.length; i++) {
//if (markerList[i].Longitude > 0) {
var data = markerList[i]
var myLatlng = new google.maps.LatLng(data.Latitude, data.Longitude);
lat_lng.push(myLatlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: data.DriverName,
});
var driverCurrentLocation = document.getElementById('<%= hdfDriverCurrentLocation.ClientID %>').value;
latlngbounds.extend(marker.position);
//if (markerList[i].Longitude > 0) {
(function (marker, data) {
google.maps.event.addListener(marker, "click", function (e) {
debugger;
var lat = data.Latitude;
var lng = data.Longitude;
var latlng = new google.maps.LatLng(lat, lng);
var geocoder = geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
currentLocation = results[1].formatted_address;
}
infoWindow.setContent('<div style="overflow: auto;width: 275px;">' +
'<div id="leftSideMainDiv" class="col25" style="padding-Left:0px; width:22%;">' +
'<div class="col100"><img src="../Images/DriverImages/driver_icon.jpg" height="60" width="60"/></div>' +
'</div>' +
'<div id="RightSideMainDiv" class="col75" style="width:72%;">' +
'<div class="col100" style="font-weight:bold; padding-top:0px; padding-left:0px; font-size:smaller;"> ' + data.DriverName + '</div>' +
'<div style="font-size:smaller; padding-top:15px;">Job Number :' + data.JobId + ' - ' + data.JobType + '</div>' +
'<div style="font-size:smaller;">Delivery Address :' + data.DeliveryAddress + '</div>' +
'<div style="font-size:smaller;">Current Location :' + currentLocation + '</div>' +
'<div style="font-size:smaller;">Last Update :' + data.LastUpdatedTime + '</div>' +
'</div>');
infoWindow.open(map, marker);
}
});
});
})(marker, data);
//}
}
//}
map.setCenter(latlngbounds.getCenter());
map.fitBounds(latlngbounds);
map.setZoom(5);
}
Related question: How to set zoom level in google map
If you only have one marker (markers.length == 1), then don't call map.fitBounds(). Change:
map.setCenter(latlngbounds.getCenter());
map.fitBounds(latlngbounds);
map.setZoom(5);
To:
map.setCenter(latlngbounds.getCenter());
if (marker.length != 1) map.fitBounds(latlngbounds);
map.setZoom(5);
on the initialization of maps set the zoom level, Here the zoom is set to 5
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
google.maps.event.addDomListener(window, 'load', function () {
map.setZoom(5);
});
Add the map variable outside of map's function scope
var map;
and then modify the line inside your map function-
map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
then after calling your map function drawMarkers(markerList) you need to set the zoom as-
$(document).ready(function(){
drawMarkers(markerList)
google.maps.event.addDomListener(window, 'load', function () {
map.setZoom(5);
});
});
Let me know if that works!

Google Map API - infowindow in foreach loop

Hello I'm retrieving data from SqlServerCe so I created foreach loop to create markers - that works it creates multiple markers but now I wanted to add to each of these marker an infowindow. But now whenever I click on marker the infowindow pops-up on the lastly created marker.
<script>
function initialize() {
var mapProp = {
center:new google.maps.LatLng(51.508742,-0.120850),
zoom:5,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
var map=new google.maps.Map(document.getElementById("googleMap")
, mapProp);
$(function () {
#foreach (var row in data)
{
<text>
var marker = new google.maps.Marker({ position: new google.maps.LatLng(#row.GeoLat, #row.GeoLong),
map: map });
marker.info = new google.maps.InfoWindow({
content: "test"
});
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, marker);
});
</text>
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
May someone help me with adding infowindow to each created markers?
Thank you for your responding and your time.
This is how I load from SqlServerCe
var db = Database.Open("StarterSite");
var data = db.Query("SELECT DescriptionService,GeoLong,GeoLat FROM services");
var array = new []{data} ;
You can use the following, written in javascript
var infoWindowContent = [];
for(var index=0; index< places.length; index++){
infoWindowContent[index] = getInfoWindowDetails(places[index]);
var location = new google.maps.LatLng(places[index].latitude,places[index].longitude);
bounds.extend(location);
marker = new google.maps.Marker({
position : location,
map : map,
title : places[index].title
});
google.maps.event.addListener(marker, 'click', (function(marker,index){
return function(){
infoWindow.setContent(infoWindowContent[index]);
infoWindow.open(map, marker);
map.setCenter(marker.getPosition());
map.setZoom(15);
}
})(marker,index));
}
function getInfoWindowDetails(location){
var contentString = '<div id="content" style="width:270px;height:100px">' +
'<h3 id="firstHeading" class="firstHeading">' + location.title + '</h3>'+
'<div id="bodyContent">'+
'<div style="float:left;width:100%">'+ location.address + '</div>'+
'</div>'+
'</div>';
return contentString;
}
I added an array infoWindowContent then added the information to the array. You can use the same logic

Got a fault in my google maps code

I am making a google maps for my website so you can view where each user is.
This works perfect only when you click on an icon of someone it will show you the same every time i cant understand it am i doing something wrong?
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET","includes/xml.php",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
var x=xmlDoc.getElementsByTagName("USER");
var infoWindow = new google.maps.InfoWindow();
var map;
var users = [];
function initialize() {
var mapOptions = {
zoom: 9,
center: new google.maps.LatLng(52.1424, 5.09428),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
for (i=0;i<x.length;i++) {
var id = x[i].getElementsByTagName("USERID")[0].childNodes[0].nodeValue;
users['USERNAME'+id] = x[i].getElementsByTagName("USERNAME")[0].childNodes[0].nodeValue;
users['CITY'+id] = x[i].getElementsByTagName("CITY")[0].childNodes[0].nodeValue;
users['COUNTRY'+id] = x[i].getElementsByTagName("COUNTRY")[0].childNodes[0].nodeValue;
users['IMAGE'+id] = x[i].getElementsByTagName("IMAGE")[0].childNodes[0].nodeValue;
users['IMAGEPIN'+id] = x[i].getElementsByTagName("IMAGEPIN")[0].childNodes[0].nodeValue;
users['LAT'+id] = x[i].getElementsByTagName("LAT")[0].childNodes[0].nodeValue;
users['LONG'+id] = x[i].getElementsByTagName("LONG")[0].childNodes[0].nodeValue;
users['DATETIME'+id] = x[i].getElementsByTagName("DATETIME")[0].childNodes[0].nodeValue;
users['TWITTER'+id] = x[i].getElementsByTagName("TWITTER")[0].childNodes[0].nodeValue;
users['FA'+id] = x[i].getElementsByTagName("FA")[0].childNodes[0].nodeValue;
users['ACTIVEUSER'+id] = x[i].getElementsByTagName("ACTIVEUSER")[0].childNodes[0].nodeValue;
users['myLatlng'+id] = new google.maps.LatLng(users['LAT'+id],users['LONG'+id]);
users['content'+id] = '<div style="width:220px;"><img id="avatar"style="margin-right: 5px;" src="' + users['IMAGE'+id] + '"></img>' +
'<b>' + users['USERNAME'+id] + '</b><br />' +
users['CITY'+id] + '<br />' + users['COUNTRY'+id] + '<br />' +
'<i>' + users['DATETIME'+id] + '</i><br />' +
'<img src="http://www.kinzart.com/images/fur-affinity-icon.png" Alt="Twitter" width="30" height="30">' +
'<img src="http://biophiliccities.org/wp-content/uploads/2013/06/twitterICON.png" Alt="Twitter" width="30" height="30">';
users['window'+id] = new google.maps.InfoWindow({ content: users['content'+id]});
users['marker'+id] = new google.maps.Marker({ position: users['myLatlng'+id], map: map, title: users['USERNAME'+id], icon: users['IMAGEPIN'+id]});
google.maps.event.addListener(users['marker'+id], 'click', function() { infoWindow.setContent(users['content'+id]); infoWindow.open(map, users['marker'+id]) });
}
}
google.maps.event.addDomListener(window, 'load', initialize);
The problem is that when you setup your event listener within the loop, it ends up that every iteration of the loop sets the infowindow content to be whatever the last value of users['content'+id] is. You need to look into using closures in your code.
Here's another way of doing it that should work:
for (i=0;i<x.length;i++) {
... // trimmed for brevity
users['marker'+id] = new google.maps.Marker({ position: users['myLatlng'+id], map: map, title: users['USERNAME'+id], icon: users['IMAGEPIN'+id]});
bindInfoWindow(users['marker'+id], users['content'+id]);
}
then have this function:
function bindInfoWindow(marker, content) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(content);
infoWindow.open(map, marker)
});
}

Categories

Resources