I'm making a mobile web app.
Part of the app drops several markers, which can be clicked to open info windows. It irritates me that these do not go away if you continue using the map without acknowledging them, as in the iOS maps app.
Is there a way to set it so that if the user clicks the underlying map, all open info windows are closed?
Try this:
google.maps.event.addListener(map, "click", function(event) {
infowindow.close();
});
It is quite simple an should work as well.
add listener to map's click event and close infoboxes in its handler
google.maps.event.addListener(map, "click", function(event) {
for (var i = 0; i < ibArray.length; i++ ) { //I assume you have your infoboxes in some array
ibArray[i].close();
}
});
I do that on typical websites, but don't see any reason it wouldn't work on mobile
google.maps.event.addListener(marker, 'click', function() {
if(!marker.open){
infoWindow.open(map,marker);
marker.open = true;
}
else{
infoWindow.close();
marker.open = false;
}
google.maps.event.addListener(map, 'click', function() {
infoWindow.close();
marker.open = false;
});
});
Works perfectly
I noticed some problems with the other answers.
Answer of Marcus Rommel and slawekwin:
When a marker is clicked, the map click event is fired afterwards. So when marker click opens the window, the propagation of the click event to map will close the window again immediately.
Answer of user1724001:
Creating a listener everytime a marker is clicked is also not a good idea. This pollutes the memory.
Therefore i just want to add some additional information to the first answers, to stop event propagation to the map. The Windows will then only be closed, if no marker is clicked.
marker.addListener("click", function(event) {
// open your window here
event.stopPropagation(); // this prevents propagation of marker click to map click
});
map.addListener("click", function() {
// close your window
});
I have better solution for all senario.
Try this: JSFiddle
const infoWindow = new google.maps.InfoWindow();
function init() {
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 6,
center: new google.maps.LatLng(39.9646, 30.8259),
mapTypeId: google.maps.MapTypeId.TERRAIN
});
map.addListener('click', () => {
if (infoWindow) {
infoWindow.close();
}
});
const istanbulMark = new google.maps.Marker({
position: new google.maps.LatLng(41.0876, 28.9288),
map: map,
label: 'I'
});
istanbulMark.addListener('click', () => {
infoWindow.setContent(`
<h1>Hi mate</h1>
<hr>
<p>Welcome to İstanbul!</p>
`)
infoWindow.open(map, istanbulMark);
});
const ankaraMark = new google.maps.Marker({
position: new google.maps.LatLng(39.9162, 32.8437),
map: map,
label: 'A'
});
ankaraMark.addListener('click', () => {
infoWindow.setContent(`
<h1>Hi mate</h1>
<hr>
<p>Welcome to Ankara!</p>
`)
infoWindow.open(map, ankaraMark);
});
}
google.maps.event.addDomListener(window, 'load', init);
html, body, #map {
height: 100%;
margin: 0px;
padding: 0px
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true">
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
Related
I'm trying to make POI's InfoWindow close when click a link.
I overrided the setContent of InfoWindow like this:
//override the built-in setContent-method
google.maps.InfoWindow.prototype.setContent = function (content) {
content = content.innerHTML + '<br/> Save place';
//run the original setContent-method
fx.apply(this, arguments);
};
Note: I didn't create any InfoWindow object to reference to use close() method.
In your override function capture a global reference to the infowindow so you can reference it to close it.
Your override of the infowindow doesn't work. I took a working version from this question: How to get a click event when a user clicks a (business) place on the map
proof of concept fiddle
code snippet:
var geocoder;
var map;
var infowindow;
//keep a reference to the original setPosition-function
var fx = google.maps.InfoWindow.prototype.setPosition;
// from https://stackoverflow.com/questions/24234106/how-to-get-a-click-event-when-a-user-clicks-a-business-place-on-the-map/24234818#24234818
//override the built-in setPosition-method
google.maps.InfoWindow.prototype.setPosition = function() {
//logAsInternal isn't documented, but as it seems
//it's only defined for InfoWindows opened on POI's
if (this.logAsInternal) {
// save reference in global infowindow variable.
infowindow = this;
google.maps.event.addListenerOnce(this, 'map_changed', function() {
var map = this.getMap();
//the infoWindow will be opened, usually after a click on a POI
if (map) {
//trigger the click
google.maps.event.trigger(map, 'click', {
latLng: this.getPosition()
});
}
});
}
//call the original setPosition-method
fx.apply(this, arguments);
};
function initialize() {
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
});
google.maps.event.addDomListener(document.getElementById('btn'), 'click', function(e) {
// close the last opened POI infowindow
infowindow.close();
});
}
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>
<input id="btn" type="button" value="close IW" />
<div id="map_canvas"></div>
Hello and thanks in advance for your help!
The following test code:
1) Uses PHP to get lat/lng data from a mySQL database, and then uses that data to form a JavaScript array with initialization data. WORKS FINE.
2) Uses the initialized JavaScript array to create markers. WORKS FINE.
3) Allows (left) clicks to create new markers (more code will be added later to add those new marker locations back into the database). WORKS FINE.
4) Allows RIGHT-clicks to delete a marker using marker.setMap(null) - either the preloaded markers from the database, or newly created user markers. USER MARKERS DELETE PROPERLY, PRE-LOADED MARKERS DO NOT DELETE PROPERLY, AS DESCRIBED BELOW.
5) Both the preloaded markers, and the newly created ones are stored in the array "markers" using the statement markers.push(marker). SEEMS TO BE OK.
Everything works, except the right-click deletion of the PRELOADED markers. (The right-click deletion of user created markers works fine.) Any right-click on any preloaded marker, only deletes the LAST preloaded marker. It's as if the delete event listener were outside and after the loop that sets the preloaded markers, but it is inside that loop.
I think the faulty section is the one with the leading comment "show prev clicks in database". Any ideas would be greatly appreciated! I'm very new at Google Maps API v3, so it's probably something obvious that I'm just missing or misunderstanding. Thanks again!
<!DOCTYPE html>
<html>
<head>
<title>Marker Test</title>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas, #map_canvas {
height: 100%;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
<?
// Generate JavaScript array initialization from database
$username="REDACTED";
$password="REDACTED";
$database="REDACTED";
$con=mysql_connect(localhost,$username,$password);
#mysql_select_db($database,$con) or die( "Unable to select database");
$query="SELECT * FROM pool where (record_id >= 1765) AND (record_id <= 1769)";
/*
$query="SELECT * FROM pool where (record_id <= '$marker_end') AND (record_id >= '$marker_start')";
$query="SELECT * FROM pool where session = '$session'";
*/
$result=mysql_query($query,$con);
$length=mysql_num_rows($result);
$length_count=1;
if ($result) {
echo "var PreviousClicks = [\n";
while($row = mysql_fetch_array($result)) {
$_lat=$row['google_lat'];
$_lng=$row['google_lng'];
$_record_id=$row['record_id'];
echo "{\n";
echo "lat: $_lat,\n";
echo "lng: $_lng,\n";
echo "title: \"$_record_id\"\n";
echo "}";
if($length_count<$length) {echo ",\n";} else {echo "\n";}
$length_count++;
} // end while
echo "];";
} // end if
mysql_close();
?>
</script>
<script type="text/javascript">
var map;
var markers = [];
function addMarker(location) {
var marker = new google.maps.Marker({
position: location,
title: "A",
map: map
});
google.maps.event.addListener(marker, 'rightclick', function(event) {
marker.setMap(null);
});
markers.push(marker);
} //end addMarker function
function initialize() {
// currently manual center initialization
var startLoc = new google.maps.LatLng(33.037380,-117.090431);
var mapOptions = {
zoom: 16,
center: startLoc,
mapTypeId: google.maps.MapTypeId.TRAFFIC
};
map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
google.maps.event.addListener(map, 'click', function(event) {
addMarker(event.latLng);
});
// show prev clicks in database ------------------------------------------------------------------
for (i = 0; i < PreviousClicks.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(PreviousClicks[i].lat, PreviousClicks[i].lng),
title: PreviousClicks[i].title,
map: map
});
google.maps.event.addListener(marker, 'rightclick', function(event) {
marker.setMap(null);
});
markers.push(marker);
} // end for
// end "show prev clicks in database" section ----------------------------------------------------
} // end function initialize
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas">
</div>
</body>
</html>
Inside a marker's event handler, this refers back to the marker. Therefore :
this.setMap(null);
will remove the marker from the map.
But more can be done with this code. In particular :
Avoid repeating code by using addMarker() to add both new and previous markers.
When markers are removed, also remove them from the markers array.
Both can be achieved as follows :
function addMarker(event) {
var marker = new google.maps.Marker({
position: event.latLng,
title: event.title || "A",
map: map
});
google.maps.event.addListener(marker, 'rightclick', function(event) {
this.setMap(null);
//Remove the marker from the markers array.
for(i=0; i<markers.length; i++) {
if(markers[i] == this) {
removed = markers.splice(i, 1);
break;
}
}
});
markers.push(marker);
}
function initialize() {
...
google.maps.event.addListener(map, 'click', addMarker);
...
for (i = 0; i < PreviousClicks.length; i++) {
addMarker({
latLng: new google.maps.LatLng(PreviousClicks[i].lat, PreviousClicks[i].lng);
title: PreviousClicks[i].title
});
}
}
I previously prepare a javascript that shows some marker downloaded in JSON format, from a webservice.
The code is:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>MAP</title>
<link type="text/css" href="css/style.css" rel="stylesheet" media="all" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&v=3.8"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="map_bar.js"></script>
</head>
<body>
<h1>MAPPA</h1>
<div id="map"></div>
</body>
</html>
that calls the map_bar.js:
(function() {
window.onload = function() {
// Creating a new map
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(80.650535,41.886146),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Creating a global infoWindow object that will be reused by all markers
function createPoints(json){
var infoWindow = new google.maps.InfoWindow();
// Looping through the JSON data
for (var i = 0, length = json.locations.length; i < length; i++) {
var data = json.locations[i],
latLng = new google.maps.LatLng(data.lat, data.long);
console.log(data.long);
var iconBase = 'https://maps.google.com/mapfiles/kml/shapes/';
var marker = new google.maps.Marker({
position: latLng,
map: map,
title: data.nombre,
icon: 'beer.png'
});
(function(marker, data) {
// Attaching a click event to the current marker
google.maps.event.addListener(marker, "click", function() {
info = data.nombre+'<br/>'+data.offerta+'<br/>'+data.horario;
infoWindow.setContent(info); //esto escibe las info
infoWindow.open(map, marker);
});
})
(marker, data);
}
}
// Get the JSON data from PHP script
var json ;
$.getJSON("http://mywebservice.php").done(function(data) {
console.log(data);
json = data;
createPoints(json);
});
}
})();
It works, but the problem appears when I trying to integrate that in an existing webpage.
I have some sections and putting the same code in my "map section", the map appears but not markers.
The console.log(data) into the getJSON method not give back the point. It strange because the same code works in a "stand alone" page.
Any idea about that?
Thanks in advance.
jquery getJSON is subject to the same origin policy, a sub-domain is not the same domain as the main domain.
Using a relative reference to a file in the sub-domain fixes the issue.
I have tried to implement the last code at
https://developers.google.com/maps/articles/phpsqlinfo_v3
I want to have a cancel and close button.
So, i modified the code and uploaded it to
http://adsany.com/testclose.htm
(view source)
when i click on the map, a marker appears,
when I click on the marker, infowindow appears.
when I click on the cancel and close button, it closes the window, but a new marker appears.
So, i want to close the infowindow without creating a new marker.
Please suggest.
Thanks.
I hope this link will solve your Problem :-
http://gmaps-samples-v3.googlecode.com/svn/trunk/single-infowindow/single-infowindow.html.
<html>
<head>
<title>Single Info Windows</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
google.maps.event.addDomListener(window, 'load', function() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: new google.maps.LatLng(37.789879, -122.390442),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infoWindow = new google.maps.InfoWindow;
var onMarkerClick = function() {
var marker = this;
var latLng = marker.getPosition();
infoWindow.setContent('<h3>Marker position is:</h3>' +
latLng.lat() + ', ' + latLng.lng());
infoWindow.open(map, marker);
};
google.maps.event.addListener(map, 'click', function() {
infoWindow.close();
});
var marker1 = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(37.789879, -122.390442)
});
var marker2 = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(37.787814,-122.40764)
});
var marker3 = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(37.767568,-122.391665)
});
google.maps.event.addListener(marker1, 'click', onMarkerClick);
google.maps.event.addListener(marker2, 'click', onMarkerClick);
google.maps.event.addListener(marker3, 'click', onMarkerClick);
});
</script>
<style type="text/css">
body {
font-family: sans-serif;
}
#map {
width: 500px;
height: 500px;
}
</style>
</head>
<body>
<h2>Demonstrates how to share a single info window on a map.</h2>
<ol>
<li>Click a marker to open a single info window containing the marker's position.</li>
<li>Close the opened info window by clicking anywhere on the map.</li>
</ol>
<div id="map"></div>
</body>
</html>
I want to enable drawing on Google Maps like (see this example)
When user finish with drawings he will click on save button to save his drawings in Database or KML file, anything :) .. I do not know how to the save part? Could anyone help me
Here, http://jsfiddle.net/X66L4/1/ try drawing some circles, click on SAVE, then edit the circles by switching to the hand cursor and SAVE again to see the changes.
I show an example to save circles' data, the main idea is to keep a global array for each drawing type (line, polygon, marker, circle), and use a listener on the drawing manager to detect each type being drawn (complete).
var circles = [];
google.maps.event.addDomListener(drawingManager, 'circlecomplete',
function(circle) {
circles.push(circle);
});
The reason to save the entire reference to the drawn object is to continue tracking changes. So you will need an array and listener for each type of drawing.
Then, when you want to save the data (you may wish to do so at every edit), iterate through the arrays and extract the minimum information to rebuild it (center, radius, path, latLng, and so on.)
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html, body, #map_canvas { margin: 0; padding: 0; height: 100% }
</style>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=drawing"></script>
<script type="text/javascript">
var myOptions = {
center: new google.maps.LatLng(-25,177.5),
zoom: 3,
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var map;
function initialize() {
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.CIRCLE,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.CIRCLE]
},
circleOptions: {
editable: true
}
});
drawingManager.setMap(map);
var circles = [];
google.maps.event.addDomListener(drawingManager, 'circlecomplete', function(circle) {
circles.push(circle);
});
google.maps.event.addDomListener(savebutton, 'click', function() {
document.getElementById("savedata").value = "";
for (var i = 0; i < circles.length; i++) {
var circleCenter = circles[i].getCenter();
var circleRadius = circles[i].getRadius();
document.getElementById("savedata").value += "circle((";
document.getElementById("savedata").value +=
circleCenter.lat().toFixed(3) + "," + circleCenter.lng().toFixed(3);
document.getElementById("savedata").value += "), ";
document.getElementById("savedata").value += circleRadius.toFixed(3) + ")\n";
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<button id="savebutton">SAVE</button>
<textarea id="savedata" rows="8" cols="40"></textarea>
<div id="map_canvas"></div>
</body>
</html>
In my experience, it's easier to use map's dataLayer then the drawing manager.
Try out this fiddle.
FiddleLink
Showing the controls:
map.data.setControls(['Polygon']);
map.data.setStyle({
editable: true,
draggable: true
});
in this function you can see the Create, Read (localStorage) and Remove (not in that order):
function loadPolygons(map) {
var data = JSON.parse(localStorage.getItem('geoData'));
map.data.forEach(function (f) {
map.data.remove(f);
});
console.log(data);
map.data.addGeoJson(data)
}