I've iterated over a table with javascript so I can use the data as a variable for creating markers on a Google Map. My map and the code that iterates over the table both work, but I cannot figure out how to make the gridmap value available inside my marker variable. I assume I need to do a for loop around my marker variable, which I can probably figure out, I am simple stuck on taking my element variables, and making them available as variables for my markers. Below is my code, if this makes any sense. I've been at this for hours and it is 3:30am; I will refractor the question in the morning if needed. Thank you.
This is the updated and working code:
I iterated over the DOM to grab the <tr> elements from tbody only. Note the tr:gt(0) part - this skips the first header row. Then I create a new array by filtering out the markers against the gdata array. I still need to clean this up a bit add more functionality like clustering, but I am very happy at this point and hopefully this will help someone else.
<script>
function initMap() {
var map;
var table = $("table");
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var labelIndex = 0;
var htmlLabel = labels.split(""); // Add Labels to Html Columns for Matching
var gdata = new Array();
$("table tbody tr:gt(0)").each(function (i) {
gdata[i] = new Array();
$(this).children('td').each(function (ii) {
gdata[i][ii] = $(this).text();
});
});
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
mapTypeId: 'satellite',
disableDefaultUI: true,
scrollwheel: false,
draggable: true
};
// Display a map on the page
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
map.setTilt(45);
// Multiple Markers
var markers = [
['a0', 32.840801, -117.244842],
['a10', 32.840801, -117.244842],
['a20', 32.840777, -117.244864],
['a30', 32.840758, -117.244881],
['a40', 32.840732, -117.244899],
['aa0', 32.840828, -117.244794],
['aa10', 32.840828, -117.244794],
['b0', 32.840624, -117.24493],
['b10', 32.840624, -117.24493],
['b20', 32.840594, -117.244928],
['b30', 32.840567, -117.244924],
['b40', 32.840544, -117.244918],
['b60', 32.840544, -117.244918],
['bb0', 32.840495, -117.244897],
['bb10', 32.840495, -117.244897],
['bb20', 32.840468, -117.244885],
['c0', 32.84082, -117.244712],
['c10', 32.84082, -117.244712],
['c20', 32.840815, -117.244729],
['c30', 32.840806, -117.244749],
['c40', 32.840793, -117.244767],
['c50', 32.840779, -117.244789],
['c70', 32.840755, -117.244816],
['cc0', 32.840828, -117.244661],
['cc10', 32.840828, -117.244661],
['d0', 32.840607, -117.244867],
['d10', 32.840607, -117.244867],
['d20', 32.840586, -117.24486],
['d30', 32.840567, -117.244856],
['d40', 32.840543, -117.244841],
['d50', 32.840514, -117.244824],
['dd0', 32.84046, -117.244774],
['dd10', 32.84046, -117.244774],
['e0', 32.840788, -117.244598],
['e10', 32.840788, -117.244598],
['e20', 32.840791, -117.24462],
['e30', 32.840788, -117.244644],
['e40', 32.840787, -117.244665],
['e50', 32.840783, -117.244687],
['e60', 32.84078, -117.244707],
['e70', 32.840769, -117.244729],
['ee0', 32.84078, -117.244539],
['ee10', 32.84078, -117.244539],
['f10', 32.840607, -117.244809],
['f20', 32.840586, -117.244802],
['f30', 32.840564, -117.244785],
['f40', 32.840543, -117.244765],
['f50', 32.840532, -117.244749],
['f60', 32.840519, -117.244731],
['f70', 32.840508, -117.244714],
['ff0', 32.840473, -117.244632],
['ff10', 32.840473, -117.244632],
['g0', 32.840709, -117.244468],
['g10', 32.840709, -117.244468],
['g20', 32.840718, -117.244484],
['g30', 32.840737, -117.244499],
['g40', 32.840739, -117.244515],
['g50', 32.840747, -117.244531],
['h0', 32.840681, -117.244569],
['h10', 32.840681, -117.244569],
['h20', 32.840707, -117.244574],
['i0', 32.840611, -117.24458],
['i10', 32.840611, -117.24458],
['i20', 32.840576, -117.24461]
];
var filteredMarkers = []; // the results array
for (var iii = 0; iii < gdata.length; iii++) // iterate for every marker key
{
filteredMarkers = filteredMarkers.concat(markers.filter(function (item) {
return item[0] == gdata[iii][0];
}));
}
console.log(filteredMarkers);
console.log(gdata);
console.log(markers);
// Info Window Content
var infoWindowContent = [
['<div class="">' +
'<h3>Add Code Here</h3>' +
'<p>Add Code Here</p>' + '</div>']
];
// Display multiple markers on a map
var infoWindow = new google.maps.InfoWindow(), marker, i;
for (i = 0; i < filteredMarkers.length; i++) {
var position = new google.maps.LatLng(filteredMarkers[i][1], filteredMarkers[i][2]);
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: filteredMarkers[i][0],
label: labels[labelIndex++ % labels.length]
});
// Allow each marker to have an info window
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infoWindow.setContent(infoWindowContent[i][0]);
infoWindow.open(map, marker);
}
})(marker, i));
// Automatically center the map fitting all markers on the screen
map.fitBounds(bounds);
}
// Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {
this.setZoom(24);
google.maps.event.removeListener(boundsListener);
});
}
</script>
It appears you're also using Angular and that the id='gridmap' div is returning the object name and not the content. The nature of the div content looks like the crux of problem and so would suggest looking at this SO question: How to show object property with Angularjs
From here if you can generate HTML that looks something like this below after Angular has done its thing, keeping the property out of view by inserting its elements into data tags:
<tr>
<td> ..... </td>
<td> ..... </td>
<td> ..... </td>
<td class='gridmap' data-lat='23.424' data-lng='-117.233'>a0</td>
</tr>
If you insert the whole object including curly brackets you may have to do additional JSON stringification and parsing which at this point are better avoided.
Note that HTML id labels should only used for unique DOM elements, so if you have more than one table row it should be a class (which also means adjusting your css accordingly)
Now we can use jquery data to interrogate the same HTML cell tag and pass to grLat and grLng variables :
$('tr').each(function (i) {
var $tds = $(this).find('td').eq(8), // moved the eq(8) here
gLabel = htmlLabel[i],
gridmap = $tds.text(),
grLat = Number($tds.data('lat')), // get the lat data
grLng = Number($tds.data('lng')); // get the lng data
console.log(
'Marker:' + gLabel
+ '\nRow:' + (i + 1)
+ '\nGrid Map: ' + gridmap
+ '\nGrid lat: ' + grLat
+ '\nGrid lng: ' + grLng // check components
);
var marker = new google.maps.Marker({
position: {lat: grLat, lng:grLng}, // recomposed object
map: map,
label: labels[labelIndex++ % labels.length],
animation: google.maps.Animation.DROP
});
})
This should put you in a better position to debug
I have looked all over but can't find an answer to this. I have a map that when I click on it adds markers to where I clicked. I am pushing those markers into an array but when I do one marker just seems to override the one that was in the array before instead of adding another index to the array. The array just always looks like this [me] no matter how many markers are on the map. Here is the code
addLatLng: function(event) {
var path = this.poly.getPath();
var markers = [];
path.push(event.latLng);
this.calcDistance(path);
var marker = new google.maps.Marker({
position: event.latLng,
title: '#' + path.getLength(),
map: this.map
});
markers.push(marker);
console.log(markers);
console.log(marker);
// debugger;
function removeMarkers(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
markers = [];
}
$('#btn-clear-map').on('click', function(event) {
event.preventDefault();
removeMarkers(null);
});
$('#btn-clear-point').on('click', function(event) {
event.preventDefault();
markers[markers.length -1].setMap(null);
});
},
this is part of a backbone view if that makes any difference. I just have no idea why when I push a marker in it seems to override the one that was already in there.
Edit: Ok I just figured out why, every time I click to make a new marker, it is resetting the marker array. Any clever ways to get around this?
The problem is that you are re-declaring the markers array on each call to addLatLng method (Also you're new event handlers and creating removeMarkers function and a closure each time)
Instead, you should keep the markers array as a property of the view as shown below:
Backbone.View.extend({
initialize: function() {
this.markers = [];
},
events: {
'click #btn-clear-map': 'removeMarkers',
'click #btn-clear-point': 'clearPoint',
},
render: function() {},
addLatLng: function(event) {
var path = this.poly.getPath();
path.push(event.latLng);
this.calcDistance(path);
var marker = new google.maps.Marker({
position: event.latLng,
title: '#' + path.getLength(),
map: this.map
});
this.markers.push(marker);
},
removeMarkers: function(event) {
event.preventDefault();
for (var i = 0; i < this.markers.length; i++) {
this.markers[i].setMap(null);
}
this.markers = [];
},
clearPoint: function(event) {
event.preventDefault();
this.markers[this.markers.length - 1].setMap(null);
}
});
I have add the following code to a Google Map on a site of mine. The map contains many points pulling from coordinates set in the WordPress backend.
I also want to include some static points which will always stay on the map and am hardcoding their coordinates.
The following is the code I am using and what happens is that the code displays the first marker but not the infobox. Because of this, the code stops and does not continue through the for loop. The issue is at the return function() bit, but I am not sure how to get it working.
var infowindow = new google.maps.InfoWindow({maxWidth: 185});
var setMarker;
var setMarkers = new Array();
var setLocations = [
['<h4>Location1</h4>', 53.4264,-6.2499, '/wp-content/themes/path/to/airport_icon.png'],
['<h4>Location2</h4>', 53.3461,-6.2969, '/wp-content/themes/path/to/train_icon.png'],
['<h4>Location3</h4>', 53.3532,-6.2468, '/wp-content/themes/path/to/train_icon.png'],
['<h4>Location4</h4>', 53.4264,-6.2499, '/wp-content/themes/path/to/dvc_icon.png'],
['<h4>Location5</h4>', 53.4264,-6.2499, '/wp-content/themes/path/to/dvc_icon.png'],
];
for (var i = 0; i < setLocations.length; i++) {
marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(setLocations[i][1], setLocations[i][2]),
icon : setLocations[i][3],
});
setMarkers.push(setMarker);
google.maps.event.addListener(setMarker, 'click', (function(setMarker, i) {
return function() {
infowindow.setContent(setLocations[i][0]);
infowindow.open(map, setMarker);
}
})(setMarker, i));
}
Define your setMarker variable inside the for loop and push it to your markers array:
for (var i = 0; i < setLocations.length; i++) {
var setMarker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(setLocations[i][1], setLocations[i][2])
});
google.maps.event.addListener(setMarker, 'click', (function (setMarker, i) {
return function () {
infowindow.setContent(setLocations[i][0]);
infowindow.open(map, setMarker);
}
})(setMarker, i));
setMarkers.push(setMarker);
}
JSFiddle demo
When I plug in values for x instead of using a for loop, this code works. But when I use the for loop, the infowindow shows up distorted on the left side of the screen.
What the heel!
for (var x = 0; x < data.page_size; x++) {
var position = new google.maps.LatLng(
data.events.event[x]['latitude'],
data.events.event[x]['longitude']);
marker.push(
new google.maps.Marker({
position: position,
map: map,
icon: image}
));
google.maps.event.addListener(marker[x], 'click', function() {
infowindow.setContent(content[x]);
infowindow.open(map, marker[x]);
});
}
You must use the closure in this case. Like this:
(function(m,c){
google.maps.event.addListener(m, 'click', function() {
infowindow.setContent(c);
infowindow.open(map, m);
});
})(marker[x],content[x])
An economical way to approach this is to make the marker aware of its own index at the cost of just one Number property per marker, and avoiding the need to form a set of closures containing copies of content[x].
for (var x = 0; x < data.page_size; x++) {
...
marker[x].x = x;//make the marker aware of its own index
google.maps.event.addListener(marker[x], 'click', function() {
infowindow.setContent(content[this.x]);
infowindow.open(map, this);
});
}
Providing the marker array and the content array remain static, or are compatibly managed, then this.x will reliably pull out the correct content for each marker.