function processZoomChange(oldzoom, zoom) {
	// Toggle overlays off if zooming too far out. Toggle them back on if zooming back in.
	// We toggle the display of the overlays checkboxes and store a list of those that are active for later re-activation if the user zooms back in.
	if ((zoom <= 13) && (oldzoom >13)) {
		//alert('Turning off overays.');
		document.getElementById('overlays').style.display = "none";
		gCU_overlays = new Array();
		gCU_overlays = getActiveOverlays().split(",");
		toggleOverlays(false);
	}
	if ((zoom > 13) && (oldzoom <=13)) {
		//alert('Turning on overays.');
		document.getElementById('overlays').style.display = "block";
		// Re-activate any overlays that were active before zooming out.
		toggleOverlays(true);
	}
	// Toggle building outlines off if zooming too far out. Toggle them back on if zooming back in.
	if ((zoom <= 13) && (oldzoom >13)) {
		//alert('Turning off building outlines.');
		map.removeOverlay(buildingShapes);
	}
	if ((zoom > 13) && (oldzoom <=13)) {
		//alert('Turning on building outlines.');
		map.addOverlay(buildingShapes);
	}
}

function processMapTypeChange() {
	// Hide building shapes overlay while in satellite or hybrid view, turn it back on if in map or terrain.
	//alert(map.getCurrentMapType().getName());
	var mapType = map.getCurrentMapType().getName();
	if ((mapType == "Satellite") || (mapType == "Hybrid")) {
		map.removeOverlay(buildingShapes);
	}
	else {
		map.addOverlay(buildingShapes);
	}
}

function getActiveOverlays() {
	// Detect which overlays are active and return a comma-separated list of them.
	var activeOverlays = "";
	var checkboxes = new Array();
	// Check points overlays.
	checkboxes = getElementsByClassName(document, "*", "overlayBox");
	for (var i=0; i<checkboxes.length; i++) {
		if (document.getElementById(checkboxes[i].id).checked) {
			activeOverlays += document.getElementById(checkboxes[i].id).id + ",";
		}
	}
	
	// Check lines overlays.
	checkboxes = getElementsByClassName(document, "*", "overlayBox2");
	for (var i=0; i<checkboxes.length; i++) {
		if (document.getElementById(checkboxes[i].id).checked) {
			activeOverlays += document.getElementById(checkboxes[i].id).id + ",";
		}
	}
	
	// Check combined points/lines overlays.
	checkboxes = getElementsByClassName(document, "*", "overlayBox3");
	for (var i=0; i<checkboxes.length; i++) {
		if (document.getElementById(checkboxes[i].id).checked) {
			activeOverlays += document.getElementById(checkboxes[i].id).id + ",";
		}
	}
	var trimRegExp = new RegExp(",$");
	activeOverlays = activeOverlays.replace(trimRegExp, "");
	return activeOverlays;
}

function makeURL() {
	// Generate a link for the current page, including named location and activated overlays.
	var URL = "http://www.cornell.edu/maps/interactive.cfm?loc=" + gCU_loc;
	URL += "&zoom=" + map.getZoom();
	var overlays = getActiveOverlays();
	if (overlays != "") {
		URL += "&overlays=" + overlays;
	}
	URL = URL.replace(/ /g, "%20");
	alert('Copy and paste this link to center, zoom, and overlay the map as shown below:\n\n' + URL);
}

function getElementsByClassName(oElm, strTagName, strClassName) {
	/* Written by Jonathan Snook, http://www.snook.ca/jonathan Add-ons by Robert Nyman, http://www.robertnyman.com */
	var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	var arrReturnElements = new Array();
	strClassName = strClassName.replace(/\-/g, "\\-");
	var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
	var oElement;
	for(var i=0; i<arrElements.length; i++){
		oElement = arrElements[i];
		if(oRegExp.test(oElement.className)){
			arrReturnElements.push(oElement);
		}
	}
	return (arrReturnElements)
}

function toggleOverlays(display) {
	// If an incoming parameter requests overlays to default as visible, activate them.
	// Also use this to show or hide overlays when the zoom level changes.
	var checkboxes = new Array();

	// Check points overlays.
	checkboxes = getElementsByClassName(document, "*", "overlayBox");
	for (var i=0; i<checkboxes.length; i++) {
		//alert(checkboxes[i].id);
		for (var j=0; j<gCU_overlays.length; j++) {
			if (gCU_overlays[j] == checkboxes[i].id) {
				document.getElementById(checkboxes[i].id).checked = display;
				toggleOverlay(display, checkboxes[i].id);
			}
		}
	}

	// Check lines overlays.
	checkboxes = getElementsByClassName(document, "*", "overlayBox2");
	for (var i=0; i<checkboxes.length; i++) {
		//alert(checkboxes[i].id);
		for (var j=0; j<gCU_overlays.length; j++) {
			if (gCU_overlays[j] == checkboxes[i].id) {
				document.getElementById(checkboxes[i].id).checked = display;
				toggleOverlay2(display, checkboxes[i].id);
			}
		}
	}

	// Check combined points/lines overlays.
	checkboxes = getElementsByClassName(document, "*", "overlayBox3");
	for (var i=0; i<checkboxes.length; i++) {
		//alert(checkboxes[i].id);
		for (var j=0; j<gCU_overlays.length; j++) {
			if (gCU_overlays[j] == checkboxes[i].id) {
				document.getElementById(checkboxes[i].id).checked = display;
				toggleOverlay(display, checkboxes[i].id);
				toggleOverlay2(display, checkboxes[i].id);
			}
		}
	}
}

function resetLocationList() {
	// Reset the location list to be the original default list and hide its reset link/button.
	document.getElementById("locationListItems").innerHTML = "";
	var newListItems = "<ul class=\"scrollingList\">";
	var mapinfo = new Array();
	for (var i = 0; i<places.length; i++) {
		mapinfo = places[i].split(':');
		newListItems += "<li><a href=\"#\" onclick=\"centerMap(" + i + ", 0)\">" + mapinfo[0] + "</a></li>";
	}
	newListItems += "</ul>";
	document.getElementById("locationListItems").innerHTML = newListItems;
	document.getElementById("resetLocationList").style.display = "none";
	document.getElementById("makeURL").style.display = "none";
}

function userSuggest() {
	// Open a window and allow users to suggest new places to add to the map.
	var formStr = "<html><head><title>Suggest a Cornell map addition</title></head><body>";
	formStr = formStr + '<p><strong>Suggest a Cornell map addition</strong></p>';
	formStr = formStr + '<form name="mapsuggestform" action="emailsuggestion.cfm" method="post">';
	formStr = formStr + '<label for="fromname">Your Name (optional): </label><input type="text" name="fromname" id="fromname" value=""/><br /><br />';
	formStr = formStr + '<label for="fromaddr">Your Email (optional): </label><input type="text" name="fromaddr" id="fromaddr" value=""/><br /><br />';
	formStr = formStr + '<label for="additionname">Name of addition: </label><input type="text" name="additionname" id="additionname" value=""/><br /><br />';
	formStr = formStr + '<label for="location">Location: </label><br /><textarea name="location" id="location" rows="12" cols="40"></textarea><br /><p>Enter a street address, a latitude/longitude datum, or a description that will help us place the addition on the map, or associate with a location we already list.</p>';
	formStr = formStr + '<br /><br />';
	formStr = formStr + '<input type="submit" value="Send"/>';
	formStr = formStr + '<br /><br /><br /><br />';
	formStr = formStr + '</form></body></html>';
	var mailWin = window.open("", "myWin", "width=450,height=600,scrollbar=auto");
	mailWin.document.write(formStr);
	mailWin.focus();
}

function getParameter( parameterName ) {
	var queryString = window.location.search.substring(1).toLowerCase();
	//alert(queryString);
	//if (queryString.length==0) {return "null";}
	var parameters = new Array();
	parameters = queryString.split('&');
	for(var i = 0; i < parameters.length; i++) {
		//alert(parameters[i]);
		//alert(parameters[i].indexOf(parameterName));
		if (parameters[i].indexOf(parameterName.toLowerCase())>=0) {
			//alert(parameters[i]);
			var parameterValue = new Array();
			parameterValue = parameters[i].split('=');
			return parameterValue[1];
		}
	}
	return "null";
}

parkingPointClosest = null;
parkingMarkerClosest = null;
infoPointClosest = null;
infoMarkerClosest = null;
closestParking1 = null;
closestParking0 = null;
closestInfo1 = null;
closestInfo0 = null;
function findClosestParking(locationName, locCoord1, locCoord2) {
	// Given coords, determine whether on campus, and if so find and display closest public parking location from our list of places.
	// Is location on campus (off-campus locations probably have closer parking that we don't track.
	var locPoint = new GLatLng(parseFloat(locCoord1), parseFloat(locCoord2));
	var closestParkingDistance = 999999;
	var closestInfoDistance = 999999;
	var closestParking = 0;
	var closestInfo = 0;
	// Remove old marker if one is present.
	if (parkingPointClosest != null) {
		map.removeOverlay(parkingMarkerClosest);
	}
	if (infoPointClosest != null) {
		map.removeOverlay(infoMarkerClosest);
	}
	destinationOnCampus = false;
	if (campusPoly.Contains(locPoint)) {
		destinationOnCampus = true;
		var mapinfo = new Array();
		var coords = new Array();
		var re = new RegExp(/Metered Parking/);
		// Find closest metered parking.
		for (var i=0; i<places.length; i++) {
			if (places[i].match(re)) {
				mapinfo = places[i].split(':');
				coords = mapinfo[1].split(',');
				var tempPt = new GLatLng(coords[1], coords[0]);
				var distance = tempPt.distanceFrom(locPoint);
				if (distance < closestParkingDistance) {
					closestParking1 = coords[1];
					closestParking0 = coords[0];
					closestParkingDistance = distance;
				}
			}
		}
		// Show closest metered parking point on the map, if the location is not an info booth or parking lot.
		if ((locationName.indexOf('Info Booth') == -1) && (locationName.indexOf('Parking') == -1)) {
			parkingPointClosest = new GLatLng(closestParking1, closestParking0);
			parkingMarkerClosest = new GMarker(parkingPointClosest,{title:mapinfo[0],icon:icons["Parking"]});
			map.addOverlay(parkingMarkerClosest);
		}
		var re = new RegExp(/Info Booth/);
		// Find closest info booth.
		for (var i=0; i<overlays.length; i++) {
			if (overlays[i].match(re)) {
				mapinfo = overlays[i].split(':');
				coords = mapinfo[1].split(',');
				var tempPt = new GLatLng(coords[1], coords[0]);
				var distance = tempPt.distanceFrom(locPoint);
				if (distance < closestInfoDistance) {
					closestInfo1 = coords[1];
					closestInfo0 = coords[0];
					closestInfoDistance = distance;
				}
			}
		}
		// Show closest info booth on the map, if the location is not an info booth or parking lot.
		if ((locationName.indexOf('Info Booth') == -1) && (locationName.indexOf('Parking') == -1)) {
			infoPointClosest = new GLatLng(closestInfo1, closestInfo0);
			infoMarkerClosest = new GMarker(infoPointClosest,{title:mapinfo[0],icon:icons["Info"]});
			map.addOverlay(infoMarkerClosest);
		}
	}
}

point = null;
marker = null;
function centerMap(loc, delay) {
	if (GBrowserIsCompatible()) {
		
		// The loc variable defaults to an array index, but it may be a string containing a room number at the beginning, such as 201 McGraw Hall. If it's a string, we need to determine the array index, checking both with and without a leading number, because the leading number might be a street address used in the array, such as 312 College Ave.
		// Also, try to match the name of a building without leading name or name's initials if possible; e.g., Frank H. T . Rhodes Hall should be the same as Rhodes Hall.
		
		// We accept a delay value in order to handle different calling conditions. We need to have a delay of some amount in order to ensure a smooth AJAX call/return, but the amount needed depends on whether we're receiving a polygon click or a location-list link click.
		
		// If we have a string, try to find an array item that matches it, and then get its index.
		if (typeof(loc) == "string") {
			var loc1 = loc;
			var loc2 = loc;
			loc2 = loc2.replace(/^P?\.? ?O?\.? ?Box \d+, /i, ""); // Remove PO box number if present.
			loc2 = loc2.replace(/^Main Floor, /i, ""); // Remove floor reference if present.
			loc2 = loc2.replace(/^Main Office, /i, ""); // Remove office reference if present.
			loc2 = loc2.replace(/^[A-Z]?\d?\-?\d+[A-Z]? /i, ""); // Remove office numbers, which can vary a lot.
			var temp = new Array();
			for (var i=0; i<places.length; i++) {
				temp = places[i].split(':');
				var tempName = temp[0];
				if ((tempName == loc1) || (tempName == loc2) || (tempName.indexOf(loc1) > -1) || (tempName.indexOf(loc2) > -1) || (loc1.indexOf(tempName) > -1) ||(loc2.indexOf(tempName) > -1)) {
					loc = i;
				}
			}
		}
		if (typeof(loc) == "string") {
			alert('Could not find places index for ' + loc + '\n\nloc1: ' + loc1 + '\n\nloc2: ' + loc2);
		}
		else {
			// Pan to and then center the map on a specific location.
			var mapinfo = new Array();
			mapinfo = places[loc].split(':');
			var locationName = mapinfo[0];
			
			// Activate widget for makings a URL once a location has been selected.
			gCU_loc = locationName; // Set global variable with location name, for use in generating a link to the current map.
			document.getElementById("makeURL").style.display = "inline";	
	
			// Dynamically fetch content for units in this location via AJAX.
			document.getElementById('bubbleTextContents').innerHTML = "";
			generateBubbleText(mapinfo[0]);

			var coords = new Array();
			coords = mapinfo[1].split(',');
			var center = new GLatLng(coords[1], coords[0]);
			map.panTo(center, 500);
			
			// Determine distance between the specific point and Day Hall. If greater than about 10 miles, set a larger zoom for better context.
			var DayHall = new GLatLng(parseFloat(42.4457), parseFloat(-76.4814));
			var distance = center.distanceFrom(DayHall);
			
			// Set the zoom level default but adjust if site is far away from campus, unless a param overrides.
			var zoom = 16;
			if (gCU_zoom > 0) {
				zoom = gCU_zoom;
			}
			if (distance > 15000) {
				zoom = 10;
				if (gCU_zoom > 0) {
					zoom = gCU_zoom;
				}
			}
			setTimeout('map.setZoom(' + parseInt(zoom) + ')', 1000);

			// Add a point marker for the location.
			if (point != null) {
				map.removeOverlay(marker);
			}
			point = new GLatLng(coords[1],coords[0]);
			marker = new GMarker(point,{title:mapinfo[0]});
			map.addOverlay(marker);
			findClosestParking(mapinfo[0], coords[1] ,coords[0]);
	
			// We need a delay here while waiting for AJAX to complete its fetch.
			// There should be enough going on with the pan and zoom that the user experiences no apparent delay.
			delay = delay + parseInt(2000);
			setTimeout('addBubbleText("'+locationName+'",'+coords[1]+','+coords[0]+')', delay);
			delay = delay + parseInt(500);
			setTimeout('marker.openInfoWindowTabsHtml(infoTabs)', delay);
//			delay = delay + parseInt(500);
//			setTimeout('updateTab()', delay);
		}
	}
}

function updateTab(){
	// Update the tab so that it redraws to fit its content. This addresses a problem in IE.
	map.updateCurrentTab(function(currentTab){currentTab.contentElem.innerHTML = "<div style='height:400px; width:300px; border:1px solid red;'>Test test test</div>";})
};

function addBubbleText(locationName, parkingLat, parkingLng) {
	// Create the text that will appear in the info bubble for the location's map marker.
	// The reference to driving directions varies according to the site, particularly with respect to providing them to the nearest parking area or to the location itself.
	boxtext = "<div class='infowindow'><p><strong>"+locationName+"</strong><br />";
	boxtext += document.getElementById('bubbleTextDirections').innerHTML;
	boxtext += "</p>" +
	'<form action="http://maps.google.com/maps" method="get" name="bubbleDir">' +
	'<p>Driving directions to';
	// Show choice of driving directions to the location, the nearest metered parking, or the nearest info booth if the location is on campus and not a parking space or info booth, else show route to the location (parking and info booths are to themselves).
	if ((destinationOnCampus) && (locationName.indexOf('Info Booth') == -1) && (locationName.indexOf('Parking') == -1)) {
	boxtext += ': <br /><input type="radio" name="dir" value="loc" onfocus="document.bubbleDir.daddr.value=\''+parkingLat+','+parkingLng+'\'" checked="checked"/>this location <br />' +
	'<input type="radio" name="dir" value="park" onfocus="document.bubbleDir.daddr.value=\''+closestParking1+','+closestParking0+'\'"/>closest metered parking <br />' +
	'<input type="radio" name="dir" value="info" onfocus="document.bubbleDir.daddr.value=\''+closestInfo1+','+closestInfo0+'\'"/>closest information booth <br />';
	}
	else {
		boxtext += ' this location ';
	}
	boxtext += '</p>' +
	'<p><strong>From:</strong>&nbsp;<input type="text" name="saddr" id="saddr" value="enter starting address here" size="40" onfocus="JavaScript:this.value=\'\'" /></p>' +
	'<input type="hidden" name="daddr" id="daddr" value="'+parkingLat+','+parkingLng+'" />' +
	'<input type="submit" value="Continue" />' +
	'</form>';
	boxtext += "</div>";
	infoTabs = new Array();
	//alert(boxtext);
	infoTabs.push(new GInfoWindowTab("Directions", boxtext));
	
	var contentsTab = document.getElementById('bubbleTextContents').innerHTML;
	contentsTab = "<div class='infowindow'>" + contentsTab + "</div>";
	if (contentsTab.indexOf("What's here") > -1) {
		//alert(contentsTab);
		infoTabs.push(new GInfoWindowTab("Contents", contentsTab));
	}
	
	phototext = "<div class='infowindow'>";
	phototext += "<img src=\"http://www.cornell.edu/maps/insignia.jpg\" width=\"200\" height=\"200\" alt=\"Cornell University insignia\"/>";
	phototext += "</div>";
	//alert(phototext);
	infoTabs.push(new GInfoWindowTab("Photo", phototext));

	GEvent.addListener(marker, "click", function() {
		marker.openInfoWindowTabsHtml(infoTabs);
	});
}


function loadIcons() {
	// Load different icons for various features.
	var iconData = new Array();
	iconData[0] = "Parking,32,32";
	iconData[1] = "Dining,32,32";
	iconData[2] = "Cafe,32,32";
	iconData[3] = "Housing,32,32";
	iconData[4] = "Info,32,32";
	iconData[5] = "Greek,34,34";
	iconData[6] = "TCAT,32,32";
	iconData[7] = "Library,32,32";
	iconData[8] = "Tour,32,32";
	iconData[9] = "Blue,32,32";
	iconData[10] = "Lactation,32,32";
	iconData[11] = "Diaper,32,32";
	iconData[12] = "Carshare,30,29";
	iconData[13] = "Bike,32,32";
	iconData[14] = "Access,32,32";
	iconData[15] = "Invis,32,32";
	iconData[16] = "East Hill Shuttle,32,32";
	
	icons = new Array();
	var temp = new Array();
	for (var i=0; i<iconData.length; i++) {
		temp = iconData[i].split(',');
		var name = temp[0];
		var width = Math.round(temp[1]*.75);
		var height = Math.round(temp[2]*.75);
		var filename = name.toLowerCase();
		filename = filename.replace(/ /g, "");
		icons[name] = new GIcon();
		icons[name].image = "http://www.cornell.edu/maps/icons/"+filename+".png";
		icons[name].shadow = null;
		icons[name].iconSize = new GSize(width, height);
		icons[name].iconAnchor = new GPoint(Math.round(width/2), Math.round(height/2));
	}
}

function toggleOverlay3(display, overlay) {
	//alert(overlay);
	// Swap the main set of building overlays and/or place it on top of the default one.
	if (overlay == "RedRover") {
		if (display) {
			// This filename has to be updated when changed, to force a new cache on Google's end.
			redroverShapes = new GGeoXml("http://www.cornell.edu/maps/Red_Rover20090422.kml"); 
			map.addOverlay(redroverShapes);
		}
		else {
			map.removeOverlay(redroverShapes);
		}
	}
}

paths = new Array();
function toggleOverlay2(display, pathType) {
	//alert(pathType);
	// Show or hide a specific set of paths.
	var mapinfo = new Array();
	var points = new Array();
	var coords = new Array();
	var vertices = new Array();
	var colors = new Array();
	colors[0] = "#660099"; // Purple
	colors[1] = "#00FF00"; // Green
	colors[2] = "#0000FF"; // Blue
	colors[3] = "#FF00FF"; // Magenta
	//colors[4] = "#FFFF00"; // Yellow
	colors[4] = "#00FFFF"; // Cyan
	var colorCount = 0;
	
	var re = new RegExp(pathType);
	for (var p=0; p<overlays.length; p++) {
		if (overlays[p].match(re)) {
			vertices = [];
			mapinfo = overlays[p].split(':');
			points = mapinfo[1].split(' ');
			for (var i=0; i<points.length; i++) {
				coords = points[i].split(',');
				if ((typeof(coords[1]) != "undefined") && (typeof(coords[0]) != "undefined")) {
					var newpoint = new GLatLng(coords[1], coords[0]);
					vertices.push(newpoint);
				}
			}
			if (display) {
				var color = colors[colorCount];
				var thickness = 2;
				if (pathType == "Closed Roads") {
					color = "#888888";
					thickness = 3;
				}
				paths[p] = new GPolyline(vertices, color, thickness, 1);
				map.addOverlay(paths[p]);
				//alert(colors[colorCount]);
				colorCount++;
			}
			else {
				map.removeOverlay(paths[p]);
			}
		}
	}
}

markers = new Array();
markersOverlay = new Array();
markersTour = new Array();
function toggleOverlay(display, placeType) {
	// Show or hide a specific set of points.
	var mapinfo = new Array();
	var coords = new Array();
	var ID = "";
	
	if (placeType == "TCAT") {
		for (var i=0; i<TCATStops.length; i++) {
			ID = placeType + i;
			if (display) {
				mapinfo = TCATStops[i].split(':');
				coords = mapinfo[1].split(',');
				var point = new GLatLng(coords[1], coords[0]);
				markers[ID] = new GMarker(point,{title:mapinfo[0],icon:icons[placeType]});
				map.addOverlay(markers[ID]);
			}
			else {
				map.removeOverlay(markers[ID]);
			}
		}
	}
	else if (placeType == "Tour") {
		for (var i=0; i<TourPoints.length; i++) {
			mapinfo = TourPoints[i].split(':');
			ID = mapinfo[3];
			coords = mapinfo[1].split(',');
			if (display) {
				var point = new GLatLng(coords[1], coords[0]);
				markersTour[ID] = new GMarker(point,{title:mapinfo[0],icon:icons[placeType]});
				// Add info window with tiny pano.
				var btext = showPano(mapinfo[0], 'Small', ID);
				panoClick(ID, btext);
				map.addOverlay(markersTour[ID]);
			}
			else {
				map.removeOverlay(markersTour[ID]);
			}
		}
	}
	else {
		//var re = new RegExp(placeType);
		for (var i=0; i<places.length; i++) {
			ID = placeType + i;
			if (places[i].indexOf(placeType) > -1) {
				if (display) {
					mapinfo = places[i].split(':');
					coords = mapinfo[1].split(',');
					var point = new GLatLng(coords[1], coords[0]);
					markers[ID] = new GMarker(point,{title:mapinfo[0],icon:icons[placeType]});
					map.addOverlay(markers[ID]);
				}
				else {
					map.removeOverlay(markers[ID]);
				}
			}
		}
		for (var i=0; i<overlays.length; i++) {
			ID = placeType + i;
			if (overlays[i].indexOf(placeType) > -1) {
				if (display) {
					mapinfo = overlays[i].split(':');
					coords = mapinfo[1].split(',');
					var point = new GLatLng(coords[1], coords[0]);
					markersOverlay[ID] = new GMarker(point,{title:mapinfo[0],icon:icons[placeType]});
					map.addOverlay(markersOverlay[ID]);
				}
				else {
					map.removeOverlay(markersOverlay[ID]);
				}
			}
		}
	}
}

function panoClick(ID, btext) {
	// Add the HTML into the pano node's text bubble.
	// For some unknown reason, this single statement does not work unless used in its own function.
	// Including it in the location whence it's called results in an error: the indexed array for the marker is undefined, even though it's global.
	GEvent.addListener(markersTour[ID], "click", function() {markersTour[ID].openInfoWindowHtml(btext);});
	//GEvent.addListener(markersTour[ID], "click", function() {markersTour[ID].openInfoWindowHtml(btext,{onOpenFn:fetchSmallQTVR(ID)});});
}

function loadPano(ID, size) {
	window.open('http://www.cornell.edu/tours/qtvrs.cfm?format=html&id='+ID+'&size='+size, 'mywindow', 'width=512,height=384');
}

function showPano(nodeTitle, panoSize, ID) {
	foundQuickTime = true;
	if (getQuicktimeVersion() < 4) {
		foundQuickTime = false;
	}
	//var filename = nodeTitle.toLowerCase();
	var filename = nodeTitle;
	filename = filename.replace(/ - /g, "-");
	filename = filename.replace(/\./g, "");
	filename = filename.replace(/ /g, "_");
	panoHTML = "";
	panoHTML += '<div style="width: 270px; height: 230px; text-align: center;"><br />';
	if (foundQuickTime) {
		panoHTML += qtvrEmbed[ID];
		panoHTML += '<p><a href="#" onclick="loadPano(\''+ID+'\', \'L\')">Full-screen, high-res</a> | ';
		panoHTML += '<a href="#" onclick="loadPano(\''+ID+'\', \'M\')">Medium-size</a></p>';
	}
	else {
		panoHTML += "<p>QuickTime is needed to view this immersive panorama. You may <a href=\"http://www.apple.com/quicktime/download/\">download QuickTime</a> for free from Apple.</p>";
	}
	panoHTML += '</div>';
	return panoHTML;
}

gmarkers = new Array();
function loadMap(locStr) {
	if (GBrowserIsCompatible()) {
		// If a specific place name was specified (in the URL from the referring page), then show 
		// it centered on the map at a close zoom, otherwise default to showing the whole campus 
		// zoomed out.
		//var locStr = getParameter('locStr');
		if ((locStr == "") || (locStr == null) || (locStr == "null")) {locStr = "Day Hall";}
		var loc = 0;
		for (var i=0; i<places.length; i++) {
			var locData = places[i].split(':');
			if (locData[0] == locStr) {
				loc = i;
			}
		}
		
		var mapinfo = new Array();
		mapinfo = places[loc].split(':');
		var coords = new Array();
		coords = mapinfo[1].split(',');
		
		//map = new GMap2(document.getElementById("map"), {size: new GSize(520, 460)});
		map = new GMap2(document.getElementById("CUmap"));
		var CUzoom = 15;
		if (gCU_zoom > 0) {
			CUzoom = gCU_zoom;
		}
		//map.setCenter(new GLatLng(coords[1],coords[0]), parseInt(CUzoom));
		map.setCenter(new GLatLng(42.449191,-76.480138), parseInt(CUzoom));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.addControl(new GScaleControl());
		map.enableScrollWheelZoom();
		map.addMapType(G_PHYSICAL_MAP);
		defineCampus();
		defineBuildingCodes();
		loadIcons();
		GEvent.addListener(map, "zoomend", function(oldzoom, zoom) {processZoomChange(oldzoom, zoom);}); 
		GEvent.addListener(map, "maptypechanged", function() {processMapTypeChange();}); 
		
		// This filename has to be updated when changed, to force a new cache on Google's end.
		buildingShapes = new GGeoXml("http://www.cornell.edu/maps/CampusPolygons20091017.kml"); 
		map.addOverlay(buildingShapes);
		
		//	for (building in buildings) { 
		//          var polygon = createPoly(building);
		//          map.addOverlay(polygon);
		//	}
		
		// Add markers for all buildngs so that we get rollover labels and can click on them to see their contents.
		for (var i=0; i<places.length; i++) {
			var mapinfo = places[i].split(':');
			var coords = mapinfo[1].split(',');
			if (mapinfo[0].indexOf("Parking at") == -1) {
				var gpoint = new GLatLng(coords[1], coords[0]);
				gmarkers[i] = new GMarker(gpoint,{title:mapinfo[0],icon:icons['Invis']});
				//GEvent.addListener(gmarkers[i], "click", function() {gmarkers[i].alert(mapinfo[0]);})
				map.addOverlay(gmarkers[i]);
			}
		}
		addListeners();
		toggleOverlay2(true, "Closed Roads");
		toggleOverlays(true);
	}
	//else {
	//	document.location.replace("http://www.csun.edu/maps/cm1.html");
	//}
}

function addListeners() {
	// Add click listeners for polygon centers.
	// See http://groups.google.com/group/Google-Maps-API/browse_thread/thread/7613ba04a7b4555d to be sure to include point's details.
	for (var i=0; i<gmarkers.length; i++) {
		var mapinfo = places[i].split(':');
		var coords = mapinfo[1].split(',');
		myAddListener(gmarkers[i], mapinfo[0]);
	}
}

function myAddListener(gmarker, info) {
	// Add an individual polygon's listener.
	//GEvent.addListener(gmarker, "click", function() {alert(info);});
	try {
		GEvent.addListener(gmarker, "click", function() {searchMaps(info, 0);});
	}
	catch(err) {
		//alert(info);
		//alert(err.description);
	}
}

function createPoly(building) {
	var polygon = new GPolygon(buildings[building], "#CCCCCC", 1, 1, "#888888", 0.5);
	GEvent.addListener(polygon, "click", function(latlng) {
			map.openInfoWindow(latlng, "You clicked " + building);
	});
	GEvent.addListener(polygon, "mouseover", function(latlng) {
			map.openInfoWindow(latlng, "You moused over " + building);
	});
	return polygon;
}

function searchMaps(searchTerm, updateLocationList) {
	// Find a list of items matching a search. Resulting value is HTML to be substituted into the right-side list of campus places.
	
	document.getElementById("locationListItems").innerHTML = "<p><img src=\"loading.gif\" alt=\"\" /></p>";
	
	// If search term is exactly three characters long, search through building codes.
	if (searchTerm.length == 3) {
		var code = searchTerm.toUpperCase();
		if (typeof(buildingCodes[code]) != "undefined") {
			searchTerm = buildingCodes[code];
			//alert(searchTerm);
		}
	}
	
	// Search through internal array of buildings to match them to the search term.
	var re = new RegExp(searchTerm, "i");
	newInnerHTML = "";
	var numHits = 0;
	var firstHit = 0;
	for (var i=0; i<places.length; i++) {
		if (places[i].match(re)) {
			mapinfo = places[i].split(':');
			coords = mapinfo[1].split(',');
			if (mapinfo[0] != "Untitled Placemark") {
				newInnerHTML += '<li><a href="##" onclick="centerMap('+i+', 0)">'+mapinfo[0]+'</a></li>';
				numHits++;
				if (numHits == 1) {
					firstHit = i;
				}
			}
		}
	}
	
	// Call search script via AJAX to look at units database as well as internal JavaScript location list.
	searchResults = "";
	generateLocationList(document.getElementById("searchMaps").value);
	// Update the location list only if returning from a true search, not when returning from a polygon click.
	if (updateLocationList == 1) {
		setTimeout('showUnitSearchResults('+numHits+', '+firstHit+')', 1000);
	}
	else {
		centerMap(firstHit, 250);
	}
}

function showUnitSearchResults(numHits, firstHit) {
	if (searchResults.indexOf('<li>') >= 0) {
		newInnerHTML += searchResults;
	}
	if (newInnerHTML != "") {
		document.getElementById("locationListItems").innerHTML = "<ul class=\"scrollingList\">"+newInnerHTML+"</ul>";
		// Show a link to reset the search results list.
		document.getElementById("resetLocationList").style.display = "inline";	
		document.getElementById("makeURL").style.display = "inline";	
	}
	else {
		//alert("Found no locations matching " + document.getElementById("searchMaps").value + ".");
		document.getElementById("locationListItems").innerHTML = "<ul class=\"scrollingList\"><li>Found no results for \""+document.getElementById("searchMaps").value+"\".</li></ul>"
		document.getElementById("resetLocationList").style.display = "inline";	
	}
	if (numHits == 1) {
		centerMap(firstHit, 0);
	}
}


function generateLocationList(searchTerm) {
	// Search database of Cornell units and show the buildings in which they're located.
	var url = "search-maps.cfm?action=&searchTerm="+searchTerm;
	url = url + "&dummy=" + new Date().getTime();
	//alert(url);
	request.open("GET", url, true);
	request.onreadystatechange = updateLocationList;
	request.send(null);
}

function updateLocationList() {
	if (request.readyState == 4) {
		if (request.status == 200) {
			//alert(request.responseText);
			searchResults = request.responseText.replace(/^\s+/g, "");;
			//alert(document.getElementById('locationListItems').innerHTML);
		} 
		else {
			var message = request.getResponseHeader("Status");
			if ((message == null) || (message.length == null) || (message.length <= 0)) {
				//alert("Error! Request status is " + request.status + ".");
			} 
			else {
				//alert(message);
			}
			//alert(url);
		}
	}
}

function generateBubbleText(location) {
	// Search database of Cornell units and show them in the location's info bubble.
	var url = "search-maps.cfm?action=bubble&location="+location;
	url = url + "&dummy=" + new Date().getTime();
	//alert(url);
	request.open("GET", url, true);
	request.onreadystatechange = updateBubbleText;
	request.send(null);
}

function updateBubbleText() {
	if (request.readyState == 4) {
		if (request.status == 200) {
			//alert(request.responseText);
			document.getElementById('bubbleTextContents').innerHTML = request.responseText.replace(/^\s+/g, "");
		} 
		else {
			var message = request.getResponseHeader("Status");
			if ((message == null) || (message.length == null) || (message.length <= 0)) {
				//alert("Error! Request status is " + request.status + ".");
			} 
			else {
				//alert(message);
			}
			//alert(url);
		}
	}
}

// AJAX stuff.
var request = null;
try {
	request = new XMLHttpRequest();
} catch (trymicrosoft) {
	try {
		request = new ActiveXObject("Msxml2.XMLHTTP");
	} catch (othermicrosoft) {
		try {
			request = new ActiveXObject("Microsoft.XMLHTTP");
		} catch (failed) {
			request = null;
		}
	}
}

if (request == null) {
	//alert("Error creating request object!");
	var x = 1; // dummy line
}

function submitEnter(myfield,e) {
	// Detect enter key being pressed to execute search.
	// From http://www.htmlcodetutorial.com/forms/index_famsupp_157.html
	var keycode;
	if (window.event) keycode = window.event.keyCode;
	else if (e) keycode = e.which;
	else return true;
	
	if (keycode == 13) {
		searchMaps(document.getElementById('searchMaps').value, 1);
		return false;
	}
	else {
		return true;
	}
}




// Quicktime Detection  v1.0
// documentation: http://www.dithered.com/javascript/quicktime_detect/index.html
// license: http://creativecommons.org/licenses/by/1.0/
// code by Chris Nott (chris[at]dithered[dot]com)

var quicktimeVersion = 0;
function getQuicktimeVersion() {
	var agent = navigator.userAgent.toLowerCase(); 
	
	// NS3+, Opera3+, IE5+ Mac (support plugin array):  check for Quicktime plugin in plugin array
	if (navigator.plugins != null && navigator.plugins.length > 0) {
      for (i=0; i < navigator.plugins.length; i++ ) {
         var plugin =navigator.plugins[i];
         if (plugin.name.indexOf("QuickTime") > -1) {
            quicktimeVersion = parseFloat(plugin.name.substring(18));
         }
      }
	}
   
	// IE4+ Win32:  attempt to create an ActiveX object using VBScript
	else if (agent.indexOf("msie") != -1 && parseInt(navigator.appVersion) >= 4 && agent.indexOf("win")!=-1 && agent.indexOf("16bit")==-1) {
	  document.write('<scr' + 'ipt language="VBScript"\> \n');
		document.write('on error resume next \n');
		document.write('dim obQuicktime \n');
		document.write('set obQuicktime = CreateObject("QuickTimeCheckObject.QuickTimeCheck.1") \n');
		document.write('if IsObject(obQuicktime) then \n');
		document.write('   if obQuicktime.IsQuickTimeAvailable(0) then \n');
		document.write('      quicktimeVersion = CInt(Hex(obQuicktime.QuickTimeVersion) / 1000000) \n');
		document.write('   end if \n');
		document.write('end if \n');
		document.write('</scr' + 'ipt\> \n');
  }

	// Can't detect in all other cases
	else {
		quicktimeVersion = quicktimeVersion_DONTKNOW;
	}

	return quicktimeVersion;
}

quicktimeVersion_DONTKNOW = -1;

function defineCampus() {
	// Define a polygon of main campus, to be used to determine whether a location is inside it when showing closest public parking space.
	// While it is possible to define this polygon in a KML file, loading the KML file via GGeoXml does not result in obtaining a polygon that can be handled as an object unless a third-party script is used (http://econym.googlepages.com/egeoxml.htm).
	campusPolyPoints = new Array();
	campusPolyPoints[0] = new GLatLng(parseFloat(42.44923319939294), parseFloat(-76.49040622077894));
	campusPolyPoints[1] = new GLatLng(parseFloat(42.44749551447904), parseFloat(-76.49038465780161));
	campusPolyPoints[2] = new GLatLng(parseFloat(42.44561338661595), parseFloat(-76.48999759065072));
	campusPolyPoints[3] = new GLatLng(parseFloat(42.44500601897025), parseFloat(-76.48919139010211));
	campusPolyPoints[4] = new GLatLng(parseFloat(42.446418083132), parseFloat(-76.48749217009399));
	campusPolyPoints[5] = new GLatLng(parseFloat(42.4458994383202), parseFloat(-76.48605669824109));
	campusPolyPoints[6] = new GLatLng(parseFloat(42.44320940503714), parseFloat(-76.48514813033701));
	campusPolyPoints[7] = new GLatLng(parseFloat(42.44312148458147), parseFloat(-76.4808768663423));
	campusPolyPoints[8] = new GLatLng(parseFloat(42.44297721981287), parseFloat(-76.47814688453994));
	campusPolyPoints[9] = new GLatLng(parseFloat(42.44347594689156), parseFloat(-76.47547172218755));
	campusPolyPoints[10] = new GLatLng(parseFloat(42.44407826228719), parseFloat(-76.47347802685796));
	campusPolyPoints[11] = new GLatLng(parseFloat(42.44377666653718), parseFloat(-76.47103700416872));
	campusPolyPoints[12] = new GLatLng(parseFloat(42.44269954570201), parseFloat(-76.46953526346094));
	campusPolyPoints[13] = new GLatLng(parseFloat(42.44370256318714), parseFloat(-76.46139413694144));
	campusPolyPoints[14] = new GLatLng(parseFloat(42.44674407426825), parseFloat(-76.4608831260106));
	campusPolyPoints[15] = new GLatLng(parseFloat(42.44773794633294), parseFloat(-76.46173722111445));
	campusPolyPoints[16] = new GLatLng(parseFloat(42.44927969053899), parseFloat(-76.46347893858906));
	campusPolyPoints[17] = new GLatLng(parseFloat(42.4500039887334), parseFloat(-76.4650102955699));
	campusPolyPoints[18] = new GLatLng(parseFloat(42.45335155621223), parseFloat(-76.46828257927373));
	campusPolyPoints[19] = new GLatLng(parseFloat(42.45524769441009), parseFloat(-76.47034282628331));
	campusPolyPoints[20] = new GLatLng(parseFloat(42.45807729490416), parseFloat(-76.47177451622082));
	campusPolyPoints[21] = new GLatLng(parseFloat(42.45895463031213), parseFloat(-76.47520087486095));
	campusPolyPoints[22] = new GLatLng(parseFloat(42.45888136904116), parseFloat(-76.47923703219217));
	campusPolyPoints[23] = new GLatLng(parseFloat(42.45891354512717), parseFloat(-76.48053886532657));
	campusPolyPoints[24] = new GLatLng(parseFloat(42.45866252045583), parseFloat(-76.48178067108066));
	campusPolyPoints[25] = new GLatLng(parseFloat(42.45792235978141), parseFloat(-76.48192226721285));
	campusPolyPoints[26] = new GLatLng(parseFloat(42.45640182314867), parseFloat(-76.48131993998594));
	campusPolyPoints[27] = new GLatLng(parseFloat(42.45567164809673), parseFloat(-76.48099166655136));
	campusPolyPoints[28] = new GLatLng(parseFloat(42.45469379298686), parseFloat(-76.48084964199872));
	campusPolyPoints[29] = new GLatLng(parseFloat(42.45408533830001), parseFloat(-76.48077640046668));
	campusPolyPoints[30] = new GLatLng(parseFloat(42.45333652864306), parseFloat(-76.48100984522794));
	campusPolyPoints[31] = new GLatLng(parseFloat(42.45236915935953), parseFloat(-76.48134274950799));
	campusPolyPoints[32] = new GLatLng(parseFloat(42.4513537382696), parseFloat(-76.48215407600821));
	campusPolyPoints[33] = new GLatLng(parseFloat(42.45134116965075), parseFloat(-76.48264700364528));
	campusPolyPoints[34] = new GLatLng(parseFloat(42.45142515258371), parseFloat(-76.48353238092739));
	campusPolyPoints[35] = new GLatLng(parseFloat(42.45128184669465), parseFloat(-76.48475450637719));
	campusPolyPoints[36] = new GLatLng(parseFloat(42.45122801547301), parseFloat(-76.48562448669836));
	campusPolyPoints[37] = new GLatLng(parseFloat(42.45119577021159), parseFloat(-76.48650277731805));
	campusPolyPoints[38] = new GLatLng(parseFloat(42.4508199599135), parseFloat(-76.48682800642786));
	campusPolyPoints[39] = new GLatLng(parseFloat(42.45032244124457), parseFloat(-76.48713737555191));
	campusPolyPoints[40] = new GLatLng(parseFloat(42.44982483764933), parseFloat(-76.48733572765832));
	campusPolyPoints[41] = new GLatLng(parseFloat(42.44942171488979), parseFloat(-76.48795391987696));
	campusPolyPoints[42] = new GLatLng(parseFloat(42.44921797579579), parseFloat(-76.488904669601));
	campusPolyPoints[43] = new GLatLng(parseFloat(42.44923319939294), parseFloat(-76.49040622077894));
	campusPoly = new GPolygon(campusPolyPoints, "##000000" , 0, 0, "##FFFFFF", 0, {clickable:false});
	map.addOverlay(campusPoly);
}


