Changing and saving content inside info window after close - javascript

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);

Related

google map map.fitBounds() is not a function

I have error when I load my page: https://www.cupsubito.it/dove-siamo
I don't kwon because about this error. Thank you very much for helping.
Thanks for help me!
The code JS is:
let _locations = [];
var elenco;
google.maps.visualRefresh = true;
var slider, infowindow = null;
var bounds = new google.maps.LatLngBounds();
var current = 0;
var map = 0;
var icons = {
//'default': '/assets/img/marker.png'
};
function showMap() {
infowindow.close();
if (!map.slide) {
return;
}
var next, marker;
if (_locations.length == 0) {
return
} else if (_locations.length == 1) {
next = 0;
}
if (_locations.length > 1) {
do {
next = Math.floor(Math.random() * _locations.length);
} while (next == current)
}
current = next;
marker = _locations[next];
setInfo(marker);
//infowindow.open(map, marker);
}
function initialize() {
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
zoom: 7,
center: new google.maps.LatLng(42.4053848, 12.4276547),
scrollwheel: false,
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
map.slide = true;
//setMarkers(map, _locations);
infowindow = new google.maps.InfoWindow({
content: "loading..."
});
google.maps.event.addListener(infowindow, 'closeclick', function () {
infowindow.close();
});
slider = window.setTimeout(showMap, 3000);
}
function setInfo(marker) {
var content =
'<div class="profile-widget" style="width: 100%; display: inline-block;">' +
'<div class="doc-img">' +
'<a href="' + marker.profile_link + '" tabindex="0" target="_blank">' +
'<img class="img-fluid" alt="' + marker.doc_name + '" src="' + marker.image + '">' +
'</a>' +
'</div>' +
'<div class="pro-content">' +
'<h4 class="text-center">' +
'' + marker.doc_name + '' +
'</h4>' +
'<ul class="available-info pt-5">' +
'<li><i class="fas fa-map-marker-alt"></i> ' + marker.address + ' </li>' +
'</ul>' +
'</div>' +
'</div>';
infowindow.setContent(content);
}
function setMarkers(map, markers) {
for (var i = 0; i < markers.length; i++) {
var item = markers[i];
var latlng = new google.maps.LatLng(item.lat, item.lng);
var marker = new google.maps.Marker({
position: latlng,
map: map,
doc_name: item.doc_name,
address: item.address,
speciality: item.speciality,
profile_link: item.profile_link,
animation: google.maps.Animation.DROP,
icon: icons[item.icons],
image: item.image
});
bounds.extend(marker.position);
markers[i] = marker;
google.maps.event.addListener(marker, "click", function () {
setInfo(this);
infowindow.open(map, this);
window.clearTimeout(slider);
});
}
map.fitBounds(bounds);
google.maps.event.addListener(map, 'zoom_changed', function () {
if (map.zoom > 16) map.slide = false;
});
// Add a marker clusterer to manage the markers.
new markerClusterer.MarkerClusterer({ markers, map });
}
google.maps.event.addDomListener(window, 'load', initialize);
$(document).ready(function () {
$.ajax({
url: "?handler=ElencoStrutture",
type: "POST",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: elenco,
contentType: "application/json; charset=utf-8",
success: function (data) {
//console.error(data.ElencoStrutture);
_locations = data.ElencoStrutture;
setMarkers(map, _locations);
slider = window.setTimeout(showMap, 3000);
//alert("done ELENCO STRUTTURE");
}
});
});
Sometimes it works and sometimes it doesn't, I don't understand why it doesn't always work.
The problem is that it usually works the first time, so I don't understand where I'm wrong on the code side.
The map should display all pointers correctly and instead it sometimes shows me a blank map with this error.
I added part of code where I load setMarkers(map, _locations) for to have more informations.
thank you very much for answers.
I hope I have added useful information to my problem, I don't understand why it sometimes works and sometimes it doesn't.

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>

How location details on pin click outside of Google Map

I have a google map several details about a location. What i want to do is when a user clicks on a location pin, i want to show the details below the map where it says City Details.
Current it shows the infobox on the map.
JS
angular.module('mapsApp', [])
.controller('MapCtrl', function ($scope) {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(40.0000, -98.0000),
mapTypeId: google.maps.MapTypeId.TERRAIN
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
var infoWindow = new google.maps.InfoWindow();
var createMarker = function (info){
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat, info.long),
title: info.city
});
marker.content = '<div class="infoWindowContent">' + info.desc + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
});
$scope.markers.push(marker);
}
for (i = 0; i < cities.length; i++){
createMarker(cities[i]);
}
$scope.openInfoWindow = function(e, selectedMarker){
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
});
Fiddle
http://jsfiddle.net/livewirerules/n4gyywdc/3/
Any help will be appreciated
Hey I have created the new jsfiddle here
In that code I have placed an input field below the city details div that will show you the details of the marker, just for the reference I have placed the title only.
Here it the html:
<div ng-app="mapsApp" ng-controller="MapCtrl">
<div id="map"></div>
<h2>
City Details
</h2>
<input id="detail">
</div>
And here is the javascript code:
//Data
var cities = [
{
city : 'Toronto',
desc : 'This is the best city in the world!',
lat : 43.7000,
long : -79.4000
},
{
city : 'New York',
desc : 'This city is aiiiiite!',
lat : 40.6700,
long : -73.9400
},
{
city : 'Chicago',
desc : 'This is the second best city in the world!',
lat : 41.8819,
long : -87.6278
},
{
city : 'Los Angeles',
desc : 'This city is live!',
lat : 34.0500,
long : -118.2500
},
{
city : 'Las Vegas',
desc : 'Sin City...\'nuff said!',
lat : 36.0800,
long : -115.1522
}
];
//Angular App Module and Controller
angular.module('mapsApp', [])
.controller('MapCtrl', function ($scope) {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(40.0000, -98.0000),
mapTypeId: google.maps.MapTypeId.TERRAIN
}
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
$scope.markers = [];
var infoWindow = new google.maps.InfoWindow();
var createMarker = function (info){
var marker = new google.maps.Marker({
map: $scope.map,
position: new google.maps.LatLng(info.lat, info.long),
title: info.city
});
marker.content = '<div class="infoWindowContent">' + info.desc + '</div>';
google.maps.event.addListener(marker, 'click', function(){
infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
infoWindow.open($scope.map, marker);
console.log(marker.title);
/*
*1. You can use the jquery selector as well, but for this example I used the pure javascript.
*2. You can access other values of marker here based on the requirement.
*/
document.getElementById("detail").value = marker.title;
});
$scope.markers.push(marker);
}
for (i = 0; i < cities.length; i++){
createMarker(cities[i]);
}
$scope.openInfoWindow = function(e, selectedMarker){
e.preventDefault();
google.maps.event.trigger(selectedMarker, 'click');
}
});
Also you can get the data from the object that is coming in the marker, but have to change little bit of code. Hope this will help you.
For Angular version :
add this to html :
<div id="divId"></div>
//this line to on click function of marker.
var myEl = angular.element( document.querySelector( '#divId' ) );
myEl.append('<p>' + marker.title + '</p>' + marker.content');

Google Maps is grey after being called a second time

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
});
}

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]
});

Categories