Google map info box run incorrectly - javascript

I'm trying to create a group of markers with info box attached. However, no matter which marker I click, it always opens the info box of the last detailmarker. Anyone know why? Please help.
var stepDisplay = new google.maps.InfoWindow();
function AddDetailMarker(map, itinerary) {
var markers = [];
for (var i = 1; i < itinerary.Legs.length; i++) {
var position = new google.maps.LatLng(itinerary.Legs[i].BusStop.Latitude, itinerary.Legs[i].BusStop.Longitude);
var title = itinerary.Legs[i].BusStop.Code + ": " + itinerary.Legs[i].BusStop.Location + " " + itinerary.Legs[i].BusStop.Street + ", Quận " + itinerary.Legs[i].BusStop.Ward;
var detailmarker = new google.maps.Marker({
position: position,
map: map,
title: title,
icon: "/Content/img/customized_marker/" + "blue" + "/" + "bus-stop2" + ".png"
});
google.maps.event.addListener(detailmarker, 'click', function () {
stepDisplay.setContent(title);
stepDisplay.open(map, detailmarker);
});
markers[i-1] = detailmarker;
}
}
Edit: possible dublicate of Google maps infowindow showing on wrong marker. I've tried all the solutions I found here and none works.

Yes, this is exactly the same problem as the other one you linked to, and the solution for your code is the same - put the code to create each marker into a function, and call that function in your loop:
var stepDisplay = new google.maps.InfoWindow();
function AddDetailMarker(map, itinerary) {
for (var i = 1; i < itinerary.Legs.length; i++) {
addLegMarker( map, itinerary.Legs[i] );
}
}
function addLegMarker( map, leg ) {
var position = new google.maps.LatLng(leg.BusStop.Latitude, leg.BusStop.Longitude);
var title = leg.BusStop.Code + ": " + leg.BusStop.Location + " " + leg.BusStop.Street + ", Quận " + leg.BusStop.Ward;
var detailmarker = new google.maps.Marker({
position: position,
map: map,
title: title,
icon: "/Content/img/customized_marker/" + "blue" + "/" + "bus-stop2" + ".png"
});
google.maps.event.addListener(detailmarker, 'click', function () {
stepDisplay.setContent(title);
stepDisplay.open(map, detailmarker);
});
}
Do you see why that fixes it? The title and detailmarker are now specific to each invocation of addLegMarker(). In the original code, there was only a single copy of each of these variables, shared among all markers.

Related

alert if marker is outside the polygon

I am currently developing a web application that would alert if a systems generated marker is outside a polygon, but my function is only working in 1 polygon, it does not work in other polygon. Is there something wrong in my loop or what did i miss ?
See image here: sample image
Here is my function.
function checkInPolygon(marker) {
var infowindow = new google.maps.InfoWindow();
for (var x = 0; x < mpa_polygon.length; x++) {
var html = google.maps.geometry.poly.containsLocation(marker.getPosition(), mpa_polygon[x]) ? 'inside' : 'outside';
console.log(mpa_polygon[x]);
}
infowindow.setContent(html);
infowindow.open(map, marker);
}
Full code implementation:
function displaySalesMan() {
var names = [];
var ids = [];
var dateMPA = [];
var longlat = [];
var header = [];
var loc = [
[]
];
var newdata = [];
$.ajax({
url: "/geofencing/GeofencingAPI.php",
type: "GET",
data: {
"type": "view_salesmanDashboard_gensan_COLOR",
"filter_Date": getDate()
},
dataType: "html",
crossDomain: true,
cache: false,
success: function(response) {
var data = JSON.parse(response);
if (response == 'No records are generated on selected salesman and date!') {
alert('No records are found in selected date!');
DeleteMarkers();
} else {
console.log(data.length);
for (var x = 0; x < data.length; x++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(data[x].latitude, data[x].longitude),
map: map,
icon: 'http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + data[x].TERRCOLOR.substr(1)
});
>
i call the
function here with a parameter ** marker **
checkInPolygon(marker);
markers.push(marker);
google.maps.event.addListener(marker, 'click', (function(marker, x) {
return function() {
var contentString = "<div style='overflow: hidden; margin: 0 auto;'><div class='modal-header' style='text-align: center;'><div class=''><img style='height: 120px; width:120px;' alt='salesmanPic' src='img/jomar.png'></div></div>" +
"<div class='table-responsive'>" +
"<table class='table table-condensed'>" +
"<tr><td>Salesman:</td><td class='bold'>" + data[x].Salesman + "</td></tr>" +
"<tr><td>Customer:</td><td>" + data[x].Customer + "</td></tr>" +
"<tr><td>Location:</td><td>" + data[x].longitude + ' ' + data[x].latitude + "</td></tr>" +
"<tr><td>Delivery Date:</td><td>" + data[x].deliveryDate + "</td></tr>" +
"</table>" +
"</div>" +
"</div>";
infoWindow.setContent(contentString);
infoWindow.open(map, marker);
}
})(marker, x));
} //end for
} //else
} //on succjess
}) //ajax close tag
//checkerForSalesman(markers, mpa_polygon);
infoWindow = new google.maps.InfoWindow;
} //display salesman funciton
From what I understood of your code, for each marker you going to ask "is this in first polygon? yes o no" then you insert the answer in the infowindow of that marker...then going to ask for the same marker "is this in the second polygon? yes o no" and so on, always overwriting the previous answer for the previous polygon....that is why it only works for the last polygon inserted.
So the solution here would be find a way to keep separate answers for each polygon, or select which polygon are you aiming.
To be clear if a marker which is only one point, can only have 2 posibles states (true or false) and you have 3 polygons..that breaks the equation. cause for instance in the image you provided, all the markers shows good results if your reference is the red polygon...but you need to know which of the 3 polygons you are referring to.
Hope it makes sense

Changing google maps marker property after clicking button inside info window

I have markers on a map. I set the opacity of the marker dependent on the date in JSON.
Because of this when the map loads, some of the markers are 0.5 opacity, some are 1 opacity.
Inside the marker's info window there is a button. When I click this button I want to change the opacity to 1.
Below is some snippets of my code to show you how I have it setup at the moment.
Any help would be much appreciated
//For every item in JSON
$.each(dbJSON, function(key, data) {
var opacity = 1;
var today = new Date();
var fadeDate = new Date(data.last_rated); //get the date last rated
fadeDate.setDate(fadeDate.getDate() + 1); //and add 1 date to it to specify the day when the icon should fade
if(Date.parse(today) > Date.parse(fadeDate)) {
console.log('fade');
opacity = 0.5;
} else {
console.log('show');
opacity = 1;
}
var postal_town = data.location;
geocoder.geocode( { 'address': postal_town}, function(results, status) {
//...
console.log(opacity);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: data.manufacturer_name,
icon: image,
rating: data.rating,
opacity: opacity
});
markers[data.id] = marker;
marker.addListener('click', function() {
var contentString = '<div id="content">'+
'<h1>' + data.manufacturer_name + '</h1>' +
'<button id="seen-it" data-rating="' + data.rating + '" data-entry-id="' + data.id + '">Seen it</button>' +
'<p><strong>Rating: </strong><span id="rating">' + markers[data.id].rating + '</span></p>' +
'</div>';
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
});
});
//Do something when the #seen-it button is clicked
$(document).on('click', '#seen-it', function(event){
//...
});
Since you have the id of the marker stored in the data-entry-id you could use (assuming the markers variable is accessible from your handler)
$(document).on('click', '#seen-it', function(event){
var markerId = $(this).data('entry-id');
markers[markerId].setOpacity(1);
});

Proper formatting and distribution on multiple events for a jquery button click?

For now, on a button click I have it so that it takes in data from two textboxes, and uses it to
1) append tweets to a panel, and
2) drop pins on a map.
My next step is to have it so that on the button click, it geodecodes a location, and does the same thing. I feel like my jquery.click function is getting really big, and wanted to know if there was a standard way to "separate" it out to make it look prettier and more readable. Can you typically have javascript functions within a jquery file that are called upon, or what is the way to go?
Here is my current jquery file. As you can see it's very big but what happens is straight forward: searchbutton on click takes some values, and sets up a new map in that location, then I access my web server's information, append it to a panel, and also drop pins on a map.
$(function () {
$("#search-button").click(function() {
// variables for google maps
var LatValue = parseFloat($("#searchLat").val());
var LonValue = parseFloat($("#searchLon").val());
var myLatLng = {lat: LatValue, lng: LonValue};
var map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 12,
center: myLatLng
});
$.getJSON(
"http://localhost:3000/tw",
{
geoSearchWord: $("#searchme").val(),
geoSearchWordLat: $("#searchLat").val(),
geoSearchWordLon: $("#searchLon").val(),
geoSearchWordRad: $("#searchRadius").val()
}
).done(function (result) {
$("#fromTweets").empty();
console.log(result);
for (i = 0; i < result.statuses.length; i++) {
//Print out username and status
$("#fromTweets").append('<b>' + "Username: " + '</b>' + result.statuses[i].user.screen_name + '<br/>');
$("#fromTweets").append('<b>' + "Tweet: " + '</b>' + result.statuses[i].text + '<br/>');
$("#fromTweets").append('<b>' + "Created at: " + '</b>' + result.statuses[i].created_at + '<br/>');
if (result.statuses[i].geo !== null) {
//Print out the geolocation
$("#fromTweets").append('<b>' + "GeoLocation: " + '</b>' + "Lat: " + result.statuses[i].geo.coordinates[0] + " Lon: " + result.statuses[i].geo.coordinates[1] + '<br/>'+ '<br/>');
//dropping a new marker on the map for each tweet that has lat/lon values
//Multiplying by i * 0.0005 to space them out in case they are from the same gelocation while still holding
//the integrity of their location.
LatValue = parseFloat(result.statuses[i].geo.coordinates[0] + i*0.0005);
LonValue = parseFloat(result.statuses[i].geo.coordinates[1] + i*0.0005);
myLatLng = {lat: LatValue, lng: LonValue};
var newMarker = new google.maps.Marker({
position: myLatLng,
map: map,
animation: google.maps.Animation.DROP,
});
} else {
$("#fromTweets").append('<b>' + "GeoLocation: " + '</b>' + "Cannot be identified" + '<br/>' + '<br/>')
}
}
});
});
The most simple and obvious thing you can do it so split your code by extracting independent logical blocks to functions:
Just something like this:
var map;
function combineTweetsAjaxRequestData()
{
return {
geoSearchWord: $("#searchme").val(),
geoSearchWordLat: $("#searchLat").val(),
geoSearchWordLon: $("#searchLon").val(),
geoSearchWordRad: $("#searchRadius").val()
};
}
function createGMap()
{
return new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 12,
center: {
lat: parseFloat($("#searchLat").val()),
lng: parseFloat($("#searchLon").val())
}
});
}
function createGMarker(coords)
{
var coordsFixed = {
lat: parseFloat(coords[0] + i * 0.0005),
lng: parseFloat(coords[1] + i * 0.0005)
};
return new google.maps.Marker({
position: coordsFixed,
map: map,
animation: google.maps.Animation.DROP,
});
}
function clearInfo() {
$("#fromTweets").empty();
}
function appendInfo(title, text)
{
$("#fromTweets").append('<b>' + title + ':</b> ' + text + '<br/>');
}
function processTweet(tw)
{
appendInfo('Username', tw.user.screen_name);
appendInfo('Tweet', tw.text);
appendInfo('Created at', tw.created_at);
if (tw.geo !== null) {
var twCoords = tw.geo.coordinates;
appendInfo('GeoLocation', "Lat: " + twCoords[0] + " Lon: " + twCoords[1]);
createGMarker(twCoords);
} else {
appendInfo('GeoLocation', "Cannot be identified")
}
}
function loadTweets() {
$.getJSON(
"http://localhost:3000/tw",
combineTweetsAjaxRequestData()
).done(function (result) {
clearInfo();
console.log(result);
result.statuses.forEach(processTweet);
});
}
$(document).ready(function () {
map = createGMap();
$("#search-button").click(function() {
loadTweets();
});
});
Now, it can be easily read as a text. Your code should be readable and understandable from the first glance. Even better, if a non-developer can read it and understand some basic concepts.
What happens when the page is loaded? We create a Google map control and load tweets
How do we load tweets? We make a AJAX request by combining request data from inputs
What happens when it is loaded? We clear out current information and process every tweet
How do we process a single tweet? We output some basic information. Then, we output geolocation if it is available. Otherwise, we output an error.
Now, if you need to add information to another source, you won't extend or modify your loadTweets method - you will extend or modify appendInfo method, because the logics of information output is encapsulated here.

Cannot read property '__e3_' of undefined adding an info windows in Google Maps API

I am trying to add an info window when the user clicks on the marker on the map. When I click the marker to test, I am getting this error: Uncaught TypeError: Cannot read property '__e3_' of undefined. Here is my code:
for(var i = 0; i < final_search_results.length; ++i) {
var title = ("Parameter: " + final_search_results[i].parm_desc + "; Date: " + final_search_results[i].date + "; Result: " + final_search_results[i].result);
var markerLatlng = new google.maps.LatLng(final_search_results[i].st_id.lat_coord, final_search_results[i].st_id.long_coord); // Add the coordinates
var marker_icon = new google.maps.MarkerImage("./marker_icon.png", null, null, null, new google.maps.Size(64,64))
var marker = new google.maps.Marker({
position: markerLatlng,
icon: marker_icon,
map: map,
title: title
});
marker['result'] = final_search_results[i].result;
marker['date'] = final_search_results[i].date;
marker['time'] = final_search_results[i].time;
marker['station'] = final_search_results[i].st_id.station_id;
marker_array.push(marker);
}
for(var k = 0; k < marker_array.length; ++k) {
var content = ("<p>Station: " + marker_array[k].station + "; Date: " + marker_array[k].date + "</p>");
var infowindow = new google.maps.InfoWindow({ // Create a new InfoWindow
content: content// HTML contents of the InfoWindow
);
google.maps.event.addListener(marker[k], 'click', function() { // Add a Click Listener to our marker
infowindow.open(map,marker[k]); // Open our InfoWindow
});
}
I only get this error when I click the marker. Everything was fine before I added the code blow the *. If you would like to see more code just let me know.

Google Maps API v3: Looping through and adding polylines to a map

I've gone through the forums trying to search for solutions, and I've adapted my code for several problems I've come across, but this one eludes me. I'm trying to plot multiple points on a map (which works) and then draw lines between the points. Each marker contains information, such as latitude and longitude, as well as it's neighbor (the point that I want to draw the line to). I also give it the color I want the line, as different 'routes' can be in different colors. The only I can see being a problem is that I draw a line, set it on the map, and run the loop again for the next marker.
My code places the markers, places the information window for each marker, but doesn't draw the lines between the markers. Can anyone see where I've screwed up, or even if this is possible to do it in the way I'm doing it?
The reason I'm keeping the drawMap function separate is in the event users want to filter out visible data, I need to re-draw the map dynamically. So, I'm keeping the marker list globally so I can reference it even after the function has finished.
My code:
http://www.nku.edu/~sweikatam1/nkuPhysicalMapTest.html
The spot in particular with the issue is the function drawMap, which gets passed an array of objects, markerList, containing the latitude, longitude, color (for the polyline), and other bits of data.
The line placement:
for(var j = 0; j < markerList.length; j++){
if(markerList[j].name == markerList[i].neighbor){
var targetDestination = new google.maps.LatLng(markerList[j].latitude,markerList[j].longitude);
//alert(markerList[i].latitude + " " + markerList[i].longitude + " \r" + markerList[j].latitude + " " + markerList[j].longitude);
}
}
//set the pathway for the two points
var flightPlanCoordinates = [
new google.maps.LatLng(markerList[i].latitude, markerList[i].longitude),
new google.maps.LatLng(targetDestination)
];
//alert("Color: " + markerList[i].routeColor);
//set the line and color
var flightPath = new google.maps.Polyline({
path:flightPlanCoordinates,
strokeColor:markerList[i].routeColor,
strokeOpacity:2,
strokeWeight:5
});
//apply lines
flightPath.setMap(map);
The function as a whole:
function drawMap(markerList){
//alert("Starting drawMap");
//create the map
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 15,
center: new google.maps.LatLng(39.032253, -84.465015),
mapTypeId: google.maps.MapTypeId.HYBRID
});
var marker;
for (var i = 0; i <markerList.length; i++){
/*alert("markerList # i: " + markerList[i].name);
alert("Marker Data: " + "Name: " + markerList[i].name + "\r "
+ "Latitude: " + markerList[i].latitude + "\r "
+ "Longitude: " + markerList[i].longitude + "\r "
+ "Content Type: " + markerList[i].contentType + "\r "
+ "Image: " + markerList[i].image
+ "Color: " + markerList[i].routeColor);*/
var contentData = '<b>'+markerList[i].name +'</b>: '
+ markerList[i].latitude + ' x '
+ markerList[i].longitude + '<br/><p>'
+ markerList[i].contentType
+'</p><img src="' + markerList[i].image + " height=150 width=100>";
//create the marker
marker = new google.maps.Marker({
position: new google.maps.LatLng(markerList[i].latitude,markerList[i].longitude),
draggable: false,
icon: markerList[i].icon,
map:map,
content: contentData,
title:markerList[i].name
});
//find the neighbor for the current marker and set the destination coordinates
for(var j = 0; j < markerList.length; j++){
if(markerList[j].name == markerList[i].neighbor){
var targetDestination = new google.maps.LatLng(markerList[j].latitude,markerList[j].longitude);
//alert(markerList[i].latitude + " " + markerList[i].longitude + " \r" + markerList[j].latitude + " " + markerList[j].longitude);
}
}
//set the pathway for the two points
var flightPlanCoordinates = [
new google.maps.LatLng(markerList[i].latitude, markerList[i].longitude),
new google.maps.LatLng(targetDestination)
];
//alert("Color: " + markerList[i].routeColor);
//set the line and color
var flightPath = new google.maps.Polyline({
path:flightPlanCoordinates,
strokeColor:markerList[i].routeColor,
strokeOpacity:2,
strokeWeight:5
});
//apply lines
flightPath.setMap(map);
//handle open information windows
google.maps.event.addListener(marker,'click', function(){
closeInfos();
var info = new google.maps.InfoWindow({content: this.content});
info.open(map,this);
infos[0]=info;
});
//alert("Marker " + markerList[i].name + " placed.");
}
//alert("drawMap complete. Drawing lines");
<!-- DRAWING LINES COMPLETE -->
}
If anything here seems odd, confusing, or needs clarification, please let me know. Criticisms and ways of doing things better are always welcome. Thanks guys!
In defining, flightPlanCoordinates, the second LatLng was being created out of another LatLng (targetDestination). So just remove the new google.maps.LatLng portion and use the targetDestination directly. With this change, I saw a blue zigzag and a red one being drawn on the map.
var flightPlanCoordinates = [
new google.maps.LatLng(markerList[i].latitude, markerList[i].longitude),
targetDestination
];

Categories