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
Related
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.
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);
});
How can I force google to redraw its infoWindow or atleast refresh its contents?
I noticed that I must click twice on a marker before the correct data appears inside the infoWindow -maybe my closure here is the culprit.
var markers = new Array();
var allMarkers = new Array();
var infoWindow = new google.maps.InfoWindow();
var infoWindows = new Array();
// IE caches ajax request - need a way to clear cache with each fetch of data
randomize = function () {
var randomnumber = Math.floor(Math.random() * 100000);
return randomnumber;
}
function getBeachLocations() {
// construct query
var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
var queryTail = "&key=apiKey&callback=?";
var query = "SELECT * FROM BeachTable"; // beach locations tbl
var queryText = encodeURI(query);
$.ajax({
type: "GET",
url: queryURL + queryText + queryTail,
cache: false,
dataType: 'jsonp',
success: createMarkers,
error: function () {
alert("Sorry, no spatial data is available at this time, please check back on a later date.");
}
});
} //end getBeachLocations
function createMarkers(data) { // =====================create markers
url = "http://swim.jpg";
var rows = data['rows'];
var ecoli_rows;
var algae_rows;
for (var m in rows) {
var ecoli_array = new Array();
var marker = new google.maps.Marker({
map: map,
icon: new google.maps.MarkerImage(url),
beach_id: rows[m][0],
beach_name: rows[m][1],
beach_region: rows[m][2],
position: new google.maps.LatLng(rows[m][4], rows[m][5]),
idx: m,
getHeader: function () {
var str = [
'<div style="width:650px;">',
'<div class="tabs">',
'<ul>',
'<li><span>E. Coli Data</span></li>',
'<li><span>Algae Data</span></li>',
'</ul>',
'<div id="tab-1">',
'<h1>' + this.beach_name + '</h1>',
'<h3>' + this.beach_region + '</h3>'
].join('');
return str;
}, // end getHeader method
getEcoliData: function () { // begin getEcoliData
var obj;
obj = getEcoliData(this.beach_id);
return obj;
}, // end getEcoliData method
afterGetEcoliData: function (data) {
var ecoli_rows;
var ecoli_rows_str;
ecoli_rows = data['rows'];
var ecoli_rows_str = [
'<table id="ecoli_table " class="data" style="width:500px;">',
'<tr>',
'<th>Sample Date</th>',
'<th>Average E. coli Density <br/> (200 cfu/100 ml)</th>',
'<th>Recreational Water Quality Guideline</th>',
'</tr>'
].join('');
if (typeof ecoli_rows == 'undefined') {
ecoli_rows_str = '<p>Sorry no ecoli data currently exists for this beach.</p></div>'
} else {
for (var i = 0; i < ecoli_rows.length; i++) {
//console.log(rows[i]);
ecoli_rows_str += '<tr><td>' + formatDate(ecoli_rows[i][2]) + '</td><td>' + checkEcoliCount(ecoli_rows[i][3]) + '</td><td>' + ecoli_rows[i][4] + '</td></tr>';
}
ecoli_rows_str += '</table>'
ecoli_rows_str += '</div>';
// remove after test
ecoli_rows_str += '<div id="tab-2"><h1>nothing loaded</h1></div></div></div>';
} //end if
return ecoli_rows_str;
}, // end outPutEcoliData method
getAlgaeData: function () { // begin getAlgaeData
var obj;
var algae_rows_str = [
'<div id="tab-2">',
'<h1>' + this.beach_name + '</h1>',
'<h3>' + this.beach_region + '</h3>',
'<table id="algae_table " class="data" style="width:500px;">',
'<tr>',
'<th>Sample Date</th>',
'<th>Algal Toxin Microcystin <br/> (20 ug/L)</th>',
'<th>Recreational Water Quality Guideline</th>',
'<th>Blue Green Algae Cells <br/>(100,000 cells/ml)</th>',
'<th>Recreational Water Quality Guideline</th>',
'</tr>'
].join('');
obj = getAlgaeData(this.beach_id);
return obj;
}, // end getAlgaeData method
outPutAlgaeData: function (data) {
obj.done(function (data) {
algae_rows = data['rows'];
}); // end success
//console.log(algae_rows);
if (typeof algae_rows === 'undefined') {
algae_rows_str = [
'<div id="tab-2">',
'<h1>' + this.beach_name + '</h1>',
'<h3>' + this.beach_region + '</h3>',
'<p>Sorry no algae data exists for this beach.</p>',
'</div>',
'</div>',
'</div>',
'</div>'
].join('');
} else {
for (var i = 0; i < algae_rows.length; i++) {
//console.log(rows[i]);
algae_rows_str += '<tr><td>' + formatDate(algae_rows[i][2]) + '</td><td>' + checkAlgaeToxinCount(algae_rows[i][3]) + '</td><td>' + algae_rows[i][4] + '</td><td>' + checkAlgaeCount(algae_rows[i][5]) + '</td><td>' + algae_rows[i][6] + '</td></tr>';
}
algae_rows_str += '</table>'
algae_rows_str += '</div></div></div>';
//return algae_rows_str;
} //end if
return algae_rows_str;
} // end outPutAlgaeData
}); // ====================end marker
allMarkers.push(marker); //required for drop down menu
console.log(marker.beach_id + " " + marker.beach_name);
// click event handler
google.maps.event.addListener(marker, 'click', function () {
var ajaxObj = this.getEcoliData();
var marker = this;
var str;
// add loading gif
//infoWindow.setContent('<img src="../img/loading.gif" alt="loading data"/>');
ajaxObj.done(function (data) {
/*
str = marker.getHeader() + marker.afterGetEcoliData(data);
console.log(str);
*/
infoWindow.setContent(marker.getHeader() + '' + marker.afterGetEcoliData(data));
infoWindow.open(map, this);
$(".tabs").tabs({ selected: 0 });
}); // End done
}); // End click event handler
} // end for loop foreach marker
checkAdvisory(); // determine where this needs to be called from.
} //end function createMarkers
// format date as January 1, 2013
function formatDate(num) {
var d = Date.parse(num).toString('MMMM d, yyyy');
return d;
}
// check ecoli count - anything greater than or equal to 200 cfu/100ml is flagged
function checkEcoliCount(num) {
var str;
num = parseFloat(num);
if (num >= 200) {
str = '<span class="ecoliCount_on" style="color:orange"><b>' + num + '</b></span>';
} else {
return num;
}
return str;
}
// check blue green algae count - anything greater than or equal to 100,000 cells/ml is flagged
function checkAlgaeCount(num) {
var str;
num = parseFloat(num);
if (num >= 100000) {
str = '<span class="algaeCount_on" style="color:orange"><b>' + num + '</b></span>';
} else {
return num;
}
return str;
}
// check algae toxin microcystin - anything greater than or equal to 20 ug/L is flagged
function checkAlgaeToxinCount(num) {
// why include < ? - ask Cassie
var str;
var idx;
idx = num.indexOf("<");
num = num.substring(idx + 1);
num = parseFloat(num);
if (num >= 20) {
str = '<span class="algaeToxinCountOn" style="color:orange"><br>' + num + '</b></span>';
} else {
return num;
}
return str;
}
function checkAdvisory() {
/* add advisory images
ecoliCount_on
algaeCount_on
algaeToxinCountOn
*/
$(".ecoliCount_on").each(function (i, v) {
console.log(i, v);
$(this).css("color", "green");
});
$(".algaeCount_on").each(function (i, v) {
console.log(i, v);
$(this).css("color", "green");
});
$(".algaeToxinCountOn").each(function (i, v) {
console.log(i, v);
$(this).css("color", "green");
});
}
function getEcoliData(beach_id) {
//console.log(beach_id);
var rows;
var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
var queryTail = '&key=apiKey&callback=?';
var whereClause = "WHERE 'Beach_ID' = " + beach_id;
var query = "SELECT * FROM EcoliTable "
+ whereClause + " ORDER BY 'Sample_Date' DESC";
var queryText = encodeURI(query);
var ecoli_array = new Array();
return $.ajax({
type: "GET",
url: queryURL + queryText + queryTail,
cache: false,
dataType: 'jsonp'
});
}
function getAlgaeData(beach_id) {
var queryURL = "https://www.googleapis.com/fusiontables/v1/query?sql=";
var queryTail = '&key=apiKey&callback=?';
var whereClause = " WHERE 'Beach_ID' = " + beach_id;
var query = "SELECT * FROM algaeTable "
+ whereClause + " ORDER BY 'Sample_Date' DESC";
var queryText = encodeURI(query);
// ecoli request
return $.ajax({
type: "GET",
url: queryURL + queryText + queryTail,
cache: false,
dataType: 'jsonp'
});
}
// create beach locations dropdown
function createDropDownMenu() {
var query = 'SELECT Beach_Location, Beach_ID FROM beachTable ORDER BY Beach_Location ASC';
var queryText = encodeURIComponent(query);
var gvizQuery = new google.visualization.Query(
'http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
//Send query and draw table with data in response
gvizQuery.send(function (response) {
var numRows = response.getDataTable().getNumberOfRows();
var numCols = response.getDataTable().getNumberOfColumns();
var name = ['<label style="font-weight:bolder;font-size:16px"> Select a Beach:</label><select id="beach_menu" style="font-size:16px;" onchange="select_beach(this.options[this.selectedIndex].value);"><option class="defaultopt" value="">--All--</option>'];
for (var i = 0; i < numRows; i++) {
var nameValue = response.getDataTable().getValue(i, 0);
var idValue = response.getDataTable().getValue(i, 1);
name.push("<option value=" + "'" + idValue + "'" + ">" + nameValue + "</option>");
}
name.push('</select>');
document.getElementById('beach_location_dropdown').innerHTML = name.join('');
});
} // end createDropDownMenu Function
function select_beach(val) {
$("#beach_menu option[value='" + val + "']").attr('selected', 'selected');
if (val === "") {
resetMapExtent();
displayAllBeaches();
}
else {
update_layer(val)
}
} // end select_beach function
function resetMapExtent() {
google.maps.event.trigger(map, "resize");
map.setCenter(new google.maps.LatLng(53.760861, -98.813876));
map.setZoom(5);
} // end resetMapExtent function
// implement update_layer function
function update_layer(beach) {
infoWindow.close();
for (var z = 0; z < allMarkers.length; z++) {
if (beach === allMarkers[z].beach_id) {
allMarkers[z].setVisible(true);
} else {
// hide all other markers
allMarkers[z].setVisible(false);
}
}
} // end update_layer function
function displayAllBeaches() {
infoWindow.close();
// show all markers
for (var z = 0; z < allMarkers.length; z++) {
// hide all markers
allMarkers[z].setVisible(true);
}
} // end displayAllBeaches
/* start map initialization */
function initialize() {
// map
latlng = new google.maps.LatLng(49.894634, -97.119141);
var myOptions = {
center: latlng,
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
mapTypeControl: true,
mapTypeControlOptions: {
mapTypeIds: [
google.maps.MapTypeId.ROADMAP,
google.maps.MapTypeId.SATELLITE,
google.maps.MapTypeId.HYBRID,
google.maps.MapTypeId.TERRAIN
],
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
overviewMapControl: true,
overviewMapControlOptions: {
opened: true
}
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
// invocation begins here
createDropDownMenu(); // not working now.
getBeachLocations();
// legend
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(
document.getElementById('legend'));
var legend = document.getElementById('legend');
var swim_icon = "swim.jpg";
var div = document.createElement('div');
div.innerHTML = '<h4>Features</h4>' +
'<br/><img src="' + swim_icon + '"> ' + "Beaches";
legend.appendChild(div);
} // end initialization function
$(function () {
$('.view_normal').live('click', function () {
$(".container").css("width", "930px").css("margin", "auto");
$(".onewidecenter").css("width", "930px").css("margin", "auto");
$("#map_canvas").css("width", "930px").css("margin", "auto");
google.maps.event.trigger(map, "resize");
map.setCenter(new google.maps.LatLng(53.760861, -98.813876));
map.setZoom(5);
});
$('.view_full_screen').live('click', function () {
$(".container").css("width", "100%").css("margin", "auto");
$(".onewidecenter").css("width", "100%").css("margin", "auto");
$("#map_canvas").css("width", "100%").css("margin", "auto");
$(" #dropdown_container").css("width", "100%").css("margin", "auto");
google.maps.event.trigger(map, "resize");
map.setCenter(new google.maps.LatLng(53.760861, -98.813876));
map.setZoom(5);
});
}); // end page load
I have included the sample code above. Please pay special attention to my click event handler. As always, as suggestions on how best to remedy this would be greatly appreciated.
Thanks in advance,
Michael
jQuery AJAX methods are asynchronous. That means:
obj.success(function (data) {
ecoli_rows = data['rows'];
}); // end sucess
Returns immediately but the callback function doesn't run until the ajax request completes.
This means that:
infoWindow.setContent(this.getHeader() + '' +
this.getEcoliData() + '' + this.getAlgaeData());
infoWindow.open(map, this); //ajax callback hasn't fired here
opens the info window with the content BEFORE the ajax request completes.
To correct, you might do something like this:
In marker.getEcoliData:
obj = getEcoliData(this.beach_id);
return obj;
// move processing below this point to new method
And in the click event handler:
google.maps.event.addListener(marker, 'click', function () {
var ajaxObj = this.getEcoliData();
var marker = this;
ajaxObj.done(function() {
infoWindow.setContent(marker.getHeader() + '' +
marker.afterGetEcoliData() + '' +
this.getAlgaeData());
infoWindow.open(map, this);
$(".tabs").tabs({ selected: 0 });
});
This is not a complete solution since you have two asynchronous calls happening. You could either chain them, or set some kind of counter to make sure that the callback only executes when both have completed.
An even better approach would be to immediately open the infowindow with some kind of information to tell the user that data is being loaded. Then after the requests complete, you simply update the infowindow content again (with a handle to the content element) to show the returned data.
Thanks for the help with this. I managed to get this to work as expected. As it turned out I had to restructure the marker class so that two ajax requests weren't be returned an additional time.
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.
The following code grabs some JSON data from /home.json URL which contain 5 microposts by 6 users. However, only the last 4 markers are shown (not even the 5th !!). I have spend 2 days to find the bug but unfortunately I can't really get why this dosen't work. If anyone could help me I would really appreciate it!
I have tested all lon/Lat variables through alert! All of them have the appropriate data. The map should be ok since the last 4 are shown !! Most probably the problem lies with my closure definition but I really cannot understand what I am doing wrong..
var GMAPS = window.GMAPS || {};
GMAPS.mainMap = function() {
var map;
var infowindow = new google.maps.InfoWindow();
var jsonObject = {};
function addMarkers() {
var xhr = new XMLHttpRequest();
xhr.open( "GET", "/home.json", true );
xhr.onreadystatechange = function () {
if ( xhr.readyState == 4 && xhr.status == 200 ) {
jsonObject = JSON.parse( xhr.responseText );
for (var i=0; i<jsonObject.length; i++) {
for (var j=0; j<jsonObject[i].microposts.length; j++) {
(function(Name, Title, Content, Latitude, Longitude) {
return function() {
//alert(Name + "\n" + Title + "\n" + Content + "\n" + Latitude + "\n" + Longitude + "\n"); //<-- this works!
var position = new google.maps.LatLng(Latitude, Longitude);
var contentString = "<h4>" + Name.bold() + "</h4>" + "<br />" + Title.bold()
+ "<br />" + Content;
var marker = new google.maps.Marker({
position: position,
title: Title,
map: map
});
google.maps.event.addListener(marker, 'click', (function(marker, contentString) {
return function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
}
})(marker, contentString));
};
})(jsonObject[i].name, jsonObject[i].microposts[j].title,
jsonObject[i].microposts[j].content,
jsonObject[i].microposts[j].lat,
jsonObject[i].microposts[j].lon)();
}
}
}
};
xhr.send(null);
}
function createMap() {
map = new google.maps.Map(document.getElementById('main_map'), {
zoom: 10,
panControl: true,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
mapTypeControl: true,
scaleControl: true,
streetViewControl: true,
overviewMapControl: true,
scrollwheel: false,
center: new google.maps.LatLng(37.975327,23.728701),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
}
function initAddress() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
else {
var position = new google.maps.LatLng(0, 0);
map.setCenter(position);
}
}
function showPosition(position) {
var position = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(position);
}
return {
initMap : function() {
createMap();
initAddress();
addMarkers();
}
};
}();
document.addEventListener("DOMContentLoaded", GMAPS.mainMap.initMap, false);
** Note: you have an unnecessary extra set of parens at the end of your IIFE.
Before your IIFE (inside the innermost for-loop), try adding:
var jObj = jsonObject[i], mPost = jObj.microposts[j];
Then in replace the arguments to the IIFE with:
(function(Name, Title, Content, Latitude, Longitude) {
return function() {
//alert(Name + "\n" + Title + "\n" + Content + "\n" + Latitude + "\n" + Longitude + "\n"); //<-- this works!
var position = new google.maps.LatLng(Latitude, Longitude);
var contentString = "<h4>" + Name.bold() + "</h4>" + "<br />" + Title.bold()
+ "<br />" + Content;
var marker = new google.maps.Marker({
position: position,
title: Title,
map: map
});
google.maps.event.addListener(marker, 'click', (function(marker, contentString) {
return function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
}
})(marker, contentString));
};
})(jObj.name, mPost.title, mPost.content, mPost.lat, mPost.lon);
The following code should work. I still don't understand why you have the extra set of parentheses.
xhr.onreadystatechange = function() {
var i = 0, j = 0;
if ( xhr.readyState == 4 && xhr.status == 200 ) {
jsonObject = JSON.parse( xhr.responseText );
for (var ilen = jsonObject.length; i < ilen;) {
for (var jObj = jsonObject[i++], jlen = jObj.microposts.length; j < jlen;) {
var mPost = jObj.microposts[j++];
(function(Name, Title, Content, Latitude, Longitude) {
return function() {
//alert(Name + "\n" + Title + "\n" + Content + "\n" + Latitude + "\n" + Longitude + "\n"); //<-- this works!
var position = new google.maps.LatLng(Latitude, Longitude);
var contentString = "<h4>" + Name.bold() + "</h4>" + "<br />" + Title.bold()
+ "<br />" + Content;
var marker = new google.maps.Marker({
position: position,
title: Title,
map: map
});
google.maps.event.addListener(marker, 'click', (function(marker, contentString) {
return function() {
infowindow.setContent(contentString);
infowindow.open(map, marker);
}
})(marker, contentString));
};
})(
jObj.name, mPost.title, mPost.content, mPost.lat, mPost.lon
);
}
}
}
};