Passing XML markers to Google Map
- by djmadscribbler
I've been creating a V3 Google map based on this example from Mike Williams http://www.geocodezip.com/v3_MW_example_map3.html
I've run into a bit of a problem though. If I have no parameters in my URL then I get the error "id is undefined idmarkers [id.toLowerCase()] = marker;" in Firebug and only one marker will show up. If I have a parameter (?id=105 for example) then all the sidebar links say 105 (or whatever the parameter in the URL was) instead of their respective label as listed in the XML file and a random infowindow will be opened instead of the window for the id in the URL. Here is my javascript:
var map = null;
var lastmarker = null;
// ========== Read paramaters that have been passed in ==========
// Before we go looking for the passed parameters, set some defaults
// in case there are no parameters
var id;
var index = -1;
// these set the initial center, zoom and maptype for the map
// if it is not specified in the query string
var lat = 42.194741;
var lng = -121.700301;
var zoom = 18;
var maptype = google.maps.MapTypeId.HYBRID;
function MapTypeId2UrlValue(maptype) {
var urlValue = 'm';
switch (maptype) {
case google.maps.MapTypeId.HYBRID: urlValue = 'h';
break;
case google.maps.MapTypeId.SATELLITE: urlValue = 'k';
break;
case google.maps.MapTypeId.TERRAIN: urlValue = 't';
break;
default:
case google.maps.MapTypeId.ROADMAP: urlValue = 'm';
break;
}
return urlValue;
}
// If there are any parameters at eh end of the URL, they will be in location.search
// looking something like "?marker=3"
// skip the first character, we are not interested in the "?"
var query = location.search.substring(1);
// split the rest at each "&" character to give a list of "argname=value" pairs
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
// break each pair at the first "=" to obtain the argname and value
var pos = pairs[i].indexOf("=");
var argname = pairs[i].substring(0, pos).toLowerCase();
var value = pairs[i].substring(pos + 1).toLowerCase();
// process each possible argname - use unescape() if theres any chance of spaces
if (argname == "id") { id = unescape(value); }
if (argname == "marker") { index = parseFloat(value); }
if (argname == "lat") { lat = parseFloat(value); }
if (argname == "lng") { lng = parseFloat(value); }
if (argname == "zoom") { zoom = parseInt(value); }
if (argname == "type") {
// from the v3 documentation 8/24/2010
// HYBRID This map type displays a transparent layer of major streets on satellite images.
// ROADMAP This map type displays a normal street map.
// SATELLITE This map type displays satellite images.
// TERRAIN This map type displays maps with physical features such as terrain and vegetation.
if (value == "m") { maptype = google.maps.MapTypeId.ROADMAP; }
if (value == "k") { maptype = google.maps.MapTypeId.SATELLITE; }
if (value == "h") { maptype = google.maps.MapTypeId.HYBRID; }
if (value == "t") { maptype = google.maps.MapTypeId.TERRAIN; }
}
}
// this variable will collect the html which will eventually be placed in the side_bar
var side_bar_html = "";
// arrays to hold copies of the markers and html used by the side_bar
// because the function closure trick doesnt work there
var gmarkers = [];
var idmarkers = [];
// global "map" variable
var map = null;
// A function to create the marker and set up the event window function
function createMarker(point, icon, label, html) {
var contentString = html;
var marker = new google.maps.Marker({
position: point,
map: map,
title: label,
icon: icon,
zIndex: Math.round(point.lat() * -100000) << 5
});
marker.id = id;
marker.index = gmarkers.length;
google.maps.event.addListener(marker, 'click', function () {
lastmarker = new Object;
lastmarker.id = marker.id;
lastmarker.index = marker.index;
infowindow.setContent(contentString);
infowindow.open(map, marker);
});
// save the info we need to use later for the side_bar
gmarkers.push(marker);
idmarkers[id.toLowerCase()] = marker;
// add a line to the side_bar html
side_bar_html += '<a href="javascript:myclick(' + (gmarkers.length - 1) + ')">' + id + '<\/a><br>';
}
// This function picks up the click and opens the corresponding info window
function myclick(i) {
google.maps.event.trigger(gmarkers[i], "click");
}
function makeLink() {
var mapinfo = "lat=" + map.getCenter().lat().toFixed(6)
+ "&lng=" + map.getCenter().lng().toFixed(6)
+ "&zoom=" + map.getZoom()
+ "&type=" + MapTypeId2UrlValue(map.getMapTypeId());
if (lastmarker) {
var a = "/about/map/default.aspx?id=" + lastmarker.id + "&" + mapinfo;
var b = "/about/map/default.aspx?marker=" + lastmarker.index + "&" + mapinfo;
} else {
var a = "/about/map/default.aspx?" + mapinfo;
var b = a;
}
document.getElementById("idlink").innerHTML = '<a href="' + a + '" id=url target=_new>- Link directly to this page by id</a> (id in xml file also entry "name" in sidebar menu)';
document.getElementById("indexlink").innerHTML = '<a href="' + b + '" id=url target=_new>- Link directly to this page by index</a> (position in gmarkers array)';
}
function initialize() {
// create the map
var myOptions = {
zoom: zoom,
center: new google.maps.LatLng(lat, lng),
mapTypeId: maptype,
mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU },
navigationControl: true,
mapTypeId: google.maps.MapTypeId.HYBRID
};
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
var stylesarray = [
{
featureType: "poi",
elementType: "labels",
stylers: [
{ visibility: "off" }
]
},
{
featureType: "landscape.man_made",
elementType: "labels",
stylers: [
{ visibility: "off" }
]
}
];
var options = map.setOptions({ styles: stylesarray });
// Make the link the first time when the page opens
makeLink();
// Make the link again whenever the map changes
google.maps.event.addListener(map, 'maptypeid_changed', makeLink);
google.maps.event.addListener(map, 'center_changed', makeLink);
google.maps.event.addListener(map, 'bounds_changed', makeLink);
google.maps.event.addListener(map, 'zoom_changed', makeLink);
google.maps.event.addListener(map, 'click', function () {
lastmarker = null;
makeLink();
infowindow.close();
});
// 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].getAttribute("html");
var label = markers[i].getAttribute("label");
var icon = markers[i].getAttribute("icon");
// create the marker
var marker = createMarker(point, icon, label, html);
}
// put the assembled side_bar_html contents into the side_bar div
document.getElementById("side_bar").innerHTML = side_bar_html;
// ========= If a parameter was passed, open the info window ==========
if (id) {
if (idmarkers[id]) {
google.maps.event.trigger(idmarkers[id], "click");
} else {
alert("id " + id + " does not match any marker");
}
}
if (index > -1) {
if (index < gmarkers.length) {
google.maps.event.trigger(gmarkers[index], "click");
} else {
alert("marker " + index + " does not exist");
}
}
});
}
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150, 50)
});
google.maps.event.addDomListener(window, "load", initialize);
And here is an example of my XML formatting
<marker lat="42.196175"
lng="-121.699224"
html="This is the information about 104"
iconimage="/about/map/images/104.png"
label="104" />