function addMarkerWindow(html, place) {
	var point = null;
	if (PEnvironment.pageName == 'report_area') {
		clearPolygons(map);

		if (place instanceof PPlace) {
			map.setCenterBounds(place.getBounds());
			point = place.getBounds().getCenter();
			var polygons = place.getVertices();
			if (polygons && currentReport.areaType != "custom")
				addPolygons(map, place);
			search.currentplace = place;
		} else {
			search.currentplace = place;
			map.setCenter(place, 13);
			point = place;
		}

		map.openInfoWindow(point, html);
	} else {
		var addr = null;
		clearPolygons(map);

		if (place instanceof PPlace) {
			// HACK: This kludge exists to prevent the map from zooming all the way
			// out to show the entirity of the United States (including Hawaii and
			// Alaska). We just want to zoom and center on the lower 48 states.
			// This is hit when the user searches for the United States.
			if(place && place.getIdentifier() == "US") {
				// Place is the United States.
				point = new PLatLng(USA_LAT, USA_LNG);
				map.setCenter(point, USA_ZOOM);
			} else {
				map.setCenterBounds(place.getBounds());
				var centroid = place.getCentroid();
				if (centroid)
					point = centroid;
				else
					point = place.getBounds().getCenter();
			}
			var polygons = place.getVertices();
			if (polygons)
				addPolygons(map, place);
			mapstates.currentplace = place;
			map.infoWindowType = 'place';
			map.openInfoWindow(point, html);
		} else {
			map.setCenter(place, 13);
			point = place;
			mapstates.currentplace = null;
			addr = html.replace(/\<[^\>]+\>/g, "");

			var link;
			// Check if we're in the Dataloader.
			if(PEnvironment.pageName == "dataloader") {
				// We are. Display a link to create a site here
				// if a site creator is currently running.
				link = generateCreateSiteLink(point.lat(), point.lng(), addr);
			} else {
				// We're not. Add a "See Report" link.
				link = generatePointReportLink(null, null, addr);
			}
			var div = document.createElement('div');
			div.className = "similarresults";
			div.innerHTML = html;
			div.appendChild(link);
			if (PEnvironment.pageName != "embedmap_dyn") {
				var clear = document.createElement('a');
				clear.innerHTML = "Clear Point";
				$(clear).css({marginTop:"3px",display:"block"});
				PEvent.addListener(clear, 'mousedown', function() {
					session2.remove('lng');
					session2.remove('lat');
					session2.remove('place');
					map.removeOverlay(map.currentAddressMarker);
					map.closeInfoWindow();
				});
				div.appendChild(clear);
			}
			html = div;
			map.infoWindowType = 'address';
			var marker = new PMarker(point, PIcon.PMap);
			map.addOverlay(marker);
			if (map.currentAddressMarker)
				map.removeOverlay(map.currentAddressMarker);
			map.currentAddressMarker = marker;
			marker.openInfoWindow(html);
			PEvent.addListener(marker, 'click', function() {
				marker.openInfoWindow(html);
			});
		}

		// add to map state list
		if (mapstates && PMapState)
			mapstates.add(new PMapState(map.getCenter(), map.getZoom(), map.getIndicator(), null, mapstates.currentplace, addr));
	}
}

function loadDelayCheck(val) {
	var initWidgetRank;
	if (loaddelaytotal) {
		if (loaddelaycount == loaddelaytotal) {
			map.disableLoadDelay();
			initWidgetRank = true;
		}
		if (loaddelaycount <= loaddelaytotal)
			loaddelaycount++;
	}

	// when everything is done loading, or if nothing had to be loaded then we can set up the rankings
	// ranking feature will only get added to the widget if the ranking parameter is set in the url
	if (PEnvironment.pageName == 'widget' && (!loaddelaytotal || initWidgetRank)) {
			initWidgetRankings();
	}

	map.refresh();
	if(PEnvironment.pageName == 'analytics'){
		mapRefreshed();
	}
}

function closeCubeWindow() {
	var c = document.getElementById("identifyContainer");
	if (c && c.showsCube) {
		map.closeInfoWindow();
	}
}

// Generate the Report Link for Points
function generatePointReportLink(lat, lng, address) {
	var reportLinkHolder = document.createElement('div');

	// Return an empty element for the widget/embedded map
	if(isWidgetOrEmbedMap() || PEnvironment.pageName == "report_generate")
		return reportLinkHolder;

	$(reportLinkHolder).addClass('point_report_link_holder');
	$(reportLinkHolder).addClass('info_extra_link');

	var reportLink = document.createElement('a');
	if(isSubscriber()) {
		if(address) {
			reportLink.innerHTML = "See Report";
			var url = "reports?area=radius&location=" + address;
		} else {
			reportLink.innerHTML = "See Radius Report";
			var url = "reports?area=radius&lat=" + lat + "&lng=" + lng;
			var overlaySets = map.getOverlaySets();
			dids = [];
			dldids = [];
			for(var i=0; i<overlaySets.length; ++i) {
				if(overlaySets[i].id) {
					if(overlaySets[i].type && overlaySets[i].type == "dl") {
						dldids.push(overlaySets[i].id);
					} else {
						dids.push(overlaySets[i].id);
					}
				}
			}
			if(dids.length > 0) {
				url += "&did=" + dids.join(',');
			}
			if(dldids.length > 0) {
				url += "&dldid=" + dldids.join(',');
			}
		}
		PEvent.addListener(reportLink, "click", function() {
			window.location = url;
		});
	} else {
		reportLink.innerText = "To see a report for the area around the address you've selected, susbcribe now.";
		PEvent.addListener(reportLink, "click", function() {
			window.location = "/subscribe";
		});
	}
	$(reportLinkHolder).append(reportLink);
	return reportLinkHolder;
}

// Generate the Table Link for Polygons
function generatePolygonTableLink(bid, pname, plat, plng) {
	var tableLinkHolder = document.createElement('div');

	// Return an empty element for the widget/embedded map
	if(isWidgetOrEmbedMap())
		return tableLinkHolder;

	$(tableLinkHolder).addClass('polygon_table_link_holder');
	$(tableLinkHolder).addClass('info_extra_link');

	var tableLink = document.createElement('a');
	tableLink.innerHTML = "See Table";
	PEvent.addListener(tableLink, "click", function() {
		if (map.getIndicator()) {
			var indicator = map.getIndicator();
			var period = indicator.getPeriod();
			session2.put("i", indicator.id);
			session2.put("period", period);
		}
		// Since the user has selected a polygon, clear
		// any place that may be stored in the session.
		session2.remove("p");
		session2.remove("place");
		// Put the polygon info in the session so it
		// can be loaded by the charts page.
		session2.put("bid", bid);
		session2.put("pname", pname);
		session2.put("plat", plat);
		session2.put("plng", plng);
		// Load the charts page.
		window.location = "/tables";
	});

	$(tableLinkHolder).append(tableLink);
	return tableLinkHolder;
}

// Generate the Report Links for Polygons
function generatePolygonReportLink(bid, polyid, pname, plat, plng, pid, rtype, submsg) {
	var reportLinkHolder = document.createElement('div');

	// Return an empty element for the widget/embedded map or a non-subscriber
	// when we're not displaying the subscribe message.
	if(isWidgetOrEmbedMap() || (!isSubscriber() && !submsg))
		return reportLinkHolder;

	$(reportLinkHolder).addClass('polygon_report_link_holder');
	$(reportLinkHolder).addClass('info_extra_link');

	var reportLink = document.createElement('a');
	if(isSubscriber()) {
		reportLink.info = getPolyReportLinkInfo(polyid);
		if(rtype == "polygon") {
			// for supermarket points make brookings report as the default selected report
			reportLink.innerHTML = reportLink.info.polygonOptionLabel
		} else if(rtype == "pradius") {
			reportLink.innerHTML = "See Radius Report";
		}

		// for the hud report links we need to check if the poly has any comparables and if it doesn't then we won't generate the report
		if (reportLink.info.isHudReport) {
			// Using the place id for the poly to retrieve its block groups, comps
			$.ajax({
				url: "/s/?id=1&ty=data&t=nic&act=n&nic=" + pid,
				dataType: "json",
				success: function(nics) {
					var hasComps = true;
					if (nics[pid].comps.length == 0)
						hasComps = false;
	
					// if the nic has no comps then don't show the report
					if (!hasComps) {
						PEvent.addListener(reportLink, "click", function() {
							var text = "No comparables were identified for this NSP Investment Cluster (NIC) so no report can be generated.";
							var alerter = new PAlerter();
							alerter.popup(text, null, null, "OK");
						});
					}
					else {
						PEvent.addListener(reportLink, "click", function() {
							window.location = reportLink.info.page + "?area=" + rtype + "&bid=" + bid + "&polyid=" + polyid + "&pname=" + encodeURIComponent(pname) + "&plat=" + plat + "&plng=" + plng + this.info.reportParam;
						});
					}
				}
			});
		}
		else {
			PEvent.addListener(reportLink, "click", function() {
				window.location = reportLink.info.page + "?area=" + rtype + "&bid=" + bid + "&polyid=" + polyid + "&pname=" + encodeURIComponent(pname) + "&plat=" + plat + "&plng=" + plng + this.info.reportParam;
			});
		}
	} else if(submsg) {
		reportLink.innerHTML = "To see a report for this area, subscribe now.";
		PEvent.addListener(reportLink, "click", function() {
			window.location = "/subscribe";
		});
	}
	$(reportLinkHolder).append(reportLink);
	return reportLinkHolder;
}

// Generate the 'See List of' Pointset Links for Polygons
function generatePolygonPointlistLinks(bid, pname, plat, plng) {
	var pointlistLinkHolder = document.createElement('div');
	var overlays = map.getOverlaySets();

	// Return an empty element for the widget/embedded map or if there are no pointsets on the map.
	if(isWidgetOrEmbedMap() || overlays.length == 0)
		return pointlistLinkHolder;

	$(pointlistLinkHolder).addClass('polygon_pointlist_link_holder');
	$(pointlistLinkHolder).addClass('info_extra_link');

	for(var i=0; i<overlays.length; i++) {
		// Make sure we're not showing see list link for a polyset.
		// Polyset links are set in generatePolygonPolylistLinks.
		if(!overlays[i].id || overlays[i].isPoly)
			continue;

		$(pointlistLinkHolder).append(document.createElement('br'));
		var listLink = document.createElement('a');
		listLink.innerHTML = "See List of " + overlays[i].getLabel();
		listLink.setid = overlays[i].id
		listLink.settype = overlays[i].type;
		listLink.set = overlays[i];
		listLink.place = bid;
		PEvent.addListener(listLink, "click", function() {
			// We need to get the place object for the selected polygon.
			var that = this;
			polycreator.polyload(bid, pname, plat, plng, function(places) {
				// Make sure we retrieved our polygon.
				if(places[0]) {
					// Seeing list isn't allowed for some pointsets at certain placetypes or zoom levels
					// An alert will be fired if the pointset is not allowed
					if (!isSeeListAllowed(that.set.id, places[0]))
						return;

					// Show list in a popup
					showSiteListAlert(that.set, places[0]);
				}
			});
		});
		$(pointlistLinkHolder).append(listLink);
		var img = document.createElement('img');
		img.src = overlays[i].icon.image;
		$(pointlistLinkHolder).append(" ");
		$(pointlistLinkHolder).append(img);
	}
	if (!pointlistLinkHolder.hasChildNodes())
		pointlistLinkHolder.style.display = "none";

	return pointlistLinkHolder;
}

// Generate the 'See List of' Polygon Links for Polygons
function generatePolygonPolylistLinks(bid, pname, plat, plng, marker) {
	var polylistLinkHolder = document.createElement('div');
	var overlays = map.getOverlaySets();
	// Return an empty element for the widget/embedded map or if there are no pointsets on the map.
	if(isWidgetOrEmbedMap() || overlays.length == 0)
		return polylistLinkHolder;

	// Determine if there are currently any polygons on the map,
	// and if so, store which pointsets have them.
	// And don't add the polygon set that was clicked.
	var polygonSets = [];
	for(var i=0; i<overlays.length; i++) {
		if(overlays[i].isPoly) {
			polygonSets.push(i);
		}
	}

	if(polygonSets.length > 0) {
		$(polylistLinkHolder).addClass('polygon_polylist_link_holder');
		$(polylistLinkHolder).addClass('info_extra_link');

		// list of polysets to not show the 'see list' link for
		// but only when the see list is for its own polyset, if that makes sense.
		var ignoreList = [93400,96500,99150,103450,107000,109200,112000,114250];

		// There are polygons on the map. For each set of polygons, add
		// a link to see the list of polygons in the selected boundary.
		for(i=0; i<polygonSets.length; i++) {
			var ignore = false;
			for (var j=0; j<ignoreList.length; j++) {
				if (marker.datasetID == ignoreList[j] && ignoreList[j] == overlays[polygonSets[i]].id) {
					ignore = true;
				}
			}
			// Don't include see list links for its own polyset for specified list
			if (ignore)
				continue;

			$(polylistLinkHolder).append(document.createElement('br'));
			var listLink = document.createElement('a');
			listLink.innerHTML = "See List of " + overlays[polygonSets[i]].getLabel() + " polygons";
			listLink.set = overlays[polygonSets[i]];
			PEvent.addListener(listLink, "click", function() {
				// We need to get the place object for the selected polygon.
				var that = this;
				polycreator.polyload(bid, pname, plat, plng, function(places) {
					// Make sure we retrieved our polygon.
					if(places[0]) {
						// Seeing list isn't allowed for some pointsets at certain placetypes or zoom levels
						// An alert will be fired if the pointset is not allowed
						if (!isSeeListAllowed(that.set.id, places[0]))
						return;

						// Show list in a popup
						showSiteListAlert(that.set, places[0]);
					}
				});
			});
			$(polylistLinkHolder).append(listLink);
			var img = document.createElement('img');
			img.src = overlays[polygonSets[i]].icon.image;
			$(polylistLinkHolder).append(" ");
			$(polylistLinkHolder).append(img);
		}
	}
	if (!polylistLinkHolder.hasChildNodes())
		polylistLinkHolder.style.display = "none";
	return polylistLinkHolder;
}

function createPlacesDiv(candidatePlaces, searchString) {

	if (PEnvironment.pageName == 'report_area') {

		var places = [];
		if (searchString) {
			for (var i = 0; i < candidatePlaces.length; ++i) {
				if (candidatePlaces[i].getLabel().toLowerCase().indexOf(searchString.toLowerCase()) == 0) {
					places.push(candidatePlaces[i]);
				}
			}
			for (var i = 0; i < candidatePlaces.length; ++i) {
				if (candidatePlaces[i].getLabel().toLowerCase().indexOf(searchString.toLowerCase()) != 0) {
					places.push(candidatePlaces[i]);
				}
			}
		} else {
			places = candidatePlaces;
		}

		var l = similarClicks.length;
		for (var i = 0; i < l; i++)
			PEvent.removeListener(similarClicks[i]);
		similarClicks = [];

		// Info window contents
		html = document.createElement("div");
		html.style.fontSize = "11px";
		var title = document.createElement("div");
		title.innerHTML = places[0].getLabel() + getState(places[0]) + " (" + places[0].getType().getName() + ")";
		html.appendChild(title);

		// Display other results if more than 1
		if (places.length > 1) {
			var similar = document.createElement("div");
			similar.innerHTML = "<br><b>Similar results:</b><br>";
			html.appendChild(similar);
			for (var i = 1; i < places.length; i++) {
				var anchor = document.createElement("a");
				anchor.href = "javascript:void(0)";
				anchor.innerHTML = places[i].getLabel() + getState(places[i]) + " (" + places[i].getType().getName() + ")";
				anchor.place = places[i];
				similarClicks.push(PEvent.addListener(anchor, 'click', function() {
					var title = "<div style='font-size: 11px'>" + this.place.getLabel() + " (" + this.place.getType().getName() + ")</div>";
					addMarkerWindow(title, this.place);
				}));
				html.appendChild(anchor);
				html.appendChild(document.createElement("br"));
			};
				}
		return html;

	} else if (PEnvironment.pageName == 'tables') {

		var l = similarClicks.length;
		for ( var i = 0; i < l; i++)
			PEvent.removeListener(similarClicks[i]);
		similarClicks = [];

		var box = document.createElement("div");
		box.className = "similarresults";

		var placeTitle = document.createElement("div");
		placeTitle.style.marginTop = "20px";
		placeTitle.style.marginBottom = "7px";
		placeTitle.style.color = "#7a7a7a";
		placeTitle.style.fontSize = "10pt";
		placeTitle.innerHTML = "<b>Locations Found:</b>";

		// Info window contents
		html = document.createElement("div");
		html.style.border = "1px solid #ccc";
		html.style.padding = "10px";
		var title = document.createElement("div");
		title.innerHTML = "<b>Location Added:</b><br>" + candidatePlaces[0].getLabel()
		    + getState(candidatePlaces[0]) + " (" + candidatePlaces[0].getType().getName() + ")";
		html.appendChild(title);

		// Display other results if more than 1
		if (candidatePlaces.length > 1) {
			var similar = document.createElement("div");
			similar.innerHTML = "<br><b>Similar Results:</b><br>";
			html.appendChild(similar);
			for ( var i = 1; i < candidatePlaces.length; i++) {
				var anchor = document.createElement("a");
				anchor.innerHTML = candidatePlaces[i].getLabel() + getState(candidatePlaces[i]) + " ("
				    + candidatePlaces[i].getType().getName() + ")";
				anchor.place = candidatePlaces[i];
				similarClicks.push(PEvent.addListener(anchor, 'click', function() {
					var title = "<div style='font-size: 11px'>" + this.place.getLabel()
					    + " (" + this.place.getType().getName() + ")</div>";

					// Check type of place
					  addPlaceType(this.place.id);
				  }));

				html.appendChild(anchor);
				html.appendChild(document.createElement("br"));
			}
		}

		box.appendChild(placeTitle);
		box.appendChild(html);
		return box;

	} else {

		var places = [];
		if (searchString) {
			for ( var i = 0; i < candidatePlaces.length; ++i) {
				if (candidatePlaces[i].getLabel().toLowerCase().indexOf(searchString.toLowerCase()) == 0) {
					places.push(candidatePlaces[i]);
				}
			}
			for ( var i = 0; i < candidatePlaces.length; ++i) {
				if (candidatePlaces[i].getLabel().toLowerCase().indexOf(searchString.toLowerCase()) != 0) {
					places.push(candidatePlaces[i]);
				}
			}
		} else {
			places = candidatePlaces;
		}

		var l = similarClicks.length;
		for ( var i = 0; i < l; i++)
			PEvent.removeListener(similarClicks[i]);
		similarClicks = [];

		// Info window contents
		html = document.createElement("div");
		html.className = "similarresults";
		var title = document.createElement("div");
		title.innerHTML = places[0].getLabel() + getState(places[0]) + " (" + places[0].getType().getName() + ")";
		html.appendChild(title);

		// Display other results if more than 1
		if (places.length > 1) {
			var similar = document.createElement("div");
			similar.innerHTML = "<br><b>Similar Results:</b><br>";
			html.appendChild(similar);
			for ( var i = 1; i < places.length; i++) {
				var placelink = document.createElement("span");
				placelink.className = "similarlinks";
				placelink.style.color = "#5D83D0";
				placelink.textDecoration = "underline";
				placelink.innerHTML = places[i].getLabel() + getState(places[i])
				+ " (" + places[i].getType().getName() + ")";
				placelink.place = places[i];
				similarClicks.push(PEvent.addListener(placelink, 'mouseup', function() {
					selectLoadedPlace(this.place, true);
				}));
				html.appendChild(placelink);
				html.appendChild(document.createElement("br"));
			}
		}
		map.saveInfoWindow = true;
		map.infoWindowType = 'place';
		return html;

	}

}

function addPolygons(map, place, fill) {
	if (PEnvironment.pageName == 'widget') {
		refreshWidgetRankings(place);
		// Novogradac requested to have a black outline around the boundaries instead of the usual
		if (PEnvironment.widgetParams && PEnvironment.widgetParams['sid'] == 61) {
			polycolor = "#000000";
		}

		// refresh trends chart
		// only if the widget has trends charts enabled will it actually refresh it
		//refreshWidgetTrendsChart(place);
	}

	// Always reset the map.polygons array, as before it was appending.
	// Apparently something else uses this. If I completely unset this, the map
	// will constantly add new boundaries for every click. WTF?
	map.polygons = new Array();
	var polygons = place.getVertices();
	for(var i=0; i<polygons.length; i++) {
		var polygon;
		if(PEnvironment.pageName == 'report_area') {
			polygon = new PPolyline(polygons[i], polycolor);
		} else if(PEnvironment.pageName == 'report_generate' && currentReport && currentReport.reportType != "hud") {
			polygon = new PPolygon(polygons[i], polycolor, polyweight, polyopacity, polyfill);
		} else {
			if(fill) {
				polygon = new PPolygon(polygons[i]);
			} else {
				polygon = new PPolyline(polygons[i], polycolor);
			}
		}
		map.addOverlay(polygon);
		map.polygons.push(polygon);
	}
}

// adds polylines, used for polygons from polysets
function addPolylines(map, verts, opts) {
	// option to change color of polyline
	if (opts && opts.color)
		reportpolygoncolor = opts.color;

	for(var i=0; i<verts.length; i++) {
		var polyline = new PPolyline(verts[i], reportpolygoncolor, 3);
		map.addOverlay(polyline);
	}
}

function clearPolygons(map) {
	var polys = map.polygons;
	if (polys) {
		for ( var i = polys.length; i >= 0; i--) {
			map.removeOverlay(polys[i]);
		}
	}
}

function createTitle(state, title) {
	var text = "";
	if (title && state.indicator && state.indicator.getFullDisplayName()) {
		addDetailsButton();
		text = state.indicator.getFullDisplayName();
	} else if (state.indicator) {
		text = state.indicator.displayName;
	}

	if (!title) {

		if (text && text.length > 0)
			text += ", ";

		if (state.addr)
			text += state.addr;
		else if (state.place) {
			text += state.place.getLabel();
			if (state.place.getType() == PPlaceType.COUNTY)
				text += " County";
			text += getState(state.place);
		}
	}

	return text;
}

// Rewritten from createTitle in MapCommon.js and removed mapstates
function createTitleForWidgetAndEmbedMap(indicator, sets) {
	var text = "";
	if (indicator && indicator.getFullDisplayName()) {
		addDetailsButton();
		if (indicator.getDescription() != "" && indicator.getDescription().length < indicator.getFullDisplayName().length) {
			text = indicator.getDescription();
		} else {
			text = indicator.getFullDisplayName();
		}
	} else if (indicator) {
		text = indicator.displayName;
	}
	else if (sets) {
		text = createSitesMapTitle(sets);
	}

	return text;
}

// This is only used when using createTitle because the toggling is handled in another function, this just displays the current view.
// So for example if the description is on and the indicator is changed then the desscription should stay on and not be toggled.
function addDetailsButton() {
	$('#morelink').show();
	if ($('#morelink').hasClass("on")) {
		$('#moreimg').attr({'src':'/images/home-maptitle-button-close.png'});
	} else {
		$('#moreimg').attr({'src':'/images/home-maptitle-button-details.png'});
	}
}

function createSitesMapTitle(sets) {
	if (!sets)
		sets = map.getOverlaySets();
	var text = "";
	for (var i=0; i<sets.length; i++) {
		var a = "";
		if (sets.length > 1 && i != 0) {
			a = ", ";
			if (i == sets.length-1) {
				if (i > 1)
					a = ", and ";
				else
					a = " and ";
			}
		}
		text += a + sets[i].getLabel();
	}
	return text;
}

function mapOptions(elem) {
	// When assembling custom regions the map options is disabled
	if (jQuery('#mapOptionsToggle').hasClass('disable')) {
		var alerter = new PAlerter();
		var text = "The map options are not available while assembling a custom region.";
		var position = getAlertPosition(parseInt(alerter.box.style.width));
		alerter.popup(text, position[0], position[1], "OK");
		return;
	}

	$('#optsbox').toggle();
}

function changeSaveMapName(anchor) {
	anchor.parentNode.parentNode.getElementsByTagName('input')[0].style.display = "block";
	anchor.parentNode.parentNode.childNodes[0].style.display = "none";
}

//Create a box within div#map, hidden by default.
function createDivMapMessage(content, width, height) {
	var alerter = new PAlerter2();
	return alerter.popup(content);
}

function genMapJpgLink(template, identifyNotAllowed) {

	// Get Map Info but strip target since we'll be prepending a different one.
	// If we cannot extract a url, then there's nothing to do.
	var mapImageUrlTokens = map.printImage().split("?");
	if (mapImageUrlTokens.length == 2) {

		// Get Map Title
		var indicator = map.getIndicator();
		var legendMerger = map.getLegendMerger();
		var title = "";
		var description = "";
		if (indicator) {
			title = '&title=' + escape(indicator.getFullDisplayName());
			description = '&desc=' + escape(indicator.getDescription());
		} else if (legendMerger) {
			title = '&title=';
			descriptions = '&desc=';
		}

		var iData = "";
		if (!identifyNotAllowed) {
			// Get Info Window Info
			var infoWindow = map.getInfoWindow();
			if (infoWindow && infoWindow.isHidden() == false
					&& map.getBounds().contains(infoWindow.getPoint())) {
				var iPoint = infoWindow.getPoint();
				iData = "&inflat=" + escape(iPoint.lat());
				iData += "&inflong=" + escape(iPoint.lng());
				var iContent = infoWindow.tabs[infoWindow.selectedTab].content;
				if (iContent.parentNode)
					iContent = iContent.parentNode.innerHTML;
				iData += "&infcont=" + escape(iContent);
			}
		}

		// Get Legend Info
		var legend = jQuery("div#legend");
		var legendHighlights = legend.find("span.legendHighlight");
		var indId = "";
		var period = "";
		var dataType = "";
		var data = "";
		var additionalData = "";
		var color = "";
		var visible = "";
		var dataSize = "";
		var additionalDataSize = "";
		var source = "";
		var boundary = "";
		var orientation = "";
		var expanded = "&ex=0";
		var breadcrumbsString = "&bc=" + escape(jQuery("div#breadcrumbs").text().split(">").join(" > "));

		orientation = "&or=" + printOrientation;

		// If map view is expanded pass notifier
		if ($('#addsites_widget')[0] && $('#addsites_widget')[0].style.display == "none")
			expanded = "&ex=1";

		if (indicator) { // We have an indicator legend
			boundary = "&bdnm=" + escape(map.getLegend().getBoundaryType().getName());
			source = "&src=" + escape(indicator.getSourceList());
			indId = "&ind=" + indicator.getID();
			period = "&p=" + indicator.getPeriod();
			dataType = "&dt=" + escape(widget.getMeasurementLabel(indicator.getMeasurement()).replace("&nbsp;", ""));
			var table = legend.find("table");
			var trs = table.find("tr:even");
			dataSize = "&ds=" + trs.size();
			trs.each( function(i) {
				var tds = jQuery(this).children("td:even");
				if (tds.eq(1).text() && tds.eq(2).text()) {
					data += "&d_" + i + "=" + escape(tds.eq(1).text() + ' - ' + tds.eq(2).text());
				} else if (tds.eq(1).text()) {
					data += "&d_" + i + "=" + escape(tds.eq(1).text());
				}
				var rgb = /^rgb\((.*)\)/.exec(tds.eq(0).css("background-color"));
				if (rgb && rgb.length > 0) {
					color += "&c_" + i + "=" + escape(rgb[1]);
				} else {
					// probaby in hex for ie
					rgb = /^(#[a-fA-F0-9]{3,6})/.exec(tds.eq(0).css("background-color"));
					if (rgb && rgb.length > 0) {
						color += "&c_" + i + "=" + escape(rgb[1]);
					}
				}
				if(editState & PIndicatorBreaks.EDITSTATE.exactBreaks) {
					// Exact breaks. Include whether the current layer is visible.
					mvaLayers = session2.get("mvalayers");
					visible +="&v_" + i + "=" + mvaLayers[i];
				}
			});
			var span = table.next().find("span");
			additionalDataSize = "&ads=" + span.size();
			span.each( function(i) {
				additionalData += "&ad_"
					+ i
					+ "="
					+ escape(jQuery(this).text()
							+ jQuery(this).get(0).nextSibling.data);
			});
		}

		// Sites data
		var addSitesIcons = "";
		var addSitesLabels = "";
		var addSitesSources = "";
		// Get all overlay sets on the map.
		var osets = map.getOverlaySets(false, true);
		var addSitesSize = "&ass=" + osets.length;
		// Cycle through each overlay set on the map.
		// Because sets in osets could be skipped, curNum is used to
		// ensure that there are no breaks in the numbering of sets.
		var curNum = 0;
		for(var i=0; i<osets.length; i++) {
			// Don't include child sets or overlay sets without an id.
			// (Child sets will still appear on the map, this will just
			// keep them from appearing in the legend.)
			if(!osets[i].id || osets[i].child) {
				continue;
			}
			// Include the set's icon (if applicable).
			if(osets[i].icon) {
				addSitesIcons += "&asi_" + curNum + "=" + encodeURIComponent(filenameFromURL(osets[i].icon.image));
			}
			// Slight hack to provide a specific name and source for mass transit points.
			if(osets[i].id == massTransitSetId) {
				addSitesLabels += "&asl_" + curNum + "=" + encodeURIComponent("Mass Transit Lines");
				addSitesLabels += "&asa_" + curNum + "=" + encodeURIComponent("Urban Mapping, Inc.");
			} else {
				addSitesLabels += "&asl_" + curNum + "=" + encodeURIComponent(osets[i].name);
			}
			// Determine if this set is color coded or contains regular filter groups (or
			// neither). Color-coded sets will not contain any regular filters/filter groups.
			if(osets[i].filtersbyicons.length > 0) {
				// This is a color coded set.
				// There should be one filter group which should contain the color-code group name.
				var filterGroups = osets[i].getFilters();
				if(filterGroups[0]) {
					addSitesLabels += "&asl_" + curNum + "_" + "0" + "=" + encodeURIComponent(filterGroups[0].name);
					// Cycle through each of the individual color codes.
					for(var m=0; m<osets[i].filtersbyicons.length; m++) {
						addSitesIcons += "&asi_" + curNum + "_" + "0" + "_" + m + "=" + encodeURIComponent(filenameFromURL(osets[i].filtericons[m].image));
						addSitesLabels += "&asl_" + curNum + "_" + "0" + "_" + m + "=" + encodeURIComponent(osets[i].filtersbyicons[m].valuesDisplay);
					}
				}
			} else {
				// This is not a color coded set.
				// Cycle through each of the filter groups.
				var filterGroups = osets[i].filtergroups;
				var k=0;
				for(group in filterGroups) {
					if(!group.match("_HIDE")) {
						addSitesLabels += "&asl_" + curNum + "_" + k + "=" + group;
						// Cycle through each of the filters in the group.
						var groupFilters = filterGroups[group];
						for(var m=0; m<groupFilters.length; m++) {
							addSitesLabels += "&asl_" + curNum + "_" + k + "_" + m + "=" + encodeURIComponent(groupFilters[m].valuesDisplay);
						}
					}
					k++;
				}
			}
			// Check if this set has a source, if so add it so it can be added to the printed image
			var psource = osets[i].sources;
			var sourceString = null;
			if(psource.length > 0) {
				// if there's multiple sources then separate them by a semi-colon
				sourceString = "";
				for (var j=0; j<psource.length; j++) {
					sourceString += psource[j].label;
					if(j < psource.length-1)
						sourceString += ", ";
				}
				encodeURIComponent(filenameFromURL(sourceString));
			}
			if(sourceString) {
				addSitesSources += "&asa_" + curNum + "=" + sourceString;
			}
			// Set added. Increment curNum.
			curNum++;
		}

		// Place
		var placeId = "";
		var address = "";
		var boundaryOutline = "";
		if (session2.get('place')) {
			address = "&a=" + escape(session2.get('place'));
			if (session2.get('lng') && session2.get('lat')) {
				address += '&ax=' + escape(session2.get('lng'))
				+ '&ay=' + escape(session2.get('lat'));
			} else { // assume
				address += '&ax=' + escape(map.getCenter().longitude) + '&ay='
				+ escape(map.getCenter().latitude);
			}
		}

		if (session2.get('p'))
			placeId = "&pid=" + session2.get('p');

		// Custom places
		var customPlaces = "";
		if(session2.get('cp')) {
			customPlaces += "&cp=" + session2.get('cp');
		}

		// Pass the argument to enable/disable boundary outlines on prints.
		// We currently show boundary outlines for all places, except we hide
		// them on regular (pre-defined) places when island printing is enabled.
		if(islandPrintEnabled == true) {
			boundaryOutline = "&bo=custom";
		} else {
			boundaryOutline = "&bo=all";
		}

		// Point/polygon labels (if applicable).
		var labels = "";
		// The true being passed in below prevents the function from
		// generating arguments for labels that are currently hidden.
		var labelParms = labelManager.generateMapLabelArguments(true);
		for(var i=0; i<labelParms.length; i++) {
			labels += "&" + labelParms[i];
		}

		var mergedLegendData = '';
		if (legendMerger) {
			var indLegend = null;
			var cnt = 0;
			for ( var i = 0; indLegend = legendMerger.getLegend(i); i++) {
				var ind = indLegend.getIndicator();
				if (ind) {
					mergedLegendData += "&mlabel_" + cnt + "=" + escape(ind.getFullLabel());
					mergedLegendData += "&mbdnm_" + cnt + "=" + escape(indLegend.legend.getBoundaryType().getName());
					mergedLegendData += "&msrc_" + cnt + "=" + escape(ind.getSourceList());
					mergedLegendData += "&mp_" + cnt + "=" + escape(ind.getPeriod());
					mergedLegendData += "&mdt_" + cnt + "=" + escape(indLegend.getMeasurementLabel(ind.getMeasurement()).replace("&nbsp;",""));
					var range = indLegend.getIndicatorRange().getRange();
					var values = indLegend.getIndicatorValues().getValues();
					if(range){
						mergedLegendData += "&mr0_" + cnt + "=" + escape(PWebUtil.formatNumber(range[0], ind.unit));
						mergedLegendData += "&mr1_" + cnt + "=" + escape(PWebUtil.formatNumber(range[1], ind.unit));
						var limits = indLegend.getIndicatorRange().getLimits();
						mergedLegendData += "&mrmin_" + cnt + "=" + escape(limits[0]);
						mergedLegendData += "&mrmax_" + cnt + "=" + escape(limits[1]);
					}
					if(values){
						mergedLegendData += "&mv" + cnt + "=" + escape(serializeJSON(values));
					}

					cnt++;
				}
				mergedLegendData += "&ms=" + cnt;
			}
		}
		// the embed map has it's own template and so won't use the global page printtemplate
		if (template)
			var newTarget = "http://" + template + "/";
		else
			var newTarget = "http://" + printTemplate + "/";

		// Widget-specific print arguments
		var widgetparams = "";
		if(PEnvironment.pageName == "widget") {
			// Determine if this widget uses rankings and they are currently visible.
			if(map.widgetRankingsOn && rRanks != null && $("#popup").is(":visible")) {
				// It does and they are. Retrieve the ranking box's display name.
				widgetparams += "&wri=" + encodeURIComponent(rRanks.ind.getID());
				widgetparams += "&wrper=" + encodeURIComponent(rRanks.period);
				widgetparams += "&wrp=" + encodeURIComponent(rRanks.place.getID());
				widgetparams += "&wrpt=" + encodeURIComponent(rRanks.place.getType().getPluralName());
				widgetparams += "&wrd=" + encodeURIComponent(rRanks.ind.fullDisplayNames[rRanks.ind.curPerIndex]);
			}
		}

		var url = newTarget + "?" + mapImageUrlTokens[1] + title + orientation
		+ expanded + boundary + source + indId + period + dataType + dataSize
		+ data + color + visible + mergedLegendData + additionalDataSize
		+ additionalData + addSitesSize + addSitesLabels + addSitesIcons + addSitesSources
		+ labels + placeId + customPlaces + address + boundaryOutline + widgetparams
		+ breadcrumbsString + description + iData;
		return url;
	} else {
		customAlert("Please display a map.");
	}
	return null;
}

function customAlert(text) {
	var alerter = new PAlerter();
	alerter.popup(text, null, null, "OK");
}

function registerAlert() {
	var text = "Available to registered users and subscribers only. <a onclick='loginAlert(this)' class='pagelinks'>Login</a> to access, or see <a href='/subscribe' class='pagelinks'>subscriber options</a>.";
	var alerter = new PAlerter();
	alerter.popup(text, null, null, "OK");
}

function premiumSubscribeAlert() {
	var link = isPublicUser() ? '/register?reg_type=full' : '/servlets/upgrade?reg_type=full';
	var text = "Currently, this data is only available to selected users.";
	var alerter = new PAlerter();
	alerter.popup(text, null, null, "OK");
}

function requestMapEmbedding() {

	var mapImageUrlTokens = map.printImage().split("?");
	if (mapImageUrlTokens.length <= 1) { // nothing to embed.
		return;
	}

	// get map dimensions
	var mapsize = map.getSize();
	var imgwidth = mapsize.width;
	var imgheight = mapsize.height;

	var alerter = new PAlerter();
	var text = "Select the type of map you'd like to embed, a static image or a dynamic map. Then define the width and height for the map and choose the features you'd like included."
	text += "<br /><br /><form id='embedMapAlertOptions'>";
	text += "<label for='embedmap'>Image</label><input id='embedmap' type='radio' name='embedtype' checked='checked' />";
	text += "&nbsp;<label for='embedmap_dyn'>Dynamic Map</label><input id='embedmap_dyn' type='radio' name='embedtype' />";
	text += "<div style='height:4px'>&nbsp;</div>";
	text += "Width: <input id='aParmsWidth' type='text' size='4' maxlength='4' value='" + imgwidth + "' />&nbsp;";
	text += "&nbsp;Height: <input id='aParmsHeight' type='text' size='4' maxlength='4' value='" + imgheight + "' />";
	text += "<div class='options'>";
	text += "<label class='option'>Include Map Title:</label> <label for='embedmap_title_yes'>Yes</label><input name='map_title'type='radio' id='embedmap_title_yes' value='true' checked='checked'/>";
	text += "<div class='spacer'>&nbsp;</div><label for='embedmap_title_no'>No</label><input name='map_title' id='embedmap_title_no' value='false' type='radio' /><br class='clear'/>";
	text += "<label class='option'>Include Map Legend:</label> <label for='embedmap_legend_yes'>Yes</label><input name='map_legend' id='embedmap_legend_yes' type='radio' value='true' checked='checked'/>";
	text += "<div class='spacer'>&nbsp;</div><label for='embedmap_legend_no'>No</label><input name='map_legend' id='embedmap_legend_no' value='false' type='radio' />";
	text += "</div>";
	text += "</form>";

	alerter.popup(text, null, null, "Cancel", "Embed", function() { // embed and generate link
		// Retrieve the selected embed map options.
		var embedOptions = $('#embedMapAlertOptions input:checked');

		// If the user chose a dynamic map, check if there are any
		// dataloader-created datasets currently on the map.
		if(embedOptions[0].id == "embedmap_dyn" && session2.get("dlo")) {
			// They did and there are. Run through them and grab the names of
			// any datasets that do not have public permissions (if there are any).
			var dlo = session2.get("dlo").split(",");
			var nonPublic = [];
			for(var i=0; i<dlo.length; i++) {
				var dloSet = getOverlaySetByIdAndType(dlo[i], "dl");
				if(dloSet != null && dloSet.perm != 2) {
					nonPublic.push(dloSet.name);
				}
			}
			// See if any of the dataloader-created datasets on the map are
			// not set to public.
			if(nonPublic.length > 0) {
				// There are non-public datasets. Alert the user and do
				// not continue.
				var text = "The following datasets are not public and cannot be used in a dynamic embedded map:<br /><br />";
				for(var i=0; i<nonPublic.length; i++) {
					text += nonPublic[i] + "<br />";
				}
				var alerter = new PAlerter();
				alerter.popup(text, null, null, "OK");
				return false;
			}
		}

		function embed(cb) {
			// rebuild parms with width and height
			var pairs = [];
			for ( var key in aParms) {
				pairs.push(key + '=' + aParms[key]);
			}
			parms = pairs.join('&');

			var link = new PMapLink(cb, 'embed');

			link.url += '&ew=' + aParms.imgwidth + '&eh=' + aParms.imgheight;
			// if user selected to have the legend and/or title add them to the url
			if (aParms.elegend == "true")
				link.url += '&elegend=' + aParms.elegend;
			if (aParms.etitle == "true")
				link.url += '&etitle=' + aParms.etitle;

			if (session2.get('cp')) { // custom poly
				parms += "&cp=" + session2.get('cp');
			}

			linkManager.embed(link, function(status, msg, lqid) {
				var alerter = new PAlerter();
				if (status == 200) {
					text = "Your map image has been created.  To embed this map, please copy and paste the following link to your source code:<br/><br/>";
					var link = '<div style=&quot;text-align:center&quot;>'
						+ '<iframe src=&quot;http://'
						+ window.location.hostname
						+ '/' + aParms.etype + '?lqid='
						+ lqid
						+ '&quot; named=&quot;embeddedmap&quot; scrolling=&quot;no&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; frameborder=&quot;0&quot; width=&quot;'
						+ aParms.imgwidth
						+ '&quot; height=&quot;'
						+ aParms.imgheight
						+ '&quot; >Click here to interact with map.</iframe>'
						+ '<div style=&quot;font:13px arial,geneva,helvetica,sans-serif&quot;>Powered by <a style=&quot;text-decoration:underline&quot; target=&quot;_blank&quot; href=&quot;http://www.policymap.com&quot;>www.policymap.com</a>, an <a style=&quot;text-decoration:underline&quot; target=&quot;_blank&quot; href=&quot;http://www.policymap.com&quot;>online mapping tool</a> and data warehouse.</div></div>';

					text += '<input id="embed_link" type="text" value="' + link + '" size="35" />';
					alerter.popup(text, null, null, "OK");
					jQuery('#embed_link').focus( function() { this.select(); });

				} else {
					alerter.popup(msg, null, null, "OK");
				}
			}, parms, 'EmbedMap', aParms.action);
		}

		var aParms = {};

		// for creating a static image
		// the genMapJpgLink string needs to be added first and then add the action and width, height, etitle, elegend, etype params
		if (embedOptions[0].id == "embedmap") {
			var template = "EmbedMap";
			var parms = genMapJpgLink(template, true);
			var pairs = parms.split('&');
			for ( var i = 0; i < pairs.length; ++i) {
				var kv = pairs[i].split('=');
				if (kv.length == 2) {
					aParms[kv[0]] = kv[1];
				}
			}
			aParms.action = "embed";
			// type is for the jsp page
			aParms.etype = "embedmap";
		}
		// for a dynamic map
		else {
			var parms = mapImageUrlTokens[1]; // contains relevant map parms.
			var pairs = parms.split('&');
			for ( var i = 0; i < pairs.length; ++i) {
				var kv = pairs[i].split('=');
				if (kv.length == 2) {
					aParms[kv[0]] = kv[1];
				}
			}
			aParms.action = "embeddyn";
			// type is for the jsp page
			aParms.etype = "embedmap_dyn";
		}

		aParms.etype = embedOptions[0].id;
		aParms.etitle = embedOptions[1].value;
		aParms.elegend = embedOptions[2].value;

		aParms.imgwidth = jQuery('#aParmsWidth').val();
		aParms.imgheight = jQuery('#aParmsHeight').val();
		if( aParms.imgwidth > 2000 ) {
			aParms.imgwidth = 2000;
		}
		if( aParms.imgheight > 2000 ) {
			aParms.imgheight = 2000;
		}

		// if no indicator is on the map then the sites titles will be used as the map title
		var indicator = map.getIndicator();

		if (!indicator && map.getOverlaySets().length > 0)
			aParms.title = createSitesMapTitle();

		if (indicator) {
			var jsonbreaks = indicator.createCustomBreaksJSON(session2.get('nb') ? session2.get('nb') : DEFAULT_NUMBREAKS, true);
			if (jsonbreaks) {
				var obj = {};
				obj[indicator.id] = jsonbreaks;
				PAsync2.call(PEnvironment.stringstoreUrl + '?str=' + MochiKit.Base.serializeJSON(obj), embed);
			} else
				embed();
		} else
			embed();
	});
}

function resetMap() {
	//setMapOptionsToDefaultAndRefresh();
	map.mapOptions.setToDefault();

	map.getLegend().setNumberOfBreaks(DEFAULT_NUMBREAKS);
	if(widget)
		widget.clear();

	clearLocation();
	if (polycreator) {
		polycreator.reset();
		polycreator.dropdown.reset();
		// only need to toggle the custom region if build is on because than by toggling it turns it off
		if (polycreator.isBuildOn())
			toggleCustomRegion();
	}

	map.clearOverlays();
	map.clearOverlaySets();
	sitelegends.refresh();
	labelManager.resetLabelManager();
	// If we have a dataset search on the map, clear it.
	if(datasetSearch != null) {
		datasetSearch.reset();
	}
	if (map.getInfoWindow())
		map.closeInfoWindow();
	map.setCenter(new PLatLng(USA_LAT, USA_LNG), USA_ZOOM);
	// We don't want to store the default zoom in the session.
	session2.remove("curZoom");
	document.getElementById("maptitle").innerHTML = "";
	updateIndicatorTitleFavorite();
	$('#moretitle').hide(200);
	resetDetailsButton();
	search.reset();

	session.clear();
	session2.removeAllRelevant();
}

function clearMapData() {
	widget.clear();
	updateIndicatorTitleFavorite();
}

function clearLocationAlert() {
	var text = "";
	var place = null;
	var alerter = new PAlerter();

	if(PEnvironment.pageName == 'widget' && textOnlyIsOn) {
		// There should only be one place on the table.
		if(cube.places && cube.places[0]) {
			place = cube.places[0];
		}
	} else if(mapstates.currentplace && mapstates.currentplace.getType()) {
		place = mapstates.currentplace;
	}

	// check count to see if there are custom places
	if (polycreator.customPlacesCount > 0)
		var customplaces = polycreator.customPlaces;

	if (place || customplaces) {
		if (place) {
			text = "Are you sure you want to clear the location currently displayed - <b>"
				+ place.getLabel()
				+ getState(place)
				+ " ("
				+ place.getType().getName() + "</b>)?";
		}

		if (place && customplaces)
			text += "<br /><br />This will also clear the custom regions currently displayed.";
		else if (customplaces)
			text = "Are you sure you want to clear the custom regions currently displayed?";

		alerter.popup(text, null, null, "No", "Yes", clearLocation);
	} else {
		if (PEnvironment.pageName == 'widget')
			text = 'There is currently no location specified. You can do this either by clicking on the map, or by clicking a "breadcrumb" which appears on the top left of the map.';
		else
			text = 'There is currently no location specified. You can do this either by entering one in Set Map Location, clicking a "breadcrumb," which appears on the top left of the map, or building a custom region (subscribers only).';
		alerter.popup(text, null, null, "OK");
	}
}

function clearLocation() {
	// remove place polygons
	if (map.polygons) {
		for (var i=0; i<map.polygons.length; i++) {
			map.removeOverlay(map.polygons[i]);
		}
		// clear polygon storage array
		map.polygons = [];
	}
	if (map.getInfoWindow())
		map.closeInfoWindow();

	session2.remove('p');
	session2.remove('pLabel');
	session2.remove('place');
	session2.remove('legendind');
	session2.remove('cp');
	// remove all the custom regions
	if (polycreator) {
		// Should probaly put all this in a PPolyCreator method
		// but since no testing will be done before going to prod playing it safe for now and just adding it here
		var customplaces = polycreator.customPlaces;
		// remove each place from the map
		for (var i in customplaces) {
			polycreator.removeCustomRegionFromMap(customplaces[i].place);
		}
		// widget page doesn't use the dropdown or the building custom region widgets that are reset in reset
		if (PEnvironment.pageName != 'widget') {
			polycreator.reset();
			polycreator.dropdown.reset();
		}
	}

	mapstates.currentplace = initialplace;
	custom_place = null;
	global_places = [];

	if(PEnvironment.pageName == 'widget' && textOnlyIsOn) {
		// There should only be one place on the table.
		cube.remove(cube.places[0]);
		jQuery("#similarbox").html("");
	}
}

function isCustomRegionOn() {
	var cr = document.getElementById("customregion");
	if (cr)
		return cr.innerHTML != "Build Custom Region";
	else
		return false;
}

function buildRegionAlert(custreg) {
	var text = "To create a custom region, click a spot on the map, move your mouse to another spot and click, and continue until you close the region by clicking on the first point.   At that point you may name the region and save it to My PolicyMap.  To clear a custom region, click Clear Location and to disable this feature, click Disable Custom Region.";
	var alerter = new PAlerter();

	function f() {
		custreg.innerHTML = "Disable Custom Region";
		map.enablePolyCreator(polycreator);
	}

	alerter.popup(text, null, null, null, "OK", f);
}

function toggleIndicatorDescription() {
	var more = document.getElementById('moretitle');
	var morelink = document.getElementById('morelink');

	if (!$(morelink).hasClass("on")) {

		// not sure why the map needs this and not the charts
		// eventually could probably fix it so this isn't needed for maps
		if (PEnvironment.pageName != "tables") {
			var ind = map.getIndicator();
			more.innerHTML = ind.getDescription();
			var sources = ind.getSources();
			if(sources.length > 1) {
				more.innerHTML += " (See data directory for " + ind.getSourceList(true) + ".)";
			} else if(sources.length == 1) {
				var sourceURL = ind.getSourceURL(sources[0]);
				if(sourceURL != null) {
					more.innerHTML += " <a class='dataLink' target='_blank' href='" + sourceURL + "'>(see data directory)</a>";
				}
			}
		}
		jQuery('#moretitle').show(200);
		jQuery('#moretitle').fadeIn(200);
		$('#moreimg').attr({'src':'/images/home-maptitle-button-close.png'});
	} else {
		jQuery('#moretitle').hide(200);
		$('#moreimg').attr({'src':'/images/home-maptitle-button-details.png'});
	}

	$(morelink).toggleClass("on");
}

function showIndicatorDescriptionIfOn(ind) {
	if (!ind)
		var ind = map.getIndicator();

	var moretitle = document.getElementById('moretitle');
	var morelink = document.getElementById('morelink');

	moretitle.innerHTML = ind.getDescription();
	var sources = ind.getSources();
	if(sources.length > 1) {
		moretitle.innerHTML += " (See data directory for " + ind.getSourceList(true) + ".)";
	} else if(sources.length == 1) {
		var sourceURL = ind.getSourceURL(sources[0]);
		if(sourceURL != null) {
			moretitle.innerHTML += " <a class='dataLink'  target='_blank' href='" + sourceURL + "'>(see data directory)</a>";
		}
	}

	if ($(morelink).hasClass("on")) {
		jQuery('#moretitle').fadeIn(2000);
		$('#moreimg').attr({'src':'/images/home-maptitle-button-close.png'});
	}
	else {
		$('#moreimg').attr({'src':'/images/home-maptitle-button-details.png'});
	}

}

function getAlertPosition(alertsize) {
	return [ 0, 0 ];
}

function loadMap() {
	// make custom place null when removing cp var in session
	session2.addListener('remove', function(k) {
		if (k == "cp")
			custom_place = null;
	});

	// change legend color ramp if in session or url params
	if (session2.get('rmp') && PColorRampOptions[session2.get('rmp')])
		PColorRamp.DEFAULT = PColorRampOptions[session2.get('rmp')].ramp;

	// popuplate previous maps drop down (from session)
	var pm = session2.get('prevmaps');
	if (pm != null && pm.length > 0) {
		// compare prevmaps entries to other session vars... remove prevmaps
		// entry if identical
		for ( var i = 0; i < pm.length; i++) {
			var pm0 = pm[i];
			if (pm0.i == session2.get('i') && pm0.p == session2.get('p') && !session2.get('cp') && !session2.get('place')) {
				var so = session2.get('o');
				var pmo = (pm0.o && pm0.o.length > 0) ? pm0.o : null;
				if ((!pmo && !so) || (pmo && so && pmo.join(',') == so)) {
					pm.splice(i, 1);
					i--;
				}
			}
		}
		mapstates.setList(pm);
	}

	var curZoom = session2.get("curZoom");
	// create polycreator
	var options = new PPolyCreatorOptions();
	options.poly.weight = 1;
	options.poly.opacity = 0.5;
	polycreator = new PPolyCreator(options);
	polycreator.boundaryWidget = new PPolyCreatorBoundaryWidget(polycreator);
	polycreator.circleWidget = new PPolyCreatorCircleWidget(polycreator);
	polycreator.assembleInfoWidget = new PPolyCreatorAssembleInfoWidget(polycreator);
	// only add the custom regions drop down when the html element that contains the drop down is in the page
	// for example the widget doesn't need this so it doesn't have the crdropdown element
	if (document.getElementById("crdropdown"))
		polycreator.dropdown = new PolyCreatorDropDownList(document.getElementById("crdropdown"), polycreator, map);

	// if there are custom places in the session then the drop down gets populated after those custom places are added to the map
	// It needs to also check it the user is actually logged in and is a subscriber
	if (!session2.get('cp') && session2.get('_userid')) {
		polycreator.dropdown.setUsersPlaces();
	}

	PEvent.addListener(polycreator, 'addpoly', function(points) {
		// opens the infowindow with the save fields and buttons
		polycreator.showSaveInfoWindow(points[0]);
	});

	PEvent.addListener(polycreator, 'savepoly', function(places) {
		polycreator.addSavedPoly(places);
	});

	// Create map and go to address
	map = new PMap(document.getElementById("map"));
	map.mapOptions = new MapLayerOptions(document.getElementById('optsbox'));
	map.mapOptions.populate();

	// temporary renderer
	// map.kamap.aMaps.prod.aLayers[0].tileServers.servers = ["http://dlt.pushpin.com/tilecache"];
	map.addControl(new PLargeMapControl());
	map.enableDoubleClickZoom();
	map.disableKeyboard();

	// Enable zooming the map with the mouse scroll wheel.
	map.enableScrollWheelZoom();
	// Create an event to catch mouse wheel scrolls.
	$("html").mousewheel(function(event, delta) {
		// If the mouse was over the map (or an SVG on the map), ignore the scroll
		// event. (Chrome responds with a different target than every other browser.)
		if(event.target.nodeName == "svg" || (event.target.offsetParent && (event.target.offsetParent.className == "mapLayer" || event.target.offsetParent.id == "theInsideLayer"))) {
			event.preventDefault();
		}
	});

	// check if map options in session and turn on/off layers
	if (session2.get('mo')) {
		MAPLAYER_OPTIONS_ON = session2.get('mo');
		var l = MAPLAYER_OPTIONS_ON.length;
		for ( var i = 0; i < l; i++)
			map.mapOptions.setLayer(i);
	}

	// Check if load delay necessary
	loaddelaytotal = session2.getMapRelatedCount();
	if (loaddelaytotal)
		map.enableLoadDelay();

	// Handle clicks as an identify request: query pushpin for features/data
	// and display result in info bubble.
	// TODO: refactor this long algorithm into functions
	PEvent.addListener(map, 'click', function(overlay, point) {
		PMIdentificationModule.clickHandler(overlay, point);
	});

	PEvent.addListener(map, 'dblclick', function() {
		map.cancelIdentify = true;
		map.closeInfoWindow();
	});

	// make sure links that pass on indicators are updated
	PEvent.addListener(map, 'removeindicator', function() {
		session2.remove('i');
		session2.remove('period');
	});

	// set up the searchbox and all it's tabs
	initSearchBox();

	// sites legend
	sitelegends = new PTRFSiteLegendGroup(map);
	sitelegends.addListener('change', function() {
		// Reduce the filters into a skinny (and therefore json-able)
		// map of filters to overlay set id's
		var filters = {};
		
		var sets = map.getOverlaySets(false, true);
		for(var i=0; i<sets.length; i++) {
			var set = sets[i];
			filters[set.id] = set.filtergroups;
		}
		
		session2.put('ofilters', filters);
		
		// Map labels may need to be updated when filters are changed.
		labelManager.updateMapLabels();
	});

	// overlay set events
	PEvent.addListener(map, 'addoverlayset', function(overlayset) {
		// We don't want to refresh the legend if we're just adding a label overlay set.
		if(overlayset.name.indexOf("labels") != 0) {
			sitelegends.refresh();
		}
		if(overlayset.type && overlayset.type == "old") {
			session2.put('o', POverlaySetUtil.toIdCsv(map.getOverlaySets(), "old"));
		} else if(overlayset.type && overlayset.type == "dl") {
			session2.put('dlo', POverlaySetUtil.toIdCsv(map.getOverlaySets(), "dl"));
		}
	});
	PEvent.addListener(map, 'removeoverlayset', function(overlayset) {
		// We don't want to refresh the legend if we're just removing a label overlay set.
		if(overlayset.name.indexOf("labels") != 0) {
			sitelegends.refresh();
		}
		// make a csv out of id's and put in session
		if(overlayset.type && overlayset.type == "old") {
			session2.put('o', POverlaySetUtil.toIdCsv(map.getOverlaySets(), "old"));
		} else if(overlayset.type && overlayset.type == "dl") {
			session2.put('dlo', POverlaySetUtil.toIdCsv(map.getOverlaySets(), "dl"));
		}
	});
	// overlay set events
	PEvent.addListener(map, 'setoverlaysets', function(overlaysets) {
		sitelegends.refresh();
	});

	// Create the place containment (breadcrumbs) widget
	var breadcrumbs = new PPlaceContainmentWidget(map, document.getElementById("breadcrumbs"),
			[ PPlaceType.COUNTRY, PPlaceType.STATE, PPlaceType.COUNTY, PPlaceType.COUNTY_SUBDIVISION,
			  PPlaceType.CITY, PPlaceType.ZIP, PPlaceType.CENSUSTRACT ]);

	// Request containments
	var geocoder = new PClientGeocoder();
	PEvent.addListener(map, 'moveend', function() {
		session2.put('curLat', map.getCenter().lat());
		session2.put('curLng', map.getCenter().lng());
		geocoder.getPlaceContainment(map.getCenter(),PPlaceTypeConfig.PPLACECONTAINMENT.getTypeByAbsoluteZoom(map.getAbsoluteZoom()), function(places) {
			// HACK: Prevent the breadcrumbs from adding Kansas on a default view of the US.
			// This happens because our default US view is centered over Kansas. If
			// mapstates.currentplace either has no label (from a fresh map or clicking
			// "Start Over") or is "United States" (from selecting or searching for the US as
			// a place) and the map's current zoom is 2, we don't want to display the state.
			if(places.length > 0 && map.getZoom() == 2 && mapstates.currentplace && (mapstates.currentplace.getLabel() == "" || mapstates.currentplace.getLabel() == "United States")) {
				breadcrumbs.refresh([places[0]]);
			} else {
				breadcrumbs.refresh(places);
			}
		});
		navteqCounter();
	});

	// change current place if one of the breadcrumbs is clicked
	breadcrumbs.addListener('click', function(place) {
		mapstates.currentplace = place;
		map.closeInfoWindow();
		clearPolygons(map);
		addPolygons(map, place);
		mapstates.add(new PMapState(map.getCenter(), map.getZoom(), map.getIndicator(), null, mapstates.currentplace));
	});

	var urlParams = getUrlParams();

	if (urlParams['cx'] && urlParams['cy'] && urlParams['cz']) {
		if ((session2.get('p') || session2.get('cp')) && loaddelaytotal > 1)
			loaddelaycount++;
		else if (session2.get('p') || session2.get('cp'))
			map.disableLoadDelay();
		map.setCenter(new PLatLng(urlParams['cy'], urlParams['cx']), urlParams['cz']);
	} else if(session2.get("curLat") && session2.get("curLng") && curZoom) {
		map.setCenter(new PLatLng(session2.get("curLat"), session2.get("curLng")), curZoom);
	} else {
		map.setCenter(new PLatLng(USA_LAT, USA_LNG), USA_ZOOM);
	}

	// Initialize the page from the session
	// check if break number in session
	if (session2.get('nb'))
		map.getLegend().setNumberOfBreaks(parseInt(session2.get('nb')));
	else
		map.getLegend().setNumberOfBreaks(DEFAULT_NUMBREAKS);

	// 3 different types of location to check (only allow one):
	// check if place in session
	if (session2.get('p') && (!urlParams['iwtype'] || urlParams['iwtype'] == 'place')) {
		var f = function(places) {
			loadDelayCheck();

			var place = places[places.length - 1];
			map.clearOverlays();

			if (place instanceof PPlace) {
				if (!urlParams['cx'] && !urlParams['cy'] && !urlParams['cz']){
					map.setCenterBounds(place.getBounds());
					if(curZoom)
						map.setZoom(curZoom);
				}

				var polygons = place.getVertices();
				if (polygons)
					addPolygons(map, place);
				mapstates.currentplace = place;
			} else if (!urlParams['cx'] && !urlParams['cy'] && !urlParams['cz']) {
				map.setCenter(place, curZoom || 13);
			}
			if (urlParams['iwx'] && urlParams['iwy']) {
				var title = "<div class='similarresults'>" + place.getLabel() + " (" + place.getType().getName() + ")</div>";
				point = place.getBounds().getCenter();
				map.openInfoWindowHtml(point, title);
			}
			// add to map state list
			mapstates.add(new PMapState(map.getCenter(), map.getZoom(), map.getIndicator(), null, mapstates.currentplace));
		}
		PPlaceLoader.load( [ session2.get('p') ], f);

		// check if address in session
	} else if (session2.get('place') && urlParams['iwtype'] != "identify") {
		var addy = session2.get('place');
		geocoder.getLatLng(addy, function(latlng) {
			if (latlng) {
				loadDelayCheck();
				var html = addy + "<br /><br />";
				addMarkerWindow(html, latlng);
				var zoom = urlParams['cz'];
				if (urlParams['cx'] && urlParams['cy'] && zoom) {
					map.setCenter(new PPoint(urlParams['cx'], urlParams['cy']), zoom)
				} else if (zoom) {
					map.setCenter(latlng, zoom)
				} else {
					zoom = curZoom || 13;
					map.setCenter(latlng, zoom);
				}

				// fire zoom end event because it's not getting called becaused technically the scale didn't change at this point
				// this way all the regular zoom end stuff happens, such as refreshing the map options
				map.kamap.triggerEvent(KAMAP_SCALE_CHANGED, map.getScale(zoom) );
			}
		});
	}

	// check if custom polygon in session
	if (session2.get('cp')) {
		polycreator.load(session2.get('cp'), function(places) {
			var placeids = [];
			for (var i=0; i<places.length; i++) {
				var place = places[i];

				// these ids go in the session
				placeids.push(place.id);

				loadDelayCheck();
				custom_place = place;

				polycreator.addPolylines(place, map);

				if (!urlParams['cx'] && !urlParams['cy'] && !urlParams['cz']) {
					map.setCenterBounds(place.getBounds());
				}
				// open custom poly infowindow from saved map
				if (urlParams['iwtype'] == 'cp')
					polycreator.polyline.polyline.infomarker.openInfoWindow(html);

				// Note: uncomment out this line when the option to fill the places within the custom region needs to be added back in to the app
				// There are a few places in MapCommon.js that need to be uncommented out, all are noted just as is it is here
				//polycreator.boundaryWidget.enable();
				//polycreator.boundaryWidget.show();
			}

			session2.put('cp', placeids.toString());

			// Once all the custom regions have been added populate My Custom Regions drop down
			// Have to add the custom regions first to know which places to highlight in the drop down
			polycreator.dropdown.setUsersPlaces();
		});
	}

	// Check if there are any overlay sets in the session.
	// First check for the old-style overlay sets.
	if (session2.get('o')) {
		var ids = session2.get('o').split(',');
		var l = ids.length;
		var sets = [];
		for ( var i = 0; i < l; i++) {
			// don't use transit points, they're added with transit layer, and aren't in hash
			var oldSet = getOverlaySetByIdAndType(ids[i], "old");
			if(oldSet != null) {
				var site = createSites(map, oldSet);
				if (site != null) {
					var filters = session2.getFilters(ids[i]);
					if (filters) {
						if (filters[0] && filters[0].values[0] == "COLORCODE") {
							var ftrs = [];
							var displayfilters = site.displayfiltergroups[filters[0].name];
							var m = displayfilters.length;
							for ( var j = 0; j < m; j++) {
								if (displayfilters[j].values[0] != "COLORCODE")
									ftrs.push(displayfilters[j]);
							}
							site.setFiltersByIcons(ftrs, site.colorcodes);
							site.filtergroups[filters[0].name] = [];
							site.filtergroups[filters[0].name].push(filters[0]);
						} else
							site.setFilters(filters);
					}
					sets.push(site);
				}
			}
		}
		map.setOverlaySets(sets);
	}
	// Next check for dataloader-created datasets.
	if(session2.get('dlo')) {
		var ids = session2.get('dlo').split(',');
		var l = ids.length;
		var sets = [];
		var displayNoSet = false;
		var loadedSets = [];
		for(var i=0; i<l; i++) {
			var dlSet = getOverlaySetByIdAndType(ids[i], "dl");
			if(dlSet == null) {
				displayNoSet = true;
				continue;
			}
			var site = createSites(map, dlSet);
			if(site != null) {
				map.addOverlaySet(site);
				loadedSets.push(ids[i]);
			}
		}
		if(displayNoSet) {
			var alerter = new PAlerter();
			alerter.popup("One or more of the user-created datasets on this map are not currently available.", null, null, "OK");
		}
		if(loadedSets.length > 0) {
			togglePublicCategories("show");
			// If the dloz argument was provided and we only loaded one user-created
			// dataset and no other datasets, we'll zoom in on the location of the
			// dataset on the map.
			if(loadedSets.length == 1 && session2.get('dloz') && !session2.get('o')) {
				// Get the coordinates of the bounding box for this dataset.
				// If there's an error or we didn't receive coordinates, we
				// just won't zoom the dataset in.
				$.ajax({
					url: "/s/?id=1&ty=data&t=site&act=b&did=" + loadedSets[0],
					dataType: "json",
					success: function(coords) {
						if(coords.minx && coords.miny && coords.maxx && coords.maxy) {
							// Center the map around the bounding
							// box of the set's points.
							var sw = new PLatLng(coords.miny, coords.minx);
							var ne = new PLatLng(coords.maxy, coords.maxx);
							map.setCenterBounds(new PLatLngBounds(sw, ne));
							// Take dloz out of the session so it
							// has to be put back in the session for
							// this happen again.
							session2.remove("dloz");
						}
					}
				});
			}
		}
	}

	if(curZoom && !(urlParams['cx'] && urlParams['cy'] && urlParams['cz'])) map.setZoom(curZoom);
	// check if indicator will need to load before using identify to open
	// infowindow
	if (urlParams['iwx'] && !session2.get('i') && urlParams['iwtype'] == 'identify')
		PMIdentificationModule.showInfoWindow(urlParams);

	var layerpoints = map.getCurrentMapType().getActiveLayerPoints();
	// zoom event to toggle points that go with a map layer
	PEvent.addListener(map, 'zoomend', function() {
		for (var i in layerpoints) {
			if (map.getScale() <= layerpoints[i].maxScale && layerpoints[i].isOn()) {// && !layerpoints[i].pointDataset.isOn()) {
				// add the set to the map
				if (!layerpoints[i].pointDataset.isOn())
					map.addOverlaySet(layerpoints[i].pointDataset);

				// set the layer to on because it's set up as default to be off
				layerpoints[i].pointDataset.on();
			}
			else if (map.getScale() > layerpoints[i].maxScale && layerpoints[i].isOn()) {
				// remove set from map because the map layer isn't on at this zoom
				if (layerpoints[i].pointDataset.isOn())
					map.removeOverlaySet(layerpoints[i].pointDataset);

				// have to set the layer to off so we know to turn it on when it needs to be on again
				layerpoints[i].pointDataset.off();
			}
		}

		navteqCounter();
	});

	//loadHovers();
}

function showColorOptions() {
	if (!isSubscriber()) {
		subscribeAlert();
		return;
	}
	if(editState & PIndicatorBreaks.EDITSTATE.exactBreaks) {
		var alerter = new PAlerter();
		alerter.popup("Legend colors cannot be changed for categorical data.", null, null, "OK");
		return;
	}
	var rampsDiv = document.getElementById('colorRampsBox');
	if (rampsDiv.style.display == "none")
		jQuery(rampsDiv).fadeIn(300);
	else
		jQuery(rampsDiv).hide();

	if (rampsDiv.hasChildNodes())
		return;

	var ramps = PColorRampOptions;
	for (var name in ramps) {
		// don't include in the menu
		if (ramps[name].excludeFromMenu)
			continue;

		var colors = ramps[name].ramp.getColors();
		var colorsDiv = document.createElement('div');
		colorsDiv.className = "colorRamps";
		for (var i=0; i<colors.length; i++) {
			var div = document.createElement('div');
			div.className = "color";
			div.style.background = "#" + colors[i].color;
			div.name = name;
			PEvent.addListener(div, 'click', function() {
				widget.changeColorRamp(this.name);
			});
			colorsDiv.appendChild(div);
		}
		rampsDiv.appendChild(colorsDiv);
		var d = document.createElement('div');
		d.style.clear = "both";
		d.style.padding = "2px";
		rampsDiv.appendChild(d);
	}
	var menuTimer = null;
	var clrcont = document.getElementById('colorRampsContainer');
	PEvent.addListener(clrcont, 'mouseout', function() {
		menuTimer = setTimeout(function() {
			jQuery(rampsDiv).hide();
		}, 300);
	});
	PEvent.addListener(clrcont, 'mouseover', function() {
		clearTimeout(menuTimer);
	});
}

function createSitesHtmlForLegend() {
	var site_containers = $(".site_container");
	var sitesDiv = "";
	if(site_containers.length > 0) {
		sitesDiv = '<div id="sitesLegendContainer"><h4>Sites</h4><div class="breakdown sites" style="padding-top: 0; color:#FFA800;">';
		for(var i=0;i<site_containers.length;i++){
			var siteLabel = $(site_containers[i]).find(".site_title");
			var siteImage = $(site_containers[i]).find(".site_image");

			sitesDiv += '<div>';
			sitesDiv += '<img src="' + $(siteImage[0]).attr("src") + '" /> ';
			sitesDiv += $(siteLabel[0]).html();
			sitesDiv += '</div>';

				var filters = $(site_containers[i]).find(".filter_container");
			for(var j=0; j<filters.length; j++){

				var filter =  $(filters[j]).find(".filter");
				if( filter.length > 0 ){
					var filterType =  $(filters[j]).find(".filter_type");
					var filterColors = $(filters[j]).find(".filter_colors");

					sitesDiv += '<div class="name">' + $(filter[0]).html() + "</div>";
					if( filterColors.length > 0){
						for(var k=0;k<filterColors.length;k++){
							sitesDiv += '<div class="value">' + $(filterColors[k]).html() + "</div>";
						}
					}else{
						sitesDiv += '<div class="value">';
							for(var k=0;k<filterType.length;k++){
								if(k!=0) sitesDiv += ", ";
								sitesDiv += $(filterType[k]).html();
							}
						sitesDiv += "</div>";
					}
				}
			}

		}
		sitesDiv += '</div></div>';
	}
	return sitesDiv;
}

function toggleOnMapLegend(elem, hide) {
	// elem is the element being clicked
	// if no elem is passed then the hide parameter must be passed
	if (elem)
		jQuery(elem).toggleClass("hide");

	// hide param will override having to send the element
	if (hide || (elem && jQuery(elem).hasClass("hide"))) {
		if (map.getIndicator())
			jQuery('#legContentHolder').css('display','none');

		jQuery('.legend_container').find('br').css('display','none');
		jQuery('#sitesLegendContainer').css('display','none');
		jQuery('#legend').find('.toggleText').html('Show Legend');

		// specific to map page
		jQuery('#onmaplegend').find('.toggleText').html('Show Legend');
	}
	else {
		if (map.getIndicator())
			jQuery('#legContentHolder').css('display','block');

		jQuery('.legend_container').find('br').css('display','inline');
		jQuery('#sitesLegendContainer').css('display','block');
		jQuery('#legend').find('.toggleText').html('Hide Legend');

		// specific to map page
		jQuery('#onmaplegend').find('.toggleText').html('Hide Legend');
	}
}

function resetMapAlert() {
	var text;
	if(PEnvironment.pageName == 'report_area') {
		text = "Are you sure you want to clear the location currently displayed?";
	} else if(PEnvironment.pageName == 'dataloader') {
		text = "Are you sure you want to discard any sites you have not saved and start over at the default view of the US?";
	} else {
		text = "Are you sure you want to clear any data layers or sites currently displayed and start over at the default view of the US?";
	}
	var alerter = new PAlerter();

	if(PEnvironment.pageName == 'analytics') {
		alerter.popup(text, null, null, "No", "Yes", resetAnalytics);
	} else if(PEnvironment.pageName == 'dataloader') {
		alerter.popup(text, null, null, "No", "Yes", resetDataloader);
	} else if(PEnvironment.pageName == 'widget') {
		alerter.popup(text, null, null, "No", "Yes", resetWidget);
	} else if(PEnvironment.pageName == 'report_area') {
		alerter.popup(text, null, null, "No", "Yes", resetReportArea);
	} else {
		alerter.popup(text, null, null, "No", "Yes", resetMap);
	}
}

// returns label used for link and url parameter to set the default report selected on reports page
function getPolyReportLinkInfo(id) {
	var info = {};
	info.page = "reports";
	if (id == 99800) {
		info.polygonOptionLabel = "See Brookings Institution LAA Report";
		info.reportParam = "&type=brookingslaa";
	} else if (id == 93400 || id == 96500 || id == 99150 || id == 103450 || id == 107000 || id == 109200 || id == 112000 || id == 114250) {
		info.polygonOptionLabel = "See Wilmington Trust Report";
		info.reportParam = "&type=h";
	} else if (id == 114550) {
		info.polygonOptionLabel = "See HUD NSP Neighborhood Change Report";
		info.page = "report_generate";
		info.reportParam = "&type=hud";
		info.isHudReport = true;
	} else if (id == 114050) {
		info.polygonOptionLabel = "See Wells Fargo Community Change Report";
		info.page = "report_generate";
		info.reportParam = "&type=wellsfargo";
		info.isWellsFargoReport = true;
	} else {
		info.polygonOptionLabel = "See Polygon Report";
		info.reportParam = "";
	}

	return info;
}

function isSupermarketIndicator(ind) {
	var supermarketInds = [9845403,9845303,9845304,9845300,9845306,9845312];
	for (var i=0; i<supermarketInds.length; i++) {
		if (ind.id == supermarketInds[i])
			return true;
	}

	return false;
}

function isSeeListAllowed(id, place) {
	var placetype = place.getType();
	// lists are only alloowed for these pointsets for census tracts and block groups
	var arr = [75550,87150,86500];
	var placeZoom = map.getBoundsZoomLevel(place.getBounds());

	// lists for NCCS dataset is allowed for custom regions only when zoomed in to level 11 or higher
	if (id == 86500 && place.isCustomOrPoly() && placeZoom >= 11)
		return true;

	for (var i=0; i<arr.length; i++) {
		if (id == arr[i]) {
			if (placetype != PPlaceType.BLOCKGROUP && placetype != PPlaceType.CENSUSTRACT) {
				customAlert("Lists of points for this dataset are only available for Census Tracts and Block Groups.");
				return false;
			}
		}
	}
	return true;
}

function mapOptionsDisable() {
	var elem = jQuery('#mapOptionsToggle');
	elem.addClass('disable');
}

function mapOptionsEnable() {
	var elem = jQuery('#mapOptionsToggle');
	elem.removeClass('disable');
}

function showSiteListAlert(set, place) {
	var func = function() {};
	var content = {};
	// Add the html needed for th ReportPins object to populate it with the list
	content.content =
'<div id="chartContainer" style="width:744px">' +
 '<div id="popup" class="popup alertList">' +
  '<div id="reportPins" class="reportPlaces">' +
   '<div class="title" align="left" id="title"></div>' +
   '<div class="buttons noPrint" id="pinOptions">' +
    '<a class="button" onclick="genericAlertDialog ({template: \'csv\', action: \'save\'})"><span>Save List</span></a>' +
    '<a class="button" onclick="rPins.downloadCSV()"><span>Download/Print List</span></a>' +
   '</div>' +
   '<div id="tableContainer"><span style="color:#ccc;font-style:italic">Loading...</span></div>' +
   '<div class="pageNav" onselectstart="return false;" style="display:block;">'+
    '<div class="pageLinks" onclick="rPins.changePage(0);">' +
     '<div class="button first"></div>' +
     '<div class="flt">First</div>' +
    '</div>'+
    '<div class="pageLinks" onclick="rPins.changePage(rPins.currentPage-1);">' +
     '<div class="button prev"></div>' +
     '<div class="flt">Prev</div>' +
    '</div>'+
    '<div class="flt">Page</div>' +
    '<div class="pageLinks" id="pageNums"></div>'+
    '<div class="pageLinks" onclick="rPins.changePage(rPins.currentPage+1);">' +
     '<div class="flt">Next</div>' +
     '<div class="button next"></div>' +
    '</div>'+
    '<div class="pageLinks" onclick="rPins.changePage();">' +
     '<div class="flt">Last</div>' +
     '<div class="button last"></div>' +
    '</div>'+
   '</div>'+
  '</div>' +
 '</div>' +
'</div>';
	content.popupStyle = "seelist";
	content.addCancel = false;
	var alerter = new PAlerter();
	alerter.popup(content, null, null, func, null, null, null, true);

	// pagePopUp is used in ReportPins and needs to be defined for the list to get populated
	pagePopUp = new PopUp();

	// Get all the sites within the selected place and load them in rPins to populate the table
	place.getMarkersWithin(set, function(markers) {
		rPins = new ReportPins();
		var count = 0;
		// make sure points are not a polyset
		if( !(markers[0] instanceof PMarker)) {
			count = markers[0];
		} else if( markers[0] instanceof PMarker && !markers[0].isPoly ) {
			count = markers.length;
		}
		rPins.load(place.getLabel(), set.id, set.type, set.getLabel(), place.id, '', count, null, place.getType().id, place.polysetid);
	});
}

function getCircle(miles, centerpoint) {
	dist = miles * 1609.344

	// Gets the distance for the radius
	var radiusX = centerpoint.moveBy("0 1N", dist);
	var radiusY = centerpoint.moveBy("90 1N", dist);
	var xRadiusMetres = radiusX.lat() - centerpoint.lat();
	var yRadiusMetres = radiusY.lng() - centerpoint.lng();

	// Points for setting zoom bounds
	var pointyeast = centerpoint.lng() + yRadiusMetres;
	var pointywest = centerpoint.lng() - yRadiusMetres;
	var pointxsouth = centerpoint.lat() - xRadiusMetres;
	var pointxnorth = centerpoint.lat() + xRadiusMetres;

	var sw = new PLatLng(pointxsouth, pointywest);
	var ne = new PLatLng(pointxnorth, pointyeast);

	circlepoints = [];
	for(var a=0; a<361; a+=5) {
		var aRad = a * (Math.PI / 180);
		var pointx = centerpoint.lat() + xRadiusMetres * Math.cos(aRad);
		var pointy = centerpoint.lng() + yRadiusMetres * Math.sin(aRad);
		var p = new PLatLng(pointx, pointy);
		circlepoints.push(p);
	}

	var cpoint = new PLatLngBounds(sw, ne);
	var obj = {'circlepoints':circlepoints, 'cpoint':cpoint};
	return obj;
}

function drawRadius(miles, centerpoint) {
	var c = getCircle(miles, centerpoint);
	var ciclepoints = c.circlepoints;
	var cpoint = c.cpoint;

	map.removeOverlay(poly);
	poly = new PPolygon(circlepoints,polycolor,polyweight,polyopacity,polyfill);

	map.setCenterBounds(cpoint);
	map.addOverlay(poly);

	return poly;
}

