Google Maps is grey after being called a second time - javascript

I am looping through some JSON files and using the address from the JSON file for the google maps. I know the address is working properly because I set an alert to show the variable and it's showing what I expect. The call for the map is inside a click function. on one virtual page I have a list of customers and when the user clicks that customer, it redirects to another virtual page to display that customers information, with a map showing their address. When I do this for the first time , it works. If I click back, then select a different customer the map is just grey. Any idea why this is happening?
Here is my click function..
function cHandle(num) {
$("#custSpan" + i).on("click", function () {
window.location.href = "#CustInv";
custName = customer.Customer[num].compName;
$("#CustInvHead").html(custName);
$("#invoiceh2").html(custName + "'s Invoices");
$("#custInfo").empty();
$("#invoice").empty();
$("#map-canvas").empty();
var inc = customer.Customer[num].compId;
$("#custInfo").append("Customer ID: " + customer.Customer[num].compId + "<br /><br />"
+"Customer Name: " + custName + "<br /><br />"
+"Customer Address: " + customer.Customer[num].compAddress + "<br /><br />"
+"Customer Contact: " + customer.Customer[num].compContact + "<br /><br />"
+"Customer Phone: " + customer.Customer[num].compPhone + "<br/ ><br />"
+ "Customer Email: " + customer.Customer[num].compEmail + ""
);
address = customer.Customer[num].compAddress;
//alert(address);
codeAddress();
})
}
cHandle(i);
And here is my maps stuff..
function success(pos) {
lat = pos.coords.latitude;
lng = pos.coords.longitude;
drawMap();
}
function error(err) {
alert("Error " + err.code + " : " + err.message);
}
;
function codeAddress() {
lat = 0;
lng = 0;
//Get the address
//address = "123 Fake St";
if (address == "") {
alert("No Address Entered");
return;
}
//Change address to coordinates to plot on map
else {
geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var myLatLng = results[0].geometry.location;
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
drawMap();
}
else {
alert("Geocode was not successful for the following reason: " + status);
return;
}
})
}
}
function drawMap() {
mapCenter = new google.maps.LatLng(lat, lng);
var mapOptions = {
center: mapCenter,
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//Display the address
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
//Map Marker
var myLoc = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
position: mapCenter
});

You call several times the creation of the map as you should call once (Initialize) map and call several times the function of creating the marker.
split the code in drawMap in two
first declare the var map at top (window) level (outside the functions)
and initialize your map
var map
function initialize() {
mapCenter = new google.maps.LatLng(lat, lng);
var mapOptions = {
center: mapCenter,
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//Display the address
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
google.maps.event.addDomListener(window, 'load', initialize);
</script>
second in the codeAddress() function call only the create marker function
function createMarker() {
var myLoc = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
position: mapCenter
});
}

Related

Changing and saving content inside info window after close

I have a map that geocodes locations retrieved from JSON and sticks a marker on the map.
The markers also have an infowindow that shows the markers name and rating.
There's a button inside an infowindow that increments a rating counter when you click a button.
The initial counter is retrieved from JSON.
Annoyingly, when the info window closed and reopen, the counter value resets.
I tried populating an object with all of the marker ratings, updating the object when the button is clicked and then output the rating from the object inside the contentString for the infowindow. This didn't work and the same initial rating counter was shown after re-opening the infowindow.
My code is below, any help would be appreciated.
var map;
var geocoder;
var infowindow;
var rating;
function initMap() {
var mapElement = document.getElementById("map_canvas");
geocoder = new google.maps.Geocoder();
var mapOptions = {
center: new google.maps.LatLng(53.481949, -2.237430),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(mapElement, mapOptions);
}
$(document).on('click', '#been-there', function(event){
var entryID = $(this).data('entry-id');
var rating = $(this).data('rating');
var dataString = 'id='+ entryID;
rating++;
$.ajax({
type: "POST",
url: "db-been-there.php",
data: dataString,
cache: false,
}).success(function(html){
console.log(html);
}).fail(function(html){
console.log(html);
});
$('#rating').html(rating);
});
$.getJSON("db-output.php", function(dbJSON) {
$.each(dbJSON, function(key, data) {
var url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + data.lat + "," + data.lng + "&result_type=sublocality|political&key=AIzaSyCsY-LOPL7dGbA1ShBEu7zMO8_GaSBA3Vg";
$.getJSON(url, function(reverseGeo) {
var postal_town = reverseGeo.results[0].formatted_address;
geocoder.geocode( { 'address': postal_town}, function(results, status) {
if (status == 'OK') {
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: data.name
});
var contentString = '<div id="content">'+
'<h1>' + data.name + '</h1>' +
'<button id="been-there" data-rating="' + data.rating + '" data-entry-id="' + data.id + '">Seen it</button>' +
'<p><strong>Rating: </strong><span id="rating">' + data.rating + '</span></p>' +
'</div>';
marker.addListener('click', function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
});
});
});
EDIT: Resolved code and JSFiddle below
Resolved JSFiddle: https://jsfiddle.net/BleepyEvans/3czqmqav/
var locations = [
{
"id": "1",
"name": "Location 1",
"lat": "53.408371",
"lng": "-2.991573",
"rating": "17"
},
{
"id": "2",
"name": "Location 2",
"lat": "53.789528",
"lng": "-2.969411",
"rating": "8"
},
]
var map;
var geocoder;
var infowindow;
var rating;
var markers = [];
function initMap() {
var mapElement = document.getElementById("map_canvas");
geocoder = new google.maps.Geocoder();
var mapOptions = {
center: new google.maps.LatLng(53.481949, -2.237430),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(mapElement, mapOptions);
}
$(document).on('click', '#been-there', function(event){
var entryID = $(this).data('entry-id');
var dataString = 'id='+ entryID;
rating = markers[entryID].rating;
rating++;
markers[entryID].rating = rating;
console.log(markers[entryID].rating);
$('#rating').html(rating);
});
$.each(locations, function(key, data) {
var url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + data.lat + "," + data.lng + "&result_type=sublocality|political&key=AIzaSyCsY-LOPL7dGbA1ShBEu7zMO8_GaSBA3Vg";
$.getJSON(url, function(reverseGeo) {
var postal_town = reverseGeo.results[0].formatted_address;
geocoder.geocode( { 'address': postal_town}, function(results, status) {
if (status == 'OK') {
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: data.name,
rating: data.rating
});
markers[data.id] = marker;
console.log(markers[data.id].rating);
marker.addListener('click', function() {
var contentString = '<div id="content">'+
'<h1>' + data.name + '</h1>' +
'<button id="been-there" data-rating="' + data.rating + '" data-entry-id="' + data.id + '">Been There</button>' +
'<p><strong>Rating: </strong><span id="rating">' + markers[data.id].rating + '</span></p>' +
'</div>';
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
});
});
Rather than just create an HTML string which includes the rating data that you assign to your infowindow, I'd add the rating value to the Marker object itself.
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: data.manufacturer_name,
rating: data.rating
});
Save those markers in an object keyed on their ID:
markers[data.id] = marker;
Then when the user clicks the button, update that value:
$(document).on('click', '#been-there', function(event){
var entryID = $(this).data('entry-id');
rating = markers[entryID].rating;
rating++;
And update the value on the Marker:
markers[entryID].rating = rating;
If it doesn't work directly accessing the rating property on the markers, you might need to use:
markers[entryID].get('rating');
markers[entryID].set('rating', rating);

Get place_id of address_components

I am using Google place autocomplete. And I don't know how to get place_id of address_components. In JSON there are only long_name, short_name, types.
My code is here:
var object_location = document.getElementById('object_location'),
autoComplete = new google.maps.places.Autocomplete(object_location);
autoComplete.addListener('place_changed', function() {
var place = autoComplete.getPlace();
console.log('place = ', place);
});
Here is my JSON (picture)
I don't need place_id of my place. I need especially place_ids of address_components
If you reverse geocode the result, it will return results (which include a place_id) for each of the address components that contain that location.
autoComplete.addListener('place_changed', function() {
var place = autoComplete.getPlace();
map.setZoom(11);
var marker = new google.maps.Marker({
position: place.geometry.location,
map: map
});
infowindow.setContent(place.formatted_address);
infowindow.open(map, marker);
geocoder.geocode({
latLng: place.geometry.location
},
function(results, status) {
if (status === 'OK') {
console.log("revGeo result=" + JSON.stringify(results));
var htmlStr = "<table border='1'>";
for (var i = 0; i < results.length; i++) {
htmlStr += "<tr><td>" + results[i].formatted_address + "</td><td>" + results[i].place_id + "</td></tr>";
}
htmlStr += "</table>";
infowindow.setContent(infowindow.getContent() + "<br>" + htmlStr);
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
});
proof of concept fiddle
code snippet:
var geocoder;
var map;
var infowindow;
function initialize() {
geocoder = new google.maps.Geocoder();
infowindow = new google.maps.InfoWindow();
var map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var object_location = document.getElementById('object_location'),
autoComplete = new google.maps.places.Autocomplete(object_location);
autoComplete.addListener('place_changed', function() {
var place = autoComplete.getPlace();
map.setZoom(11);
var marker = new google.maps.Marker({
position: place.geometry.location,
map: map
});
infowindow.setContent(place.formatted_address);
infowindow.open(map, marker);
geocoder.geocode({
latLng: place.geometry.location
},
function(results, status) {
if (status === 'OK') {
var htmlStr = "<table border='1'>";
for (var i = 0; i < results.length; i++) {
htmlStr += "<tr><td>" + results[i].formatted_address + "</td><td>" + results[i].place_id + "</td></tr>";
}
htmlStr += "</table>";
infowindow.setContent(infowindow.getContent() + "<br>" + htmlStr);
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
});
}
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry,places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<input id="object_location" />
<div id="map_canvas"></div>

I have custom google map multiple markers.when i am using reverse geolocation for multiple marker

I have custom google map multiple markers.when i am using reverse geolocation for multiple marker i am receiving unknown adddress for most of the markers if i use alert btwn the call i get the result for most address
for(var z = 0 ; z < markersArray.length; z++){
alert(z);
geocoder.geocode({'location': markersArray[z].position}, function(results, status) {
if(status == 'OK'){
if(results != null){
address = address + z +" : "+ results[1].formatted_address + "<br>";
alert(z);
}
else
{
address = address + z +" : "+"Unknown Address" + "<br>";
}
}
else{
alert(z);
address = address + z +" : "+"Unknown Address"+ "<br>";
}
});
}
The geocoder is asynchronous. By the time the callback function runs the loop has completed and z is equal to markersArray.length (which isn't a valid entry of the array). This problem can be solved with function closure (example in [this question: Google Maps JS API v3 - Simple Multiple Marker Example for the marker click listener functions.
for (var z = 0; z < markersArray.length; z++) {
geocoder.geocode({
'location': markersArray[z].position
}, (function(z) {
// get function closure on z
return function(results, status) {
if (status == 'OK') {
if (results != null) {
var address = z + " : " + results[0].formatted_address + "<br>";
var marker = new google.maps.Marker({
position: markersArray[z].position,
title: address,
map: map
});
bounds.extend(marker.getPosition());
map.fitBounds(bounds);
google.maps.event.addListener(marker,'click', function(evt) {
infowindow.setContent(address);
infowindow.open(map, this);
})
} else {
var address = z + " : " + "Unknown Address" + "<br>";
}
} else {
var address = z + " : " + "Unknown Address" + "<br>";
}
}
})(z));
}
proof of concept fiddle
code snippet:
var geocoder;
var map;
var markersArray = [{position: {lat: 40.7127837,lng: -74.0059413}},
{position: {lat: 40.735657,lng: -74.1723667}},
{position: {lat:39.2903848,lng: -76.6121893}},
{position: {lat: 39.9525839,lng: -75.1652215}}];
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
geocoder = new google.maps.Geocoder();
var infowindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();
for (var z = 0; z < markersArray.length; z++) {
geocoder.geocode({
'location': markersArray[z].position
}, (function(z) {
// get function closure on z
return function(results, status) {
if (status == 'OK') {
if (results != null) {
var address = z + " : " + results[0].formatted_address + "<br>";
var marker = new google.maps.Marker({
position: markersArray[z].position,
title: address,
map: map
});
bounds.extend(marker.getPosition());
map.fitBounds(bounds);
google.maps.event.addListener(marker, 'click', function(evt) {
infowindow.setContent(address);
infowindow.open(map, this);
})
} else {
var address = z + " : " + "Unknown Address" + "<br>";
}
} else {
var address = z + " : " + "Unknown Address" + "<br>";
}
}
})(z));
}
}
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>
Try to add a short delay between the calls. Had the same problem once, checking the result of each call and try resending them a couple times helped.

InfoWindow & GeoCoder

I have an issue with getting longitude and latitude values geocoded and then display the relevant address in an info window. I have tried multiple ways without success, however I must admit that I am not so familiar with javascript. I am continuously getting back as value : "undefined".
Here is a snippet of my code showing the main components:
var position = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var geocoder = new google.maps.Geocoder();
var address;
if (geocoder) {
geocoder.geocode({ 'latLng': position }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
address = (results[0].formatted_address);
} else {
address = (position.coords.latitude + ', ' + position.coords.longitude);
}
});
}
var info =
('<span class="txt_bld">Location:</span> ' + address + '<br />' +
'<span class="txt_bld">Accuracy:</span> ' + position.coords.accuracy + '<br />' +
'<span class="txt_bld">Time:</span> ' + position.timestamp);
Can anyone tell me how I can translate the lat/lng in position to an address in order to show them in my infowindow?
EDIT
Updated Code:
var position = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var geocoder = new google.maps.Geocoder();
var infowindow = new google.maps.InfoWindow();
var address;
if (geocoder) {
geocoder.geocode({ 'latLng': position }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
address == (results[0].formatted_address);
} else {
address == (position.coords.latitude + ', ' + position.coords.longitude);
}
var info =
('<span class="txt_bld">Location:</span> ' + address + '<br />' +
'<span class="txt_bld">Accuracy:</span> ' + position.coords.accuracy + '<br />' +
'<span class="txt_bld">Time:</span> ' + position.timestamp);
if(!infowindow){
infowindow = new google.maps.InfoWindow({
content: info
});
}else{
infowindow.setContent(info);
}
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
setTimeout(function () {
infowindow.close();
}, 5000);
});
});
}
if(!marker){
marker = new google.maps.Marker({
position: position,
map: this.map,
icon: markericon,
draggable:false
});
}else{
marker.setPosition(point);
}
The geocoder is asynchronous. You need to use the data it returns in the callback function. Something like this (not tested):
var position = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var geocoder = new google.maps.Geocoder();
var infowindow = new google.maps.InfoWindow();
var address;
if (geocoder) {
geocoder.geocode({ 'latLng': position }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
address = (results[0].formatted_address);
} else {
address = (position.coords.latitude + ', ' + position.coords.longitude);
}
var info =
('<span class="txt_bld">Location:</span> ' + address
+ '<br />' +
'<span class="txt_bld">Accuracy:</span> ' + position.coords.accuracy
+ '<br />' +
'<span class="txt_bld">Time:</span> ' + position.timestamp);
infowindow.setContent(info);
infowindow.setPosition(position);
infowindow.open(map);
});
}
Working example
We are using geocoder to get Lat long by address, as we don't have Lat long so we need to find Lat long via geocoder. In case if we have Lat long coordinates then we can use direct
var position = new google.maps.LatLng(markers[i][1], markers[i][2]);
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: markers[i][0]
});

Google Maps API V3 Search KML File

I am wanting to search a KML file to see if a particular address falls within an overlay. Presently, I have the address converting to a geocode. However, I'm not sure what code is needed to add this functionality.
Here's the present code:
function initialize() {
var infowindow = new google.maps.InfoWindow({
content: '',
suppressMapPan:true
});
var myLatlng = new google.maps.LatLng(35.910200,-84.085100);
var myOptions = {
zoom: 12,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(
document.getElementById("map_canvas"), myOptions);
var d = new Date();
var n = d.getMilliseconds();
var nyLayer = new google.maps.KmlLayer(
'http://www.cspc.net/neighborhoods/groups.kml?rand=' + n,
{ suppressInfoWindows: true, map: map});
google.maps.event.addListener(nyLayer, 'click', function(kmlEvent) {
var url = kmlEvent.featureData.snippet;
var groupName = kmlEvent.featureData.name;
var insideContent = "<div style='width:250px;'><h2>" + groupName +
"</h1><p>We have a neighborhood contact in your area! </p>" +
"<p><a href='" + url + "' target='_blank'>Get connected!</a>" +
" They look forward to hearing from you.</p><p>If you have " +
"any additional questions, please contact our " +
"<a href='http://www.cspc.net/communitylife' target='_blank'>" +
"Community Life</a> staff for more information. Betsy Palk, " +
"the Administrative Assistant, may be reached at:<br/><br/>" +
"<b>Email:</b> <a href='mailto:betsypalk#cspc.net'>" +
"betsypalk#cspc.net</a><br/><b>Phone:</b> 865-291-5268<p></div>";
var clickPos = kmlEvent.latLng;
var posX = new google.maps.LatLng(clickPos.lat(), clickPos.lng());
infowindow.close();
infowindow.setPosition(posX);
infowindow.setContent(insideContent);
infowindow.open(map);
});
eventMapClick = google.maps.event.addListener(map, 'click',
function(event) {
var marker = new google.maps.Marker({ position: event.latLng });
var outsideContent = "<div style='width:250px;'><h2>Oops!</h1>" +
"<p> It seems we don't have a neighborhood contact in your " +
"area.</p><p>Please contact our <a " +
"href='http://www.cspc.net/communitylife' target= '_blank'>" +
"Community Life</a> staff for more information. " +
"Betsy Palk, the Administrative Assistant, may be reached at:" +
"<br/><br/><b>Email: </b> <a href='mailto:betsypalk#cspc.net'>" +
"betsypalk#cspc.net</a><br/><b>Phone:</b> 865-291-5268<p></div>";
infowindow.setContent(outsideContent);
infowindow.open(map, marker);
});
}
var geocoder = new google.maps.Geocoder();
function searchAddress(address) {
geocoder.geocode(
{'address': address},
function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var loc = results[0].geometry.location;
// use loc.lat(), loc.lng()
window.alert(loc);
}
else {
window.alert("Not found: " + status);
}
}
);
};
If I understand your question, I believe you want the formula to determine if a point (google.maps.LatLng) falls within one of your KML Placemark definitions (that you give names such as: Neighborhood Group 1). Within each Placemark, you define a Polygon and within each Polygon, you define a set of coordinates, which represent the vertices of the Polygon.
Using the coordinates within the Polygon and the LatLng you retrieve via geocoding, you could start with these formulas and select that one that is the best fit for you:
Fast Winding Number Inclusion of a Point in a Polygon
Point-In-Polygon Algorithm
A very similar question has also been asked here on SO: Determine the lat lngs of markers within a polygon.

Categories