I'm trying to add markers to a google maps by iterating through a list and retrieving some information. I'm using the prototype library. The code is the following:
var point = new Array();
var myMarkerOptions = new Array();
var marker = new Array();
recommendedList.each(function(item){
point[item.location.ID] = new google.maps.LatLng(item.location.lat, item.location.lng);
myMarkerOptions[item.location.ID] = {
position: point[item.location.ID],
map: map
};
marker[item.location.ID] = new google.maps.Marker(myMarkerOption[item.location.ID]);
});
where the recommendedList is a JSON response of the form:
[
{"artist":"artist1","location":{"lat":"50.952226","lng":"5.34832","ID":28}},
{"artist":"artist2","location":{"lat":"52.362287","lng":"4.883965","ID":32}},
...
]
However, this is not working.
I know that the problem is not about the JSON or the google map, because I tried a simpler version with the following code and it worked:
var myLatlng = new google.maps.LatLng(recommendedList[0].location.lat,recommendedList[0].location.lng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map
});
So the problem must be in the iteration and the hash maps.
Anyone can see the problem? Thanks!
Simple enough to test without the .each
for (var i=0, item; item = recommendedList[i]; i++) {
point[item.location.ID] = new google.maps.LatLng(item.location.lat, item.location.lng);
myMarkerOptions[item.location.ID] = {
position: point[item.location.ID],
map: map
};
marker[item.location.ID] = new google.maps.Marker(myMarkerOption[item.location.ID]);
}
You can also simplify this quite a lot, unless you "need" those other arrays:
for (var i=0, item; item = recommendedList[i]; i++) {
marker[item.location.ID] = new google.maps.Marker({
new google.maps.LatLng(item.location.lat, item.location.lng),
map
});
}
I think it could be the array accessors you're using. What are you doing the point, myMarkerOptions and marker arrays once you're done with them?
Can you try declaring them as
var point = {};
var myMarkerOptions = {};
var marker = {};
That'll let you refer to them as point[item.location.ID] (etc). I think with the item.ID property being a number, JS is trying to set that numeric index of the array, rather than creating a new property in your hash.
Prototype each iterator doesn't support JSON or object data type.
Related
I'm getting back an array of JavaScript objects from a database. I'm looping through that array and creating objects to be displayed on the screen. I'm trying to use .addEventListener() to each object but I just realized that addEventListener() only works for DOM objects.
How could I add an event listener to each JavaScript object?
Here is my code:
var objects = JSON.parse(data.responseText);
var i;
var objectLn = objects.length;
for (i = 0; i < objectLn; i++) {
//Puts each object into a variable
var eachObject = objects[i];
//Establishes pin position
var pinPos = {
lat: parseFloat(eachObject.lat),
lng: parseFloat(eachObject.lng)
};
//Creates new icon for pin
var icon = {
url: "path/to/img",
scaledSize: new google.maps.Size(60, 60),
origin: null,
anchor: null
};
//Creates a new pin from pulled information
var pin = new google.maps.Marker({
position: pinPos,
map: map,
icon: icon
});
//Alerts each object on click
pin.addListener('click', function() {
alert(JSON.stringify(eachObject));
map.panTo(pinPos);
map.setCenter(pinPos);
});
}
addListener is adding a 'click' listener to each pin that is dropped, so that's good. The problem is that it's supposed to alert each object, but it's only alerting the last object I retrieve from the database on every pin I click.
try doing your loopage like so..
for (i = 0; i < objectLn; i++) {
(function(eachObject){
// copy the loop contents here. eachObject is already defined.
})(objects[i]);
}
Simply put, I am trying to dynamically create a marker and corresponding label for each property of in the loop. The label will contain the time-stamp.
However, I am fairly stuck on figuring out how to get the on-click function to remain bound to it's respective marker. The infowindow variable as well.
I have tried using a counter and creating an array of variables to reference each function. I have also tried eval and creating new variables within the global window
window["foo" + counter]
unsuccessfully. With all variations of this that I have tried the code has broken or resulted in all triggers/infowindows being bound to the same property.
Any help or direction would be greatly appreciated. I think I am just missing some depth on understanding variable/object scope. This base code results in all markers appearing and the final label (since the previous ones are overwritten) as depicted below.
variables:
prop = string representing long,lat coordinates
obj[prop] = An ISOformat timestamp
Rest of the code taken from marker Labels Google Maps API
for (var prop in obj) {
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(prop)) continue;
var templocs = prop.split(",").map(Number);
console.log(templocs[0]);
var temppos = new google.maps.LatLng(templocs[0], templocs[1]);
var mark = new google.maps.Marker({
position:temppos,
map: map,
animation:google.maps.Animation.BOUNCE,
});
var infowindow = new google.maps.InfoWindow({
content: "date taken: " + obj[prop],
maxWidth: 200
});
mark.addListener('click', function() {
infowindow.open(map, mark);
});
}
var cnt = 0;
var infowindow = [];
var mark = [];
var bounds = new google.maps.LatLngBounds();
for (var prop in obj) {
// skip loop if the property is from prototype
if(!obj.hasOwnProperty(prop)) continue;
var templocs = prop.split(",").map(Number);
console.log(templocs[0]);
var temppos = new google.maps.LatLng(templocs[0], templocs[1]);
infowindow[cnt] = new google.maps.InfoWindow({
content: "date taken: " + obj[prop],
maxWidth: 200
});
mark[cnt] = new google.maps.Marker({
position: temppos,
map: map,
animation:google.maps.Animation.BOUNCE,
});
/* mark[cnt].addListener('click', function() {
infowindow[cnt].open(map, mark);
}); */
google.maps.event.addListener(mark[cnt], 'click', (function(markerrr, cnt) {
return function() {
infowindow[cnt].open(map, mark[cnt]);
}
})(mark[cnt], cnt));
bounds.extend(mark[cnt].getPosition());
cnt++;
}
Fixed. This post is a duplicate of this one
Issue had to do with closure.
I'm writing a code that will plot multiple locations on a map using google's api. The coordinates, name and MMSI number is stored on an XML file and is imported in a javascript.
This is the part of code I'm talking about:
for(i=0; i<x; i++)
{
var locations = [
['MMSI', 50.26835, 50.45563, 1],
['MMSI', 50.29435, 50.44523, 2],
['MMSI', 50.09399, 50.40548, 3]
}
What I would like to do is add i to the end of 'MMSI' and turn it into a variable which is predefined above.
So what is written above the first code is:
var MMSI1 = 163474;
var MMSI2 = 209483;
var MMSI3 = 705245;
etc, etc...
and need the map markers to display those numbers instead of simply MMSI.
But I don't know how to achieve this as the program won't run every time I try it and google's api will only work with quotes, not variables.
I'm pretty sure there is a simple answer to this question and I am sorry for having to ask such a stupid question but I can't seem to find an answer anywhere or figure it out on my own.
Thanks in advance for any help.
Also I'm sorry if I used any terms wrong I'm still learning this language and I don't always know if I'm saying things correctly.
Ok this seems to work, I removed your ajax call to load the XML and pasted the XML in the fiddle itself. Also, I'm not an XML guru so there might be an easier method for the first part.
http://jsfiddle.net/gt8vK/4/
var x= "<Vessels><Ship><MMSI>431000527</MMSI><CALLSIGN>SLBM</CALLSIGN><LATITUDE>35.4150</LATITUDE><LONGITUDE>139.725</LONGITUDE><DESTINATION>JP SGM</DESTINATION></Ship><Ship><MMSI>244660180</MMSI><CALLSIGN>PD8027</CALLSIGN><LATITUDE>52.4066</LATITUDE><LONGITUDE>4.82345</LONGITUDE><DESTINATION>lalallal</DESTINATION></Ship></Vessels>";
var xmlDoc = new DOMParser().parseFromString(x,'text/xml');
var allShips = xmlDoc.getElementsByTagName("Ship");
console.log(xmlDoc.getElementsByTagName("Ship")[0].getElementsByTagName("MMSI")[0].childNodes[0].text)
var ships = [];
for (var i = 0, l = allShips.length; i < l; i++) {
ships.push({
name: 'MMSI' + (i + 1).toString(),
originalName: allShips[i].getElementsByTagName("MMSI")[0].childNodes[0].nodeValue,
latitude: allShips[i].getElementsByTagName("LATITUDE")[0].childNodes[0].nodeValue,
longitude: allShips[i].getElementsByTagName("LONGITUDE")[0].childNodes[0].nodeValue
})
}
var map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 2 ,
center: new google.maps.LatLng(0, 0),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var marker, i;
for (i = 0; i < ships.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(ships[i].latitude, ships[i].longitude),
map: map
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(ships[i].name);
infowindow.open(map, marker);
}
})(marker, i));
}
Basically I placed all the ships in an object, instead of creating a new variable for each one, this will keep everything cleaner and you can still access each one of them, just use ships['number'] instead of shipNumber.
I have a problem. I'm sending to JavaScript strings with lat and lng values. Then, in JavaScript I use the split() method, and gets an array with this values. How can I draw all markers? This function doesn't work properly - the markers aren't created on the map. What is wrong?
var lngstring = <%=lngstring %>
var latstring = <%=latstring %>
alert(latstring);
alert(lngstring);
var arraylat = latstring.split("#");
var arraylng = lngstring.split("#");
alert(arraylat.length) // 200
for (var i = 0; i < arraylat.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(arraylat[i],arraylng[i]),
map: map
});
//alert(arraylat[i],arraylng[i]);
}
alert("ready!");
alert(arraylat[2]); // 37.789879
alert(arraylng[2]); // -122.39044200000001
You need to quote <%=lngstring %> and <%=latstring %> to mark them as a string:
var lngstring = "<%=lngstring %>";
var latstring = "<%=latstring %>";
otherwise you will have something like this:
var lngstring = 18.69872650000002#14.971600200000012#15.58599490000006#16.077066699999932;
which is invalid javascript, and Browser can't parse it.
In your code you do not set a map object, it can be set like below, use this before adding your marker.
var mapOptions = {
zoom: 12
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
In HTML
<div id="map_canvas"></div>
Latitude and Longitude values need to be numbers. Call parseFloat() on the strings you are passing in to the LatLng constructor:
change:
position: new google.maps.LatLng(arraylat[i],arraylng[i])
to:
position: new google.maps.LatLng(parseFloat(arraylat[i]),parseFloat(arraylng[i]))
I have a Google Map with a bunch of markers.
I add markers to the map one-by-one and need to remove individual markers one-by-one too when required, using individual IDs.
Currently I have some horrible, verbose code, involving a global array of markers, an ID added as metadata to each marker, and a clunky method for looking up a marker's position within the array, as follows:
var markersArray = [];
function getPositionById(markerId, arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].metadata.id === markerId) {
return i;
}
}
return null;
}
function removeMarker(markerId) {
var marker_position = getPositionById(markerId, markersArray);
if (marker_position !== null) {
markersArray[marker_position].setMap(null);
markersArray.splice(marker_position,1);
}
}
function setMarker(position, markerId) {
removeMarker(markerId);
var temp_marker = new google.maps.Marker({
position: position
});
temp_marker.setMap(map);
temp_marker.metadata = { id: markerId };
markersArray.push(temp_marker);
}
Could anyone suggest an even slightly more elegant way to do it?
Given that to remove a marker from the Map you need to use setMap(null), means that you need to have a reference to that marker.
The way you presented in your question doesn't look as horrible as you think, but another way to do it is to use a map instead of an array (not sure if map is the best term to use here since we are already working with the Google maps Map), nonetheless, using a map would rid you from the getPositionById() function, off course this assumes that all your markerIds are unique.
Your code would look something like this.
var markers = {};
function removeMarker(markerId) {
if(markers[markerId]){
markers[markerId].setMap(null);
delete markers[markerId];
}
}
function setMarker(position, markerId) {
removeMarker(markerId);
var temp_marker = new google.maps.Marker({
position: position
});
temp_marker.setMap(map);
temp_marker.metadata = { id: markerId };
markers[markerId] = temp_marker;
}