google maps infowindow positioning with polylines - javascript

I have a map with multiple polylines which I am looking to display infowindow for each line. I have the infowindow working but it is not positioning to the event click as it should be. Instead, each window displays in the same place. Can't seem to track down the root of the issue.
<script type="text/javascript">
var contentString = "";
var infowindow = new google.maps.InfoWindow({
content: contentString,
});
function initialize() {
var myLatlng = new google.maps.LatLng(30.695895, -97.354080);
var mapOptions = {
zoom: 5,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.TERRAIN,
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
downloadUrl("data.xml", function(data) {
var xml = xmlParse(data);
var polylines = xml.documentElement.getElementsByTagName("polyline");
var polylineData = new Array();
for (var i = 0; i < polylines.length; i++) {
polylineData[i] = {id:polylines[i].getAttribute("id"),
name:polylines[i].getAttribute("name"),
olat:polylines[i].getAttribute("olat"),
olng:polylines[i].getAttribute("olng"),
dlat:polylines[i].getAttribute("dlat"),
dlng:polylines[i].getAttribute("dlng")}
}
for (var j = 0; j < polylineData.length; j++) {
var path = [
new google.maps.LatLng(parseFloat(polylineData[j].olat), parseFloat(polylineData[j].olng)),
new google.maps.LatLng(parseFloat(polylineData[j].dlat), parseFloat(polylineData[j].dlng))
];
var polyline = new google.maps.Polyline({
path: path,
strokeWeight: 2
});
google.maps.event.addListener(polyline, 'click', (function(event,index){
return function(){
infowindow.content = '<div class="infobox" style="width:280px;"><span class="name">' + polylineData[index].name + '</span></div>';
var point = event.latLng;
infowindow.setPosition(point);
infowindow.open(map);
};
})(event,j));
polyline.setMap(map);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
XML data looks like this:
<polylines>
<polyline id="176" name="Line Name" olat="53.545204" olng="-113.369492" dlat="53.545204" dlng="-113.369492"/>
</polylines>
I have read some similar posts but none of the answers have worked in this case thus far. Thanks!

event must be the argument passed to the returned function:
google.maps.event.addListener(polyline, 'click', (function(index){
//_________________________________________________________^:the index of the item
return function(event){
//________________^:the event
infowindow.content = '<div class="infobox" style="width:280px;"><span class="name">' + polylineData[index].name + '</span></div>';
var point = event.latLng;
infowindow.setPosition(point);
infowindow.open(map);
};
})(j));

Related

Google Maps: Select previous Marker on Polyline

I'm doing an application with google maps API that have a JSON with the marker's coordinates. Then I draw polylines between the markers. I also implemented a function with a onclick event that creates a new marker inside the polyline. This marker has to show information of the previous marker in the polyline (the one taked of the JSON, not a clicked one). But I don't know how to take the previous vertex(marker) of a selected polyline.
Code:
(function() {
window.onload = function() {
var options = {
zoom: 3,
center: new google.maps.LatLng(37.09, -95.71),
mapTypeId: google.maps.MapTypeId.HYBRID,
noClear: true,
panControl: true,
scaleControl: false,
streetViewControl:false,
overviewMapControl:false,
rotateControl:false,
mapTypeControl: true,
zoomControl: false,
};
var map = new google.maps.Map(document.getElementById('map'), options);
// JSON
$.getJSON("loc.js", function(json) {
console.log(json);
});
//Marker type
var markers = [];
var arr = [];
var pinColor = "FE7569";
var pinImage = new google.maps.MarkerImage("http://labs.google.com/ridefinder/images/mm_20_red.png" + pinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));
// JSON loop
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i],
latLng = new google.maps.LatLng(data.lat, data.lng);
arr.push(latLng);
// Create markers
var marker = new google.maps.Marker({
position: latLng,
map: map,
icon: pinImage,
});
infoBox(map, marker, data);
//Polylines
var flightPath = new google.maps.Polyline({
path: json,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2,
map:map
});
infoPoly(map, flightPath, data);
//Calculate polylines distance
google.maps.LatLng.prototype.kmTo = function(a){
var e = Math, ra = e.PI/180;
var b = this.lat() * ra, c = a.lat() * ra, d = b - c;
var g = this.lng() * ra - a.lng() * ra;
var f = 2 * e.asin(e.sqrt(e.pow(e.sin(d/2), 2) + e.cos(b) * e.cos
(c) * e.pow(e.sin(g/2), 2)));
return f * 6378.137;
}
google.maps.Polyline.prototype.inKm = function(n){
var a = this.getPath(n), len = a.getLength(), dist = 0;
for (var i=0; i < len-1; i++) {
dist += a.getAt(i).kmTo(a.getAt(i+1));
}
return dist;
}
}
function infoBox(map, marker, data) {
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, "click", function(e) {
salta(data.tm);
});
(function(marker, data) {
google.maps.event.addListener(marker, "click", function(e) {
salta(data.tm);
});
})(marker, data);
}
//Create onclick marker on the polyline
function infoPoly(map, flightPath, data){
google.maps.event.addListener(flightPath, 'click', function(event) {
mk = new google.maps.Marker({
map: map,
position: event.latLng,
});
markers.push(mk);
map.setZoom(17);
map.setCenter(mk.getPosition());
});
}
function drawPath() {
var coords = [];
for (var i = 0; i < markers.length; i++) {
coords.push(markers[i].getPosition());
}
flightPath.setPath(coords);
}
// Fit these bounds to the map
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < arr.length; i++) {
bounds.extend(arr[i]);
}
map.fitBounds(bounds);
//dist polylines
distpoly = flightPath.inKm();
distpolyround = Math.round(distpoly);
};
})();
If I click in the blue arrow, I create a marker on that point of the polyline. I that marker it takes the values of the previous one.
You can use the geometry library .poly namespace isLocationOnEdge method to determine which segment of the polyline the clicked point (new marker) is on.
//Create onclick marker on the polyline
function infoPoly(map, flightPath, data) {
google.maps.event.addListener(flightPath, 'click', function(event) {
mk = new google.maps.Marker({
map: map,
position: event.latLng,
});
markers.push(mk);
map.setZoom(17);
map.setCenter(mk.getPosition());
// find line segment. Iterate through the polyline checking each line segment.
// isLocationOnEdge takes a google.maps.Polyline as the second argument, so make one,
// then use it for the test. The default value of 10e-9 for the tolerance didn't work,
// a tolerance of 10e-6 seems to work.
var betweenStr = "result no found";
var betweenStr = "result no found";
for (var i=0; i<flightPath.getPath().getLength()-1; i++) {
var tempPoly = new google.maps.Polyline({
path: [flightPath.getPath().getAt(i), flightPath.getPath().getAt(i+1)]
})
if (google.maps.geometry.poly.isLocationOnEdge(mk.getPosition(), tempPoly, 10e-6)) {
betweenStr = "between "+i+ " and "+(i+1);
}
}
(function(mk, betweenStr) {
google.maps.event.addListener(mk, "click", function(e) {
infowindow.setContent(betweenStr+"<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, mk);
// salta(data.tm);
});
})(mk, betweenStr);
google.maps.event.trigger(mk,'click');
});
proof of concept fiddle
code snippet:
var infowindow = new google.maps.InfoWindow();
(function() {
window.onload = function() {
var options = {
zoom: 3,
center: new google.maps.LatLng(37.09, -95.71),
mapTypeId: google.maps.MapTypeId.HYBRID,
};
var map = new google.maps.Map(document.getElementById('map'), options);
//Marker type
var markers = [];
var arr = [];
var pinColor = "FE7569";
var pinImage = "http://labs.google.com/ridefinder/images/mm_20_red.png";
// JSON loop
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i],
latLng = new google.maps.LatLng(data.lat, data.lng);
arr.push(latLng);
// Create markers
var marker = new google.maps.Marker({
position: latLng,
map: map,
icon: pinImage,
});
infoBox(map, marker, data);
//Polylines
var flightPath = new google.maps.Polyline({
path: json,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2,
map: map
});
infoPoly(map, flightPath, data);
}
function infoBox(map, marker, data) {
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, "click", function(e) {
infowindow.setContent("tm:" + data.tm + "<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, marker);
// salta(data.tm);
});
(function(marker, data) {
google.maps.event.addListener(marker, "click", function(e) {
infowindow.setContent("tm:" + data.tm + "<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, marker);
// salta(data.tm);
});
})(marker, data);
}
//Create onclick marker on the polyline
function infoPoly(map, flightPath, data) {
google.maps.event.addListener(flightPath, 'click', function(event) {
mk = new google.maps.Marker({
map: map,
position: event.latLng,
});
markers.push(mk);
map.setZoom(17);
map.setCenter(mk.getPosition());
// find line segment. Iterate through the polyline checking each line segment.
// isLocationOnEdge takes a google.maps.Polyline as the second argument, so make one,
// then use it for the test. The default value of 10e-9 for the tolerance didn't work,
// a tolerance of 10e-6 seems to work.
var betweenStr = "result no found";
for (var i = 0; i < flightPath.getPath().getLength() - 1; i++) {
var tempPoly = new google.maps.Polyline({
path: [flightPath.getPath().getAt(i), flightPath.getPath().getAt(i + 1)]
})
if (google.maps.geometry.poly.isLocationOnEdge(mk.getPosition(), tempPoly, 10e-6)) {
betweenStr = "between " + i + " and " + (i + 1);
}
}
(function(mk, betweenStr) {
google.maps.event.addListener(mk, "click", function(e) {
infowindow.setContent(betweenStr + "<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, mk);
// salta(data.tm);
});
})(mk, betweenStr);
google.maps.event.trigger(mk, 'click');
});
}
function drawPath() {
var coords = [];
for (var i = 0; i < markers.length; i++) {
coords.push(markers[i].getPosition());
}
flightPath.setPath(coords);
}
// Fit these bounds to the map
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < arr.length; i++) {
bounds.extend(arr[i]);
}
map.fitBounds(bounds);
//dist polylines
distpoly = flightPath.inKm();
distpolyround = Math.round(distpoly);
};
})();
var json = [{
lat: 38.931808,
lng: -74.906606,
tm: 0
}, {
lat: 38.932442,
lng: -74.905147,
tm: 1
}, {
lat: 38.93311,
lng: -74.903473,
tm: 2
}, {
lat: 38.933777,
lng: -74.901671,
tm: 3
}, {
lat: 38.930739,
lng: -74.912528,
tm: 1000
}];
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map"></div>
INITIALIZING
When you are creating those markers in the for loop, add them to a map [Data structure] that you define (empty) before the loop. In the map markers will be stored. Their keys - concatenated lat/lng.
var initial_markers = {}; //before for loop
initial_markers[data.lat+"-"+data.lng] = marker; //after each marker initialization
Count them, so you know how many there are initial_marker_count, because you cannot get length of size of a map[data structure]
DETECTION
When you have clicked on a polyline, I don't think you can get exactly the part of polyline that is clicked, so you need to get it yourself. The steps are:
Get the coordinate of click event
Loop through the markers
Take their coordinates
Check if the clicked point on the map is on the line between those two points
If is, take the first of those two points
DETECTION PSEUDOCODE
var prev_marker;
for (var i=initial_markers; i<initial_marker_count-2; i++) {
if( isPointOnLine(initial_markers[i], initial_markers[i+1], clicked_point) {
prev_marker = initial_markers[i];
break;
}
}
The only reason I am saying that this is pseudocode, is because I don't know hor to find if point is on the line between two points in Google maps. And you should write that isPointOnLine() functions. Apart from that - the idea is given. Hope You appreciate it.

google map addlistener onclick get xml data

hi I have problem with addlistener in google map
I cant get html value from xml. always return [object Element]
document.getElementById("infobox").innerHTML = html;
and infowindow.setContent(html); work perfectly
I know I do this before last 1 month ago i dont know was v3 version or this. but i do this before!
or if you know other way for getting out data please help!
from this code in addlistener
var side_bar_html = " ";
var html = " ";
var gmarkers = [];
var map = null;
/
function createMarker(latlng, name, html) {
var contentString = html;
var marker = new google.maps.Marker({
position: latlng,
map: map,
zIndex: Math.round(latlng.lat()*-100000)<<5,icon : 'mark.png'
});
google.maps.event.addListener(marker, 'click', function() {
document.getElementById("infobox").innerHTML = html;
infowindow.setContent(html);
infowindow.open(map,marker);
});
gmarkers.push(marker);
// add a line to the side_bar html
side_bar_html += '<a href="javascript:myclick(' + (gmarkers.length-1) + ')">' + name + '<\/a><br>';
}
function myclick(i) {
google.maps.event.trigger(gmarkers[i], "click");
}
function initialize() {
var myOptions = {
zoom: 11,
center: new google.maps.LatLng(38.06106741381199,46.359741),
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
// Read the data from example.xml
downloadUrl("example.xml", function(doc) {
var xmlDoc = xmlParse(doc);
var markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// obtain the attribues of each marker
var lat = parseFloat(markers[i].getAttribute("lat"));
var lng = parseFloat(markers[i].getAttribute("lng"));
var point = new google.maps.LatLng(lat,lng);
var html = markers[i].getElementsByTagName("infowindow")[0] ;
var label = markers[i].getAttribute("label");
// create the marker
var marker = createMarker(point,label,html);
}
document.getElementById("side_bar").innerHTML = side_bar_html;
// put the assembled side_bar_html contents into the side_bar div
});
}
var infowindow = new google.maps.
InfoWindow(
{
size: new google.maps.Size(150,50)
});
xml code:
<?xml version="1.0"?>
<maincontent>
<markers>
<marker lat="37.95989919257204" lng="46.38427734375" label="way 1">
<infowindow>station 1</infowindow>
</marker>
</markers>
</maincontent>
I found what is problem just change tag to attribute!
var html = markers[i].getAttribute("html");
But I dont know why!

Google Maps Javascript not getting Coordinates of user

This javascript wont get the coordinates of the user
(this is a html, js and css application only)
(the area with Bold and Italic text, is the one supposed to get the coordinates from the client)
I have tried different soloutions, and they wont work, + it doesnt show the ones if the user is within 25km
center: new google.maps.LatLng(val(coords.latitude),val(coords.longitude)),
<script type="text/javascript">
var side_bar_html = "";
var gmarkers = [];
var map = null;
var markerclusterer = null;
function createMarker(latlng, name, html) {
var contentString = html;
var marker = new google.maps.Marker({
position: latlng,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
gmarkers.push(marker);
side_bar_html += '<a href="javascript:myclick(' + (gmarkers.length-1) + ')">' + name + '<\/a><br>';
}
function myclick(i) {
google.maps.event.trigger(gmarkers[i], "click");
}
function initialize() {
var myOptions = {
zoom: 8,
center: new google.maps.LatLng(val(coords.latitude),val(coords.longitude)),
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
google.maps.event.addListener(map, 'click', function() {
infowindow.close();
});
google.maps.event.addListener(map, 'click', find_closest_marker);
downloadUrl("markers.xml", function(doc) {
var xmlDoc = xmlParse(doc);
var markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var lat = parseFloat(markers[i].getAttribute("lat"));
var lng = parseFloat(markers[i].getAttribute("lng"));
var point = new google.maps.LatLng(lat,lng);
var id = markers[i].getAttribute("id");
var sted = markers[i].getAttribute("sted");
var html="<b>"+sted+"</b><br>"+id;
var marker = createMarker(point,sted+" "+id,html);
}
markerCluster = new MarkerClusterer(map, gmarkers);
document.getElementById("side_bar").innerHTML = side_bar_html;
});
}
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
function find_closest_marker( event ) {
var closestMarker = -1;
var closestDistance = Number.MAX_VALUE;
for( i=0;i<gmarkers.length; i++ ) {
var distance = google.maps.geometry.spherical.computeDistanceBetween(gmarkers[i].getPosition(),event.latLng);
if ( distance < closestDistance ) {
closestMarker = i;
closestDistance = distance;
}
}
map.setCenter(gmarkers[closestMarker].getPosition());
if (map.getZoom() < 16) map.setZoom(16);
google.maps.event.trigger(gmarkers[closestMarker], 'click');
}
</script>
You can user a simple JS function for that.
<script>
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showLatLng);
} else {
alert("Geolocation is not supported by this browser.");
}
}
function showLatLng(location) {
alert("Latitude: " + location.coords.latitude +
"Longitude: " + location.coords.longitude);
}
</script>
Hope it helps

How to close an infowindow

I have already have an array of markers, I want to close an opened infowindow when I click another marker.
I know that with the v3 API, I can close a infowindow with the InfoWindow.close() method.But where to add the code?I have tried a lot but failed.
I have another question ,why need I click the link in "side_bar_div" tiwce to call the method myclick(i)?
<script type="text/javascript">
var markers=[];
var side_bar_html='<table border=0 cellpadding=0><tr>';
var tdrow = 1;
var i = 0;
function creatmarker(lat,long,map,html,index){
var mylatlng = new google.maps.LatLng(lat,long);
var marker = new google.maps.Marker({
position: mylatlng,
map: map,
zIndex: index
});
var infowindow = new google.maps.InfoWindow({
content: html
});
markers.push(marker);
side_bar_html +='<td width=330 valign=top align=left><a id="side_bar_'+i+'" href="javascript:myclick('+ (markers.length-1) +');">'+html+'</a></td>';
tdrow++;
i++;
if (tdrow > 2){side_bar_html += '</tr><tr>'; tdrow =1; }
google.maps.event.addListener(marker,'click',function(){
infowindow.open(map,marker);
});
function myclick(i){
var id="side_bar_"+i;
google.maps.event.addDomListener(document.getElementById(id), "click", function(){ google.maps.event.trigger(markers[i], "click");
});
}
function initialize(){
var myOptions = {
zoom: 11,
center: new google.maps.LatLng(-33.9, 151.2),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("mymap"),myOptions);
var lat = "-33.890542";
var lng = "151.274856";
var html = 'Bondi Beach';
creatmarker(lat,lng,map,html,5);
var lat = "-33.923036";
var lng = "151.259052";
var html = 'Coogee Beach';
creatmarker(lat,lng,map,html,4);
var lat = "-34.028249";
var lng = "151.157507";
var html = 'Cronulla Beach';
creatmarker(lat,lng,map,html,3);
var lat = "-33.80010128657071";
var lng = "151.28747820854187";
var html = 'Manly Beach';
creatmarker(lat,lng,map,html,2);
var lat = "-33.950198";
var lng = "151.259302";
var html = 'Maroubra Beach';
creatmarker(lat,lng,map,html,1);
side_bar_html +='</tr></table>';
document.getElementById("side_bar_div").innerHTML = side_bar_html;
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
Try the following code snippet:
var infoWindows = [];
google.maps.event.addListener(marker,'click',function(){
closeInfowindow();
var infowindow = new google.maps.InfoWindow({
content: html
});
infowindow.open(map,marker);
infoWindows[0] = infowindow;
});
function closeInfowindow(){
if(infoWindows.length > 0){
infoWindows[0].set("marker",null);
infoWindows[0].close();
infoWindows.length = 0;
}
}
Hope this helps you :-)
The correct way to do this is to store it in a local variable and then add an eventlistener like this:
function addeventlistenerinfo(marker, infowindow, i){
google.maps.event.addListener(marker, 'click', function() {
if (currentinfowindow)
currentinfowindow.close();
infowindow.open(map,marker);
currentinfowindow = infowindow;
});
markersarray[i] = marker;
}
currentinfowindow is a global variable that will only hold the open infowindow if one exists.
No need to use an array or an extra method :)

Google maps - Custom JS to output infowindows and markers issues

Trying to simplify my google maps custom code to put markers and an info bubble. However have run into a few issues which I can't seem to debug the code is below, it's currently outputting nothing. The code defines lat/long/title and content and then trys to ouput them as markers on a map.
<script type="text/javascript">
function initialize() {
var myLatlng = new google.maps.LatLng(20,0);
var myOptions = {
zoom: 2,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.TERRAIN
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var countries = [
{title:'Afghanistan', lat:34.28, lon:69.11, content:"<h2>Afghanistan</h2><p>16 Alumni</p>"},
{title:'Albania', lat:41.18, lon:19.49, content:"<h2>Albania</h2><p>7 Alumni</p>"},
{title:'Angola', lat:-8.5, lon:13.15, content:"<h2>Angola</h2><p>9 Alumni</p>"},
{title:'Antarctica', lat:-80, lon:0, content:"<h2>Antarctica</h2><p>1 Alumnus</p>"},
{title:'Antigua & Barbuda', lat:17.20, lon:-61.48, content:"<h2>Antigua & Barbuda</h2><p>1 Alumnus</p>"},
{title:'Argentina', lat:-36.30, lon:-60, content:"<h2>Argentina</h2><p>29 Alumni</p>"},
];
for (i=0;i<countries.length;i++)
{
c = countries[i];
marker: new google.maps.Marker({position: new google.maps.LatLng(" + c['lat'] + "," + c['lon'] + "), map: map, title: '" + c['title'] + "'}),
infowindow: new google.maps.InfoWindow({content: '" + c['content'] + "'});
}
var item;
for (var i=0; i<countries.length; i++) {
item = countries[i];
google.maps.event.addListener(item.marker, 'click', makeCallback(item));
}
function makeCallback(country) {
return function () {
country.infowindow.open(map, country.marker);
};
}
}
</script>
There are various typographical and syntax errors in the code. Also there is no need to construct strings in the place of variables. The following is a working version:
...
var countries = [...];
for (var i = 0; i < countries.length; i++) {
var c = countries[i];
c.marker = new google.maps.Marker({
position: new google.maps.LatLng(c.lat, c.lon),
map: map,
title: c.title});
c.infowindow = new google.maps.InfoWindow({content: c.content});
google.maps.event.addListener(c.marker, 'click', makeCallback(c));
}
function makeCallback(country) {
return function () {
country.infowindow.open(map, country.marker);
};
}

Categories

Resources