/***************************************
 * Globals
 **************************************/

//array of map layers for options
//null replaces a layer when it's removed, null is needed to maintain old links that rely on the order of the layers
MAPLAYER_OPTIONS = [ PMapLayer.POINTLINE, PMapLayer.POLY, PMapLayer.COUNTY,
                     PMapLayer.ZIP, PMapLayer.TRACT, PMapLayer.BLOCK, PMapLayer.PARCEL,
                     PMapLayer.SLD_UPPER, PMapLayer.SLD_LOWER, null,
                     PMapLayer.CONGRESSIONAL, PMapLayer.SCHOOL, PMapLayer.CHI_WARD,
                     PMapLayer.CHI_AREA, PMapLayer.NJ_RENT_MKT, PMapLayer.CBSA07,
                     PMapLayer.MD07, PMapLayer.PARCEL_CAMDEN, PMapLayer.UMTRANSIT,
		     PMapLayer.CDBG, PMapLayer.STATE, PMapLayer.CITY, PMapLayer.COUNTY_SUBDIVISION ];

//order layers should appear in map options
MAPLAYER_OPTIONS_ORDER = [ PMapLayer.UMTRANSIT, PMapLayer.STATE, PMapLayer.CBSA07, PMapLayer.MD07, PMapLayer.COUNTY, PMapLayer.ZIP, PMapLayer.TRACT, PMapLayer.BLOCK,
			   PMapLayer.CONGRESSIONAL, PMapLayer.SLD_UPPER, PMapLayer.SLD_LOWER, PMapLayer.SCHOOL, PMapLayer.CDBG,
			   PMapLayer.POINTLINE, PMapLayer.POLY, PMapLayer.PARCEL, PMapLayer.PARCEL_CAMDEN, PMapLayer.CHI_WARD, PMapLayer.CHI_AREA, PMapLayer.NJ_RENT_MKT
			 ];

// There are 3 sections in the map options feature
// This is strictly done for the order that the map layers are shown in the map options feature
MAPLAYER_OPTIONS_ORDER = {};
MAPLAYER_OPTIONS_ORDER.national = [PMapLayer.STATE, PMapLayer.CBSA07, PMapLayer.MD07, PMapLayer.COUNTY_SUBDIVISION, PMapLayer.COUNTY, PMapLayer.CITY, PMapLayer.ZIP, PMapLayer.TRACT, PMapLayer.BLOCK, PMapLayer.PARCEL,
					PMapLayer.CONGRESSIONAL, PMapLayer.SLD_UPPER, PMapLayer.SLD_LOWER, PMapLayer.SCHOOL, PMapLayer.CDBG];
MAPLAYER_OPTIONS_ORDER.provincial = [PMapLayer.PARCEL_CAMDEN, PMapLayer.CHI_WARD, PMapLayer.CHI_AREA, PMapLayer.NJ_RENT_MKT];
MAPLAYER_OPTIONS_ORDER.features = [PMapLayer.UMTRANSIT, PMapLayer.POINTLINE, PMapLayer.POLY];

//array of map layers on/off
MAPLAYER_OPTIONS_ON = [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];

//array that maps boundaries to labels
MAPLAYER_LABELS = [];
MAPLAYER_LABELS[PMapLayer.POINTLINE.name] = PMapLayer.POINTLINE_LABEL;
MAPLAYER_LABELS[PMapLayer.POLY.name] = PMapLayer.POLY_LABEL;
MAPLAYER_LABELS[PMapLayer.COUNTY.name] = PMapLayer.COUNTY_LABEL;
MAPLAYER_LABELS[PMapLayer.ZIP.name] = PMapLayer.ZIP_LABEL;
MAPLAYER_LABELS[PMapLayer.TRACT.name] = PMapLayer.TRACT_LABEL;
MAPLAYER_LABELS[PMapLayer.BLOCK.name] = PMapLayer.BLOCK_LABEL;
MAPLAYER_LABELS[PMapLayer.SLD_UPPER.name] = PMapLayer.SLD_UPPER_LABEL;
MAPLAYER_LABELS[PMapLayer.SLD_LOWER.name] = PMapLayer.SLD_LOWER_LABEL;
MAPLAYER_LABELS[PMapLayer.CONGRESSIONAL.name] = PMapLayer.CONGRESSIONAL_LABEL;
MAPLAYER_LABELS[PMapLayer.SCHOOL.name] = PMapLayer.SCHOOL_LABEL;
MAPLAYER_LABELS[PMapLayer.CHI_WARD.name] = PMapLayer.CHI_WARD_LABEL;
MAPLAYER_LABELS[PMapLayer.CHI_AREA.name] = PMapLayer.CHI_AREA_LABEL;
MAPLAYER_LABELS[PMapLayer.NJ_RENT_MKT.name] = PMapLayer.NJ_RENT_MKT_LABEL;
MAPLAYER_LABELS[PMapLayer.CBSA07.name] = PMapLayer.CBSA07_LABEL;
MAPLAYER_LABELS[PMapLayer.MD07.name] = PMapLayer.MD07_LABEL;
MAPLAYER_LABELS[PMapLayer.CDBG.name] = PMapLayer.CDBG_LABEL;
MAPLAYER_LABELS[PMapLayer.CITY.name] = PMapLayer.CITY_LABEL;
MAPLAYER_LABELS[PMapLayer.COUNTY_SUBDIVISION.name] = PMapLayer.COUNTY_SUBDIVISION_LABEL;

//turn map options layers off
PMapLayer.ZIP.off(); PMapLayer.TRACT.off(); PMapLayer.BLOCK.off(); PMapLayer.PARCEL.off(); PMapLayer.SLD_UPPER.off(); PMapLayer.SLD_LOWER.off(); PMapLayer.ZIP_LABEL.off();
PMapLayer.TRACT_LABEL.off(); PMapLayer.BLOCK_LABEL.off(); PMapLayer.SLD_UPPER_LABEL.off(); PMapLayer.SLD_LOWER_LABEL.off(); PMapLayer.CONGRESSIONAL.off(); 
PMapLayer.CONGRESSIONAL_LABEL.off(); PMapLayer.SCHOOL.off(); PMapLayer.SCHOOL_LABEL.off(); PMapLayer.COUNTY.off(); PMapLayer.COUNTY_LABEL.off(); PMapLayer.CHI_WARD.off(); 
PMapLayer.CHI_WARD_LABEL.off(); PMapLayer.CHI_AREA.off(); PMapLayer.CHI_AREA_LABEL.off(); PMapLayer.NJ_RENT_MKT.off(); PMapLayer.NJ_RENT_MKT_LABEL.off(); 
PMapLayer.CBSA07.off(); PMapLayer.CBSA07_LABEL.off(); PMapLayer.MD07.off(); PMapLayer.MD07_LABEL.off(); PMapLayer.PARCEL_CAMDEN.off(); PMapLayer.UMTRANSIT.off(); 
PMapLayer.CDBG.off(), PMapLayer.CDBG_LABEL.off(); PMapLayer.STATE.off(); PMapLayer.CITY.off(); PMapLayer.COUNTY_SUBDIVISION.off();

//set up default map types with options preloaded
PMapType.DEFAULT = new PMapType( [ PMapLayer.BASE, PMapLayer.POLY, PMapLayer.TMINORROADS, PMapLayer.POINTLINE, PMapLayer.COUNTY_SUBDIVISION, PMapLayer.COUNTY, PMapLayer.CBSA07, PMapLayer.MD07, 
		PMapLayer.CITY, PMapLayer.ZIP, PMapLayer.TRACT, PMapLayer.BLOCK, PMapLayer.PARCEL, PMapLayer.SLD_UPPER, PMapLayer.SLD_LOWER, PMapLayer.CONGRESSIONAL, PMapLayer.SCHOOL, 
		PMapLayer.CHI_WARD, PMapLayer.CHI_AREA, PMapLayer.NJ_RENT_MKT, PMapLayer.PARCEL_CAMDEN, PMapLayer.UMTRANSIT, PMapLayer.CDBG, PMapLayer.STATE, 
		PMapLayer.POLY_LABEL, PMapLayer.POINTLINE_LABEL, PMapLayer.LABEL, PMapLayer.NEIGHBORHOOD, PMapLayer.CITIES, PMapLayer.COUNTY_LABEL, 
		PMapLayer.CBSA07_LABEL, PMapLayer.MD07_LABEL, PMapLayer.ZIP_LABEL, PMapLayer.TRACT_LABEL, PMapLayer.BLOCK_LABEL, PMapLayer.SLD_UPPER_LABEL, 
		PMapLayer.SLD_LOWER_LABEL, PMapLayer.CONGRESSIONAL_LABEL, PMapLayer.SCHOOL_LABEL, PMapLayer.CHI_WARD_LABEL, PMapLayer.CHI_AREA_LABEL, 
		PMapLayer.NJ_RENT_MKT_LABEL, PMapLayer.CDBG_LABEL ], new PProjection(54004), "Map");

//custom place type config for legend
PPlaceTypeConfig.PLEGEND = new PPlaceTypeConfig();
PPlaceTypeConfig.PLEGEND.zooms[0] = PPlaceType.STATE;
PPlaceTypeConfig.PLEGEND.zooms[3] = [PPlaceType.CITY,PPlaceType.SLD_LOWER,PPlaceType.SLD_UPPER,PPlaceType.COUNTY,PPlaceType.MD,PPlaceType.CBSA_07,PPlaceType.CONGRESSIONAL, PPlaceType.CDBG];
PPlaceTypeConfig.PLEGEND.zooms[5] = PPlaceType.SCHOOL;
PPlaceTypeConfig.PLEGEND.zooms[6] = PPlaceType.ZIP;
PPlaceTypeConfig.PLEGEND.zooms[7] = PPlaceType.COUNTY_SUBDIVISION;
PPlaceTypeConfig.PLEGEND.zooms[9] = PPlaceType.CENSUSTRACT;
PPlaceTypeConfig.PLEGEND.zooms[12] = PPlaceType.BLOCKGROUP;

//custom breadcrumb config
PPlaceTypeConfig.PPLACECONTAINMENT = new PPlaceTypeConfig();
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[0] = PPlaceType.STATE;
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[3] = PPlaceType.CBSA_07;
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[5] = PPlaceType.COUNTY;
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[7] = PPlaceType.COUNTY_SUBDIVISION;
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[8] = PPlaceType.CITY;
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[10] = PPlaceType.ZIP;
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[13] = PPlaceType.CENSUSTRACT;
PPlaceTypeConfig.PPLACECONTAINMENT.zooms[14] = PPlaceType.BLOCKGROUP;

//default number of breaks
var DEFAULT_NUMBREAKS = 5;
//track similar result click events
var similarClicks = [];

/****
** Color Ramps
*****/
PColorRamp.DEFAULT = new PColorRamp('trf', [new PColor("FFE6F4"),new PColor("E6CCE0"), new PColor("CCB1CC"), new PColor("B29AB8"),new PColor("9B839B"), new PColor("866F94"), new PColor("725B82"),new PColor("5D4770")]);
PColorRampOptions = [];
PColorRampOptions['default'] = new PColorRamp('trf', [new PColor("FFE6F4"),new PColor("E6CCE0"), new PColor("CCB1CC"), new PColor("B29AB8"),new PColor("9B839B"), new PColor("866F94"), new PColor("725B82"),new PColor("5D4770")]);
//PColorRampOptions['rust'] = new PColorRamp('rust',[new PColor('FFFFE5'), new PColor('FFF7BC'), new PColor('FEE391'), new PColor('FEC44F'), new PColor('FE9929'), new PColor('EC7014'), new PColor('CC4C02'), new PColor('8C2D04')]);
PColorRampOptions['olive'] = new PColorRamp('olive',[new PColor('FAF4C8'), new PColor('FCF7CA'), new PColor('F5E993'), new PColor('DECF7A'), new PColor('BAAE66'), new PColor('A3985A'), new PColor('736B36'), new PColor('59522A')]);
PColorRampOptions['blue'] = new PColorRamp('blue',[new PColor('DEEBFF'), new PColor('CCE0FF'), new PColor('B4CEFA'), new PColor('A2BBFA'), new PColor('88A4F7'), new PColor('6A82F7'), new PColor('5C60D6'), new PColor('4141D1')]);

var map = null;
var search = null;
var autosuggest = null;
var widget = null;
var initialplace = new PPlace();
initialplace.label = "USA";

var overlayset = new POverlaySet(637);
overlayset.setLabel("test points");
var sitelegends;
var global_period;
var custom_place = null;
var linkManager = new PLinkManager();
var printManager = new PPrintManager();
var session = PSession;
var loaddelaycount = 1;
var loaddelaytotal = 0;
var allowSelect = true;
//todo: remove this once session2 has assumed all duties of session

var polycreator;

var savemaplink;
var onmaplegendZoomEvent;
var printOrientation;

// Used for island printing. isIslandPrint set to true if a map is being printed and island printing
// is selected. Gets set back to false immediately after appending the isl_ and islt_ layer attributes.
// hideOutline gets set to true if we want to hide the outline of the selected boundary.
// (As of right now, this is only the case for Island Printing with a NON-custom region.)
// This gets set back to false immediately after appending the bo (boundary outline) parameter.
var isIslandPrint = false;
var hideOutline = false;

/***************************
 * CLASSES
 */

function addMarkerWindow(html, place) {
	var point = null;
	var addr = null;
	clearPolygons(map);

	if (place instanceof PPlace) {
		map.setCenterBounds(place.getBounds());
		point = place.getBounds().getCenter();
		var polygons = place.getVertices();
		if (polygons)
			addPolygons(map, polygons);
		mapstates.currentplace = place;
		map.infoWindowType = 'place';
	} else {
		map.setCenter(place, 13);
		point = place;
		mapstates.currentplace = null;
		addr = html.replace(/\<[^\>]+\>/g, "");

		// add see report link
		var link = generatePointReportLink(null, null, addr);
		var div = document.createElement('div');
		div.innerHTML = html;
		div.appendChild(link);
		html = div;
		map.infoWindowType = 'address';
	}
	map.openInfoWindow(point, html);

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

PMIdentificationPrinter = {
		placeTypeConfig :new PPlaceTypeConfig()
};
PMIdentificationPrinter.placeTypeConfig.zooms = PPlaceTypeConfig.PLEGEND.zooms
.slice();
PMIdentificationPrinter.placeTypeConfig.zooms[1] = PPlaceType.STATE;
PMIdentificationPrinter.placeTypeConfig.zooms[2] = PPlaceType.STATE;
PMIdentificationPrinter.placeTypeConfig.zooms[6] = PPlaceType.COUNTY;
PMIdentificationPrinter.placeTypeConfig.zooms[7] = PPlaceType.ZIP;
PMIdentificationPrinter.placeTypeConfig.zooms[8] = PPlaceType.ZIP;

PMIdentificationPrinter.findPlace = function(z, places) {
	// set up config
	return this.findPlaceTopDown(z, places);
}

PMIdentificationPrinter.findPlaceTopDown = function(z, places) {
	// find the right place according to the legend's place hierarchy
	var t;
	var p;
	var found = false;
	for ( var i = z; i < 16 && !found; i++) {
		t = this.placeTypeConfig.zooms[i];
		if (t) {
			for ( var j = 0; j < places.length; j++) {
				p = places[j];
				if (p.typeid == t.id) {
					found = true;
					break;
				}
			}
		}
	}

	if (!p) {
		p = places[places.length - 1];
	}
	// if (!p) p = places[0];
	return p;
}

PMIdentificationPrinter.findPlaceBottomUp = function(z, places) {
	// find the right place according to the legend's place hierarchy
	var t;
	var p;
	var found = false;
	for ( var i = z; i >= 0 && !found; i--) {
		t = PPlaceTypeConfig.PLEGEND.zooms[i];
		if (t) {
			for ( var j = 0; j < places.length; j++) {
				p = places[j];
				if (p.typeid == t.id) {
					found = true;
					break;
				}
			}
		}
	}

	if (!p) {
		p = places[places.length - 1];
	}
	// if (!p) p = places[0];
	return p;
}

PMIdentificationPrinter.selectPlace = function(z, places) {
	clearPolygons(map);

	var p = this.findPlace(z, places);
	if (!p)
		p = places[0];
	if (p)
		addPolygons(map, p.getVertices());
	return p;
}

//PMIdentificationPrinter.getBoundaryTypeAbove(types, places)

PMIdentificationPrinter.printPlaces = function(places, container, selectedPlace) {
	var tableElem = document.createElement("table");
	tableElem.id = "identify";
	tableElem.className = "cube";
	container.appendChild(tableElem);

	var tbodyElem = document.createElement("tbody");
	tableElem.appendChild(tbodyElem);

	var place;
	var type;
	var l = places.length;
	var teaser;
	var rowElem;
	for ( var i = 0; i < l; i++) {
		place = places[i];
		type = place.getType();

		// don't show this cbsa placetype and these other placetypes
		if (type == PPlaceType.CBSA || type == PPlaceType.CONGRESSIONAL || type == PPlaceType.SLD_UPPER || type == PPlaceType.SLD_LOWER)
			continue;

		highlight = type.id == selectedPlace.getType().id ? "hl" : "";
		if (type.id == selectedPlace.getType().id)
			mapstates.currentplace = place;

		rowElem = document.createElement("tr");
		rowElem.className = highlight;
		tbodyElem.appendChild(rowElem);

		var cellElem = document.createElement("td");
		rowElem.appendChild(cellElem);

		// teaser's don't need links
		if (teaser) {
			cellElem.className = teaser;
			cellElem.innerHTML = place.label + "<span class='placeType'> ("
			+ type.getName() + ")</span></td>";
		} else {
			this.addPlaceLink(place, cellElem);
		}
	}

	PMIdentificationPrinter.printSeeSites(container, selectedPlace);
	PMIdentificationPrinter.printSeePolygons(container);
}

/**
 * Returns a link that for the given place that affects the map.
 */
PMIdentificationPrinter.addPlaceLink = function(place, container) {
	var a = document.createElement("a");

	PEvent.addListener(a, 'mouseup', function() {
		map.setCenterBounds(place.bounds);
		clearPolygons(map);
		map.closeInfoWindow();
		addPolygons(map, place.getVertices());
		mapstates.add(new PMapState(map.getCenter(), map.getZoom(), map.getIndicator(), null, place));
		mapstates.currentplace = place;
		session2.put('p', place.id);
	});

	// block groups should be labeled by full fips code
	var label = place.getType()
	&& place.getType().id == PPlaceType.BLOCKGROUP.id ? place.identifier : place.label;
	a.innerHTML = label;
	a.className = "label";
	container.appendChild(a);

	var s = document.createElement("span");
	s.className = "placeType";
	s.innerHTML = "&nbsp;(" + place.getType().getName() + ")";
	container.appendChild(s);
}

PMIdentificationPrinter.printCustomPolyPlaces = function(polyplace, marker) {
	// set for saving map with infowindow
	map.infoWindowType = 'cp';
        map.saveInfoWindow = true;

	var container = document.createElement('div');
	container.id = "identifyContainer";
	var div = document.createElement('div');
	jQuery(div).css({
		fontSize:"18px",
		fontWeight:"bold",
		color:"#333"
	});
	div.innerHTML = polyplace.getLabel();
	container.appendChild(div);
	if (polyplace.description && polyplace.description != "null") {
		var div = document.createElement('div');
		jQuery(div).css({
			fontSize:"14px",
			color:"#333",
			margin:"0px"
		});
		div.innerHTML = polyplace.description;
		container.appendChild(div);
	}
	var zoom = document.createElement('a');
	zoom.innerHTML = "Zoom here";
	zoom.place = polyplace;
	// zoom in to custom region
	PEvent.addListener(zoom, 'mousedown', function() {
		map.setCenterBounds(this.place.getBounds());
	});
	container.appendChild(zoom);
	var span = document.createElement('span');
	span.innerHTML = " - ";
	container.appendChild(span);
	var remove = document.createElement('a');
	remove.innerHTML = "Remove";
	remove.place = polyplace;
	// removes the custom region from the map
	PEvent.addListener(remove, 'mousedown', function() {
		polycreator.removeCustomRegionFromMap(this.place);
		map.closeInfoWindow();
	});
	container.appendChild(remove);

	// anything in here doesn't go in the window widgets identify
	if (PAGE_ID != "w_") {
		container.appendChild(document.createElement('br'));
		container.appendChild(document.createElement('br'));

		var anchor1 = document.createElement("a");
		anchor1.innerHTML = "See Table";
		anchor1.style.marginRight = "15px";
		PEvent.addListener(anchor1, "click", function() {
			if (map.getIndicator()) {
				var indicator = map.getIndicator();
				var period = indicator.getPeriod();
				session2.put("i", indicator.id);
				session2.put("period", period);
			}
			window.location = "charts.jsp";
		});
		container.appendChild(anchor1);

		var anchor2 = document.createElement('a');
		anchor2.innerHTML = "Get Report";
		anchor2.style.marginRight = "15px";
		anchor2.polylabel = polyplace.getLabel();
		anchor2.polyid = polyplace.id;
		PEvent.addListener(anchor2, "click", function() {
			var ind = map.getIndicator();
			var report = "";
			// when indicator is from Supermarket Study of Low Access Areas category
			// select brookings report as default
			if (ind && isSupermarketIndicator(ind)) {
				report = "&type=brookingslaa";
			}

			window.location = "reports.jsp?area=custom&cpid=" + anchor2.polyid + report;
		});
		container.appendChild(anchor2);
		PMIdentificationPrinter.printSeeSites(container, polyplace);
		PMIdentificationPrinter.printSeePolygons(container);
	}

	// add more info if the place is a radius type
	if (polyplace.ctypeid == 3) {
		var div = document.createElement('div');
		div.className = 'extraInfo';
		div.innerHTML = "";
		if (polyplace.caddress) {
			var addr = "<div><div class='header'>Center of Radius:</div> <div class='content'>" + polyplace.caddress + "</div></div>";
			div.innerHTML += addr;
		}
		var radius = "<div><div class='header'>Radius:</div> <div class='content'>" + polyplace.radius + " Miles</div></div>";
		div.innerHTML += radius;
		container.appendChild(div);
	}

	return container;
//	marker.openInfoWindowHtml(container);
}

//This is here until we can handle enumerated indicators
PMIdentificationPrinter.printCubeWithEnum = function() {

}

PMIdentificationPrinter.printCube = function(cube, legend, container, isPublicUser) {

	// mark div as containing cube data (needed for knowing if we should close
	// it when indicator is removed)
	container.showsCube = true;

	var places = cube.getPlaces();
	var values = cube.values;

	if (cube.periods.length > 0) {
		var period = legend.getIndicator().getPeriod();
		var indicator = legend.getIndicator();
		var place;
		var typePlace;
		var typeInd;
		var obs; // the indicator value (aka observation)
		var shaded;
		var highlight = "";
		var teaser;
		var dispIndex = 0; // used to count the displayed rows (for shading
		// purposes) - needed due to place skipping

		// kluge: using myi as a global i seems to overtake local scoped i!
		var titleElem = document.createElement("div");
		titleElem.innerHTML = legend.getIndicator().getLabel();
		titleElem.className = "title";
		container.appendChild(titleElem);

		var tableElem = document.createElement("table");
		container.appendChild(tableElem);
		tableElem.id = "identify";
		tableElem.className = "cube";
		var tbodyElem = document.createElement("tbody");
		tableElem.appendChild(tbodyElem);

		// print column headers
		var rowElem = document.createElement("tr");
		tbodyElem.appendChild(rowElem);
		var cellElem = document.createElement("th");
		cellElem.style.backgroundColor = "#EEEEEE";
		rowElem.appendChild(cellElem);
		cellElem.innerHTML = "Area";
		cellElem = document.createElement("th");
		cellElem.style.backgroundColor = "#EEEEEE";
		rowElem.appendChild(cellElem);
		cellElem.innerHTML = "Value";

		// print each place and values
		var l = places.length;
		for ( var myi = 0; myi < l; myi++) {

			// highlight place and observation that appears shaded on the map
			place = places[myi];
			typePlace = place.getType();
			typeInd = legend.getBoundaryType();

			var iPlaceType = false;
			
			if (typePlace && typeInd) {
				highlight = typePlace.id == typeInd.id ? "hl" : "";
				if (typePlace.id == typeInd.id){
					mapstates.currentplace = place;
					iPlaceType = true;
				}
			}
			// block these placetypes from appearing in identify unless it's the geography being displayed
			if ((typePlace == PPlaceType.CONGRESSIONAL || typePlace == PPlaceType.SLD_UPPER || typePlace == PPlaceType.SLD_LOWER) && (typeInd && typeInd.id != typePlace.id))
				continue;

			// Only print value for place being shaded by for the analytics page.
			if(PAGE_ID != "a_" || iPlaceType == true) {

				var isNum = null;
				// get value of indicator for the place
				obs = values[period][place.id][indicator.id];
				if (isPublicUser) {
					obs = '<b>-</b>';
				} else if (typeof obs == "string") {
					obs = obs;
				} else if (obs == "-9999") {
					obs = "Insufficient Data";
				} else if (obs || obs == 0) {
					obs = PWebUtil.formatNumber( obs, indicator.unit ); 
					isNum = true;
				} else if (typeInd && typeInd.id == typePlace.id) {
					obs = "";
				} else {
					continue;
				}
	
				// used to alternate row shading
				dispIndex++;
				shaded = dispIndex % 2 == 1 ? "on" : "off";
	
				rowElem = document.createElement("tr");
				tbodyElem.appendChild(rowElem);
				rowElem.className = highlight;
	
				cellElem = document.createElement("td");
				rowElem.appendChild(cellElem);
				cellElem.className = "place " + shaded;
				this.addPlaceLink(place, cellElem);
	
				cellElem = document.createElement("td");
				// IE adds a line break when a negative sign is used in front of the number, so this fixes that
				if (isNum)
					cellElem.style.whiteSpace = "nowrap";

				rowElem.appendChild(cellElem);
				cellElem.className = "obs " + shaded;
				cellElem.innerHTML = obs;
		
				if (isSubscriber() && place.gsussdid && indicator.getSource() == "GreatSchools") {
					rowElem = document.createElement("tr");
					tbodyElem.appendChild(rowElem);
	
					cellElem = document.createElement("td");
					cellElem.colSpan = 2;
					rowElem.appendChild(cellElem);
					cellElem.innerHTML = "<br /><a target='_blank' href='http://www.greatschools.net/cgi-bin/"
						+ place.state.toLowerCase()
						+ "/district_profile/"
						+ place.gsussdid
						+ "'>http://www.greatschools.net/cgi-bin/"
						+ place.state.toLowerCase()
						+ "/district_profile/"
						+ place.gsussdid + "</a>";
				}
			}
		}
		// Just for HUD NSP datasets
		if (indicator.id == 9627155 || indicator.id == 9627151 || indicator.id == 9627201 || indicator.id == 9627156) {
			rowElem = document.createElement("tr");
			tbodyElem.appendChild(rowElem);

			cellElem = document.createElement("td");
			cellElem.colSpan = 2;
			rowElem.appendChild(cellElem);
			cellElem.innerHTML = "<br /><a target='_blank' href='http://www.huduser.org/publications/commdevl/nsp_target.html'>http://www.huduser.org/publications/commdevl/nsp_target.html</a>";
		}

		if (indicator.getSource() == "IRS & The Brookings Institution") {
			rowElem = document.createElement("tr");
			tbodyElem.appendChild(rowElem);

			cellElem = document.createElement("td");
			cellElem.colSpan = 2;
			rowElem.appendChild(cellElem);
			cellElem.innerHTML = "<br /><a target='_blank' href='http://www.brookings.edu/metro/EITC/EITC-Homepage.aspx'>http://www.brookings.edu/metro/EITC/EITC-Homepage.aspx</a>";
		}

		if (indicator.id == 9639604) {
			rowElem = document.createElement("tr");
			tbodyElem.appendChild(rowElem);

			cellElem = document.createElement("td");
			cellElem.colSpan = 2;
			rowElem.appendChild(cellElem);
			cellElem.innerHTML = "<br /><a target='_blank' href='/our-data-directory.html#trf_NIDAdescriptionmatrix'>/our-data-directory.html#trf_NIDAdescriptionmatrix</a>";
		}

		container.appendChild(document.createElement("br"));
	}
}

PMIdentificationPrinter.printAttributes = function(attributes, num, marker) {
	var tabs = [];
	var i = 1;
	var j = 0;
	var l = attributes.length;
	while (j < l) {
		var div = document.createElement('div');
		div.id = "identifyContainer";
		div.className = "pointAttributes";
		var cnt = 0;
		while (cnt < 10) {
			if (j == l)
				break;
			var value;
			if (attributes[j].value == -9999)
				value = "N/A";
			else if (attributes[j].unit)
				value = PWebUtil.formatNumber(attributes[j].value,
						attributes[j].unit);
			else
				value = attributes[j].value;
			if (attributes[j].value != "" && attributes[j].value != "null" || attributes[j].value == "0") {
				if (typeof value == 'string' && value.match('http://'))
					value = "<a href='" + value + "' target='new' style='color:#5D83D0;text-decoration:underline;'>" + value + "</a>";
				var b = document.createElement('b');
				b.innerHTML = attributes[j].name + ": ";
				var span = document.createElement('span');
				span.innerHTML = value + "<br />";
				div.appendChild(b);
				div.appendChild(span);
				cnt++;
			}
			j++;
		}
		if (num)
			var index = " - " + num;
		else
			var index = "";

		// specific to TRF Supermarket Study of LAA for Brookings Institution polys
		// adds a link for each tab to the data directory
		if (marker.datasetID == 91450) {
			div.appendChild(document.createElement('br'));
			var datadir = document.createElement('a');
			datadir.innerHTML = "Details and Methodology";
			datadir.target = "_blank";
			datadir.href = "our-data-directory.html#Details for TRF Supermarket Study of LAA for Brookings Institution";
			div.appendChild(datadir);
		}

		// specific to Wilmington Trust polys
		// adds a link for each tab to the data directory
		if (marker.datasetID == 93400) {
			div.appendChild(document.createElement('br'));
			var datadir = document.createElement('a');
			datadir.innerHTML = "Details";
			datadir.target = "_blank";
			datadir.href = "our-data-directory.html#Details for Wilmington Trust";
			div.appendChild(datadir);
		}

		if (div.hasChildNodes())
			tabs.push(new PInfoWindowTab("Info " + i + index, div));
		i++;
	}
	return tabs;
}

PMIdentificationPrinter.printSameAddresses = function(attributes, point, marker) {
	var pmid = this;
	var urlParams = PWebUtil.parseQuery(window.location.search);
	var tabs = [];
	var i = 1;
	var j = 0;
	if (attributes.length > 1) {
		while (j < attributes.length) {
			var cnt = 0;
			var div = document.createElement('div');
			div.id = "identifyContainer";
			div.className = "pointAttributes";
			var h4 = document.createElement('h4');
			h4.innerHTML = attributes[j][0].name;
			div.appendChild(h4);
			while (cnt < 10) {
				if (j == attributes.length)
					break;
				var value;
				if (attributes[j][0].unit)
					value = PWebUtil.formatNumber(attributes[j][0].value, attributes[j][0].unit);
				else
					value = attributes[j][0].value;
				if (attributes[j][0].value != ""
					&& attributes[j][0].value != "null") {
					var link = document.createElement('a');
					link.innerHTML = j + 1 + ") " + value + "<br />";
					link.attr = attributes[j];
					link.num = j;
					PEvent.addListener(link, 'mouseup', function() {
						pmid.addAttributeTabs(this.attr, tabs, point, this.num + 1, marker);
						// stores the link selected for when user saves map with infowindow
						pmid.selectedLink = this.num;
					});
					// Stores the attributes for the saved site that was selected
					if (urlParams['iwlink'] && urlParams['iwlink'] == j)
						pmid.savedMarkerAttr = attributes[j];
					div.appendChild(link);
					cnt++;
				}
				j++;
			}
			tabs.push(new PInfoWindowTab("Sites", div));
		}
		return tabs;
	}
}

PMIdentificationPrinter.addAttributeTabs = function(attributes, tabs, point, num, marker) {
	var attributeTabs = PMIdentificationPrinter.printAttributes(attributes, num, marker);
	var newtabs = [];
	for ( var i = 0; i < tabs.length; i++)
		newtabs.push(tabs[i]);
	for ( var i = 0; i < attributeTabs.length; i++)
		newtabs.push(attributeTabs[i]);

	var t = tabs.length;
	map.openInfoWindowTabs(point, newtabs);
	map.getInfoWindow().selectTab(t);
}

PMIdentificationPrinter.addFakes = function(places, cube) {
	var fake = new PPlace();
	fake.label = "Coming Soon";
	fake.typeid = PPlaceType.BLOCKGROUP.id;
	fake.id = 0;
	places.push(fake);

	if (cube) {
		var period = cube.getPeriods()[0];
		var indicator = cube.getIndicators()[0];

		if (cube.getPlaces() != places)
			cube.addPlace(fake);
		cube.values[period][fake.id] = [];
		cube.values[period][fake.id][indicator.id] = '';
	}
}

PMIdentificationPrinter.printComingSoon = function(blurb, container) {
	container.style.textAlign = "center";
	container.style.width = "200px";
	// necessary for closing bubble automatically when indicator changes
	container.id = "identifyContainer";
	container.showsCube = true;
	var msg = '<h2 style="font-style: italic; color: #f00">Coming Soon</h2>';
	msg += "<p style=\"text-align: justify\">" + blurb + "</p>";
	container.innerHTML = msg;
}

//Only used for HUD MVA dataset
PMIdentificationPrinter.printHudMVA = function(places, indicator, blurb,
		container) {
	// Only use block group place
	for ( var i = 0; i < places.length; i++) {
		if (places[i].getType() == PPlaceType.BLOCKGROUP)
			var place = places[i];
	}

	container.style.width = "320px";
	// necessary for closing bubble automatically when indicator changes
	container.id = "identifyContainer";
	container.style.width = "240px";
	container.className = "identify";
	container.style.fontSize = "12px";
	container.style.color = "#333333";
	container.showsCube = true;
	var title = document.createElement('div');
	title.className = "title";
	title.style.color = "#000000";
	title.style.fontSize = "19px";
	title.style.fontWeight = "bold";
	title.style.paddingBottom = "13px";

	title.innerHTML = indicator.getLabel();
	container.appendChild(title);
	if (place) {
		var placeDiv = document.createElement('div');
		this.addPlaceLink(place, placeDiv);
		container.appendChild(placeDiv);
		clearPolygons(map)
		addPolygons(map, place.getVertices());
	}
	var content = document.createElement('div');
	content.innerHTML = '<p style="text-align: justify">' + blurb + '</p>';
	content.innerHTML += "<br /><a target='_blank' href='http://www.huduser.org/publications/commdevl/nsp_target.html'>http://www.huduser.org/publications/commdevl/nsp_target.html</a>";
	container.appendChild(content);
}

PMIdentificationPrinter.printSeeSites = function(container, selectedPlace) {
	// don't show see list links for window widget
	if (PAGE_ID == "w_")
		return;

	var overlays = map.getOverlaySets();
	if (overlays.length == 0)
		return;

	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 printSeePolygons.
		if(overlays[i].isPolySet(overlays[i].id, map))
			continue;
		
		var anchor = document.createElement('a');
		anchor.style.marginRight = "5px";
		anchor.innerHTML = "See List of " + overlays[i].getLabel();
		anchor.setid = overlays[i].id;
		anchor.place = selectedPlace;
		PEvent.addListener(anchor, "click", function() {
			// 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(this.setid, this.place))
				return;

			window.location = "charts.jsp?showlist=" + this.setid;
		});
		container.appendChild(document.createElement("br"));
		container.appendChild(anchor);
		var img = document.createElement('img');
		img.src = overlays[i].icon.image;
		container.appendChild(img);
	}
}

PMIdentificationPrinter.printSeePolygons = function(container) {
	// Don't show See Polygons list for the window widget
	if(PAGE_ID != "w_") {
		// Determine if there are currently any polygons on the map,
		// and if so, store which pointsets have them.
		var polygonSets = [];
		var pointSets = map.getOverlaySets();
		var ind = map.getIndicator();
		for(var i=0; i<pointSets.length; i++) {
			// don't show link when overlays are the TRF Supermarket Study of LAA for Brookings Institution polys and
			// when indicator is either of the following Supermarket indicators
			if (pointSets[i].id == 91450) {
				if (ind && isSupermarketIndicator(ind)) {
					continue;
				}
			}

			if(POverlaySet.PointAndPolygonSets[pointSets[i].id])
				polygonSets.push(i);
		}

		if(polygonSets.length > 0) {
			// There are polygons on the map. For each set of polygons, add
			// a link to see the list of polygons in the selected boundary.
			container.appendChild(document.createElement("br"));
			for(i=0; i<polygonSets.length; i++) {
				var anchor = document.createElement('a');
				anchor.style.marginRight = "5px";
				anchor.innerHTML = "See List of " + pointSets[polygonSets[i]].getLabel() + " polygons";
				anchor.setid = pointSets[polygonSets[i]].id;
				PEvent.addListener(anchor, "click", function() {
					window.location = "charts.jsp?showlist=" + POverlaySet.PointAndPolygonSets[this.setid].polygonID;
				});
				container.appendChild(document.createElement("br"));
				container.appendChild(anchor);
				var img = document.createElement('img');
				img.src = polyicon.image;
				container.appendChild(img);
			}
		}
	}
}

PMIdentificationModule = {};
PMIdentificationModule.showInfoWindow = function(urlParams) {
	this.clickHandler(null, new PLatLng(urlParams['iwx'], urlParams['iwy']));
}
PMIdentificationModule.clickHandler = function(overlay, point) {
	// abort if custom region is being drawn
	if (isCustomRegionOn())
		return;

	// already haven overlay in the browser so don't query server
	if (overlay) {
		var attributes = overlay.getAttributes();
		if (attributes.length > 0)
			overlay.openInfoWindowTabs(PMIdentificationPrinter.printAttributes(attributes, null, overlay));
	} else {
		map.saveInfoWindow = true;
		map.infoWindowType = 'identify';
		
		// create handler to render the output of the identify query
		var f = function(markers, places, cube) {
			var ind = map.getIndicator();
			var boundaryType = map.getLegend() ? map.getLegend().getBoundaryType() : null;
			// display pin info differently than place/cube result
			if (markers && markers.length > 0) {
				var sitesAttributes = [];
				// check for sites with same coordinates
				for ( var i = 0; i < markers.length; i++) {
					if (markers[0].getPoint().lat() == markers[i].getPoint().lat() && markers[0].getPoint().lng() == markers[i].getPoint().lng()) {
						sitesAttributes.push(markers[i].getAttributes());
					}
				}
				if (sitesAttributes.length > 1)
					var tabs = PMIdentificationPrinter.printSameAddresses(sitesAttributes, markers[0].getPoint(), markers[0]);
				else {
					var attributes = markers[0].getAttributes();
					var tabs = PMIdentificationPrinter.printAttributes(attributes, null, markers[0]);
				}
				for ( var i = 0; i < tabs.length; ++i) {
					if(markers[0].isPoly) {
						// The icon clicked was for a polygon.
						
						// Determine the bdid of the currently selected polygon.
						// Loop through the point and polygon sets on the map until
						// the one is found that matches this polygon's dataset id.
						var bdid;
						var polysetid;
						var pointSets = map.getOverlaySets();
						for(var j=0; j<pointSets.length; j++) {
							// For each pointset, see if it contains a polygon set.
							if(POverlaySet.PointAndPolygonSets[pointSets[j].id]) {
								// It does. See if its dataset id matches this polygon's.
								if(POverlaySet.PointAndPolygonSets[pointSets[j].id].polygonID == markers[0].datasetID) {
									// This is it. Grab the bdid (and polyset id for reports).
									bdid = POverlaySet.PointAndPolygonSets[pointSets[j].id].bdid;
									polysetid = POverlaySet.PointAndPolygonSets[pointSets[j].id].polygonID;
								}
							}
						}
						
						// Get the rest of the polygon info we need.
						var pname = markers[0].polyName;
						var plat = markers[0].getPoint().lat();
						var plng = markers[0].getPoint().lng();
						
						// Display links based on what kind of polygon we're dealing with.
						if(markers[0].polyType == "polygon" && bdid != null) {
							// Add links for regular polygons.
							jQuery(tabs[i].content).append("<br />");
							// Add the 'See Table' link
							jQuery(tabs[i].content).append(generatePolygonTableLink(bdid, pname, plat, plng));
							// Add the 'See Polygon Report' link
							jQuery(tabs[i].content).append(generatePolygonReportLink(bdid, polysetid, pname, plat, plng, "polygon", true));
							// Add the 'See Radius Report' link
							jQuery(tabs[i].content).append(generatePolygonReportLink(bdid, polysetid, pname, plat, plng, "pradius", false));
							// Add the 'See List of' links (for polygons)
							jQuery(tabs[i].content).append(generatePolygonPointlistLinks(bdid, pname, plat, plng));
						} else if(markers[0].polyType == "line") {
							// Add links for line polygons.
							// None exist at this time.
						} else if(markers[0].polyType == "specialized") {
							// Add links for specialized polygons.
							// None exist at this time.
						}
					} else {
						// The icon clicked was for a point.
						
						// Add the 'See Radius Report' link.
						jQuery(tabs[i].content).append(generatePointReportLink(markers[0].getPoint().lat(), markers[0].getPoint().lng()));
					}
				}
				map.openInfoWindowTabs(markers[0].getPoint(), tabs);

				var pmid = PMIdentificationPrinter;
				var urlParams = PWebUtil.parseQuery(window.location.search);
				// Only run this for a saved map, otherwise the identify
				// continues to use the urlparams
				if (!pmid.savedMapLoaded && urlParams['iwtab']) {
					pmid.savedMapLoaded = true;

					// Adds the attribute tabs for the saved pin from a multiple
					// sites pin
					if (urlParams['iwlink'])
						pmid.addAttributeTabs(pmid.savedMarkerAttr, tabs,markers[0].getPoint(), urlParams['iwlink'], markers[0]);

					if (urlParams['iwtab']) {
						var t = urlParams['iwtab'];
						map.getInfoWindow().selectTab(t);
					}
				}
			} else if (places || cube) {
				clearPolygons(map);
				// encase identify result in div
				var identifyDiv = document.createElement("div");
				identifyDiv.id = "identifyContainer";
				identifyDiv.className = "identify";
				if (cube) {
					
					// find shaded place and draw border around it
					var typeInd = null;
					var p = null;
					{
						var l = places.length;
						var typePlace;
						typeInd = map.getLegend().getBoundaryType();
						if(map.getLegendMerger()){
							var indLegend;
							for(var i=0; indLegend = map.getLegendMerger().getLegend(i); i++){
								if(indLegend.containsIndicator()){
									var tmpPlaceType = indLegend.legend.getBoundaryType();
									if(typeInd == null){
										typeInd = tmpPlaceType;
									}else if(tmpPlaceType && comparePlaceType(tmpPlaceType, typeInd) > 0){
										typeInd = tmpPlaceType;
									}
								}
							}
						}
						for ( var i = l-1; i >=0 ; i--) {
							p = places[i];
							typePlace = p.getType();
							if (typePlace && typeInd && typePlace.id == typeInd.id) {
								break;
							} else {
								p = null;
							}
						}
					}
					if (p) {
						clearPolygons(map)
						addPolygons(map, p.getVertices());
						var currentPlace = p;
						session2.put("p", currentPlace.id);
					}
					var isPublicUser = !(session2.get("_userid"));
					if(map.getLegendMerger()){
						for(var i=0; i<3; i++)
							if(map.getLegendMerger().getLegend(i).getIndicator())
								PMIdentificationPrinter.printCube(cube, map.getLegendMerger().getLegend(i).legend, identifyDiv, isPublicUser);
						if(typeInd != null){
							var pSpans = $(identifyDiv).find(".placeType");
							for(var i=0; i<pSpans.length; i++) 
								if(pSpans[i].innerHTML.indexOf(typeInd.getName(),0)>=0)
									pSpans[i].innerHTML = "(" + typeInd.getName() + " - Outlined)";
						}
						if (!isSubscriber()) {
							var div = document.createElement('div');
							var text = "Become a <a href='subscribe.jsp'>Subscriber</a> to use the Analytics feature.";
							div.innerHTML = text;
							identifyDiv.appendChild(div);
						}
						PMIdentificationPrinter.printSeeSites(identifyDiv, currentPlace);
						PMIdentificationPrinter.printSeePolygons(identifyDiv);
					}else{
						PMIdentificationPrinter.printCube(cube, map.getLegend(), identifyDiv, isPublicUser);
					}

					if(PAGE_ID != "a_") {
						// Registered users get charts link while others get sign up link
//console.log(isPublicUser)
						if (isPublicUser) {
							var span = document.createElement("span");
							identifyDiv.appendChild(span);
							span.innerHTML = '<a href="register.jsp?reg_type=reg">Register</a> now for free to see the information about this place.<br /><br />';
						} else {
							// anything in here doesn't go in the window widgets identify
							if (PAGE_ID != "w_") {
								var hasData = false;
								var period = cube.getPeriods()[0];
	                                                        var indicator = cube.getIndicators()[0];
								for( var i = 0; i < places.length; ++i ) {
									var place = places[i];
									if( cube.values[period][place.id][indicator.id] !== null && !isNaN(cube.values[period][place.id][indicator.id]) ) {
										hasData = true;
										break;
									}
								}
								if( hasData ) {
								// create charts link
								var anchor = document.createElement("a");
								anchor.innerHTML = "See Table";
								anchor.style.marginRight = "15px";
								PEvent.addListener(anchor,"click",function() {
									var placeIds = [];
									var l = places.length;
									var place;
									var shouldInclude = false;
									var hasData = false;

									var period = cube.getPeriods()[0];
									var indicator = cube.getIndicators()[0];

									// gather ids of palces
									for ( var i = 0; i < l; i++) {
										place = places[i];

										hasData = cube.values[period][place.id][indicator.id] != null;

										// don't include states in charts if indicator is count (to make chart more meaningful)
										shouldInclude = indicator.getMeasurement() != "count"
											|| (place.getType() != PPlaceType.STATE)
											|| (map.getLegend().getBoundaryType().id == PPlaceType.STATE.id);

										if (shouldInclude && hasData) placeIds.push(place.id);
									}

									// identify means user selected the place and indicator
									session2.put("p", placeIds.join(","));
									session2.put("i", cube.getIndicators()[0].id);
									session2.put("period", cube.getPeriods()[0]);
									window.location = "charts.jsp";
								});
								identifyDiv.appendChild(anchor);
								}
							}
						}
						// anything in here doesn't go in the window widgets identify
						if (PAGE_ID != "w_") {
							// Add report link to identify
							var anchor = document.createElement('a');
							anchor.innerHTML = "Get Report";
							anchor.style.marginRight = "15px";
							if(currentPlace){
								anchor.placetypeid = currentPlace.getType().id;
								anchor.placeid = currentPlace.id;
								anchor.state = currentPlace.getState();
								anchor.label = currentPlace.getLabel();
							}
							for ( var i = 0; i < places.length; i++) {
								if (places[i].getType() == PPlaceType.COUNTY)
									anchor.county = places[i].getLabel();
							}
							PEvent.addListener(anchor, "click", function() {
								if(currentPlace)
									session2.put("p", currentPlace.id);

								var ptype = "ptype=" + anchor.placetypeid;
								var state = "";
								if (anchor.state != "null")
									state = "&state=" + anchor.state;
								var placeid = "&pid=" + anchor.placeid;
								if (anchor.county)
									var county = "&county=" + anchor.county;
								else
									var county = "";

								var ind = map.getIndicator();
								var report = "";
								// when indicator is from Supermarket Study of Low Access Areas category
								// select brookings report as default
								if (ind && isSupermarketIndicator(ind)) {
									report = "type=brookingslaa";
								}

								// No url params for Block Groups 
								if (anchor.placetypeid == "15")
									window.location = "reports.jsp?" + report;
								else
									window.location = "reports.jsp?" + ptype + placeid + county + state + "&" + report;
							});
							identifyDiv.appendChild(anchor);
							PMIdentificationPrinter.printSeeSites(identifyDiv, currentPlace);
							PMIdentificationPrinter.printSeePolygons(identifyDiv);
						}
						// create link to data directory for mva indicators with color-coded grid images in data directory
						if (ind.getMeasurement() == "enum") {
							var mva_charts = [196211,196126,9609712,196193,196510,196528,198853,196544,198870,198887,9627551,196300,9844405];
							for (var m=0; m<mva_charts.length; m++) {
								if (ind.getID() == mva_charts[m]) {
									var link = document.createElement('a');
									link.innerHTML = "See table of underlying values";
									if (mva_charts[m] == 196126)
										link.innerHTML = "See cluster descriptions";
									link.target = "_blank";
									link.href = "/our-data-directory.html#mva_" + ind.getID();
									identifyDiv.appendChild(document.createElement('br'));
									identifyDiv.appendChild(document.createElement('br'));
									identifyDiv.appendChild(link);
								}
							}
							var mva_charts = [196211,196126,9609712,196193,196510,196528,198853,196544,198870,198887,9627551,196300,9844405];
							for (var m=0; m<mva_charts.length; m++) {
								if (ind.getID() == mva_charts[m]) {
									var link = document.createElement('a');
									link.innerHTML = "See table of underlying values";
									link.target = "_blank";
									link.href = "/our-data-directory.html#mva_" + ind.getID();
									identifyDiv.appendChild(document.createElement('br'));
									identifyDiv.appendChild(document.createElement('br'));
									identifyDiv.appendChild(link);
								}
							}
						}
					}
				} else if (places) {
					// outline appropriate place
					var p = PMIdentificationPrinter.selectPlace(map.getZoom(), places);
					// show bubble
					PMIdentificationPrinter.printPlaces(places, identifyDiv, p);
					if (p){
						session2.put("p", p.id);
						session2.put("pLabel", p.getLabel())
					}
				}
				map.openInfoWindow(point, identifyDiv);
			}
		};

		var legend = map.legend;
		var options = {
				showmarker :true,
				showindicator :true,
				// not interested in just places
				showplaces :true,
				// optimize queries: we don't need palces or cube if marker is found.
				nonmixedresult :true,
				// only show areas shaded or larger
				uptotype :(legend.getIndicator() ? legend.getBoundaryType() : null)
		};
		
		if(map.getLegendMerger()){
			var uptotype = null;
			var legendMerger = map.getLegendMerger();
			var legend = null;
			options.boundaryTypes = [];
			for(var i=0; legend=legendMerger.getLegend(i); i++){
				if(legend.legend.getIndicator())
					options.boundaryTypes.push(legend.legend.getBoundaryType());
			}
		}
		
		map.identify(point, f, options);
	}
}

/*******************************************************************************
 * ** Class: PMapState ***
 ******************************************************************************/
PMapState = function(center, zoom, indicator, sets, place, addr) {
	this.center = center;
	this.zoom = zoom;
	this.indicator = indicator;
	this.sets = sets;
	this.place = place;
	if (addr)
		this.addr = addr;
	else
		this.addr = null;
}

//returns skinny version so we can serialize and store efficiently (and without
//circular ref's)
PMapState.prototype.toDataObject = function() {
	var retVal = {};
	if (this.indicator)
		retVal.i = this.indicator.id;
	if (this.place)
		retVal.p = this.place.id;
	if (this.sets) {
		var sets = this.sets;
		var l = sets.length;
		var ids = [];
		var filters = {};
		var s;
		for ( var i = 0; i < l; i++) {
			var s = sets[i];
			ids.push(s.id);
			filters[s.id] = s.filtergroups;
		}
		retVal.o = ids;
		retVal.ofilter = filters;
	}
	retVal.center = this.center;
	retVal.zoom = this.zoom;
	retVal.addr = this.addr;
	return retVal;
}

/*******************************************************************************
 * ** Class: PMapStateList ***
 ******************************************************************************/
PMapStateList = function(size, place) {
	this.eventTypes = new Object();
	this.eventTypes.add = 'add';
	this.eventTypes.set = 'set';

	this.eventManager = new _eventManager();
	for ( var ev in this.eventTypes)
		this.eventManager.registerEventID(ev);

	this.list = [];
	this.size = size;
	this.currentplace = place;
}

PMapStateList.prototype.addListener = function(eventId, func) {
	this.eventManager.registerForEvent(eventId, [], func);
}

PMapStateList.prototype.removeListener = function(eventId, func) {
	this.eventManager.deregisterForEvent(eventId, [], func);
}

PMapStateList.prototype.add = function(state) {
	this.addQuietly(state);
	this.eventManager.triggerEvent('add', state);
}

//doesn't trigger any events
PMapStateList.prototype.addQuietly = function(state) {
	// remove dupes before adding
	for ( var i = 0; i < this.list.length; i++) {
		var checkpid = false;
		var checkiid = false;
		if (!this.list[i].addr && !state.addr) {
			if (!this.list[i].place && !state.place && !this.list[i].addr && !state.addr)
				checkpid = true;
			else if (this.list[i].place && this.list[i].place.id && state.place && state.place.id && this.list[i].place.id == state.place.id)
				checkpid = true;
		} else if (this.list[i].addr && state.addr && this.list[i].addr == state.addr)
			checkpid = true;
		if (!this.list[i].indicator && !state.indicator)
			checkiid = true;
		else if (this.list[i].indicator && this.list[i].indicator.id && state.indicator && state.indicator.id && this.list[i].indicator.id == state.indicator.id)
			checkiid = true;

		if (checkpid && checkiid) {
			this.list.splice(i, 1);
			i--;
		}
	}

	if (this.list.length == this.size)
		this.list.splice(0, 1);
	// only add if not USA
	if ((state.place && state.place.label && state.place.label != "USA") || state.addr)
		this.list.push(state);
}

PMapStateList.prototype.setMap = function(map, index) {
	map.removeIndicator();
	// map.clearOverlaySets();
	map.clearOverlays();

	var state = this.list[index];
	if (state.place && state.place.getBounds()) {
		map.setCenterBounds(state.place.getBounds());
		var polygons = state.place.getVertices();
		if (polygons)
			addPolygons(map, polygons);
		this.currentplace = state.place;
	} else {
		this.currentplace = null;
		map.setCenter(state.center, state.zoom);
	}

	// if (state.sets && state.sets.length > 0)
	// map.setOverlaySets(state.sets);
	this.addQuietly(state);
	this.eventManager.triggerEvent('set', state);
}

//returns a skinny version of the object that is json'ifiable (trim's uneeded
//data)
PMapStateList.prototype.toDataObject = function() {
	var retVal = [];
	var states = this.list;
	var l = states.length;
	var state;
	for ( var i = 0; i < l; i++) {
		retVal.push(states[i].toDataObject());
	}
	return retVal;
}

//fills in the list from the passed in data object
//@param obj an array of state data objects (hash of overlay set id's to
//filtergoups)
//tbd: remove duplicates
PMapStateList.prototype.setList = function(obj) {
	var indids = [];
	var placeids = [];
	var indconstructors = {};
	var placeconstructors = {};
	var constructors = [];
	var seen = {};

	for ( var i = 0; i < obj.length; i++) {
		var sd = obj[i];
		var sets = [];
		var seenkey = sd.center.latitude + ',' + sd.center.longitude + ',' + sd.zoom + ',' + sd.p + ',' + sd.i + ',';

		if (seen[seenkey])
			continue;

		seen[seenkey] = 1;

		var center;
		if (sd.center) {
			center = new PLatLng(sd.center.latitude, sd.center.longitude);
		}

		var stateargs = {
				center :center,
				zoom :sd.zoom,
				sets :sets,
				addr :sd.addr
		};

		if (sd.p) {
			if (!placeconstructors[sd.p]) {
				placeids.push(sd.p);
				placeconstructors[sd.p] = [];
			}
			placeconstructors[sd.p].push(stateargs);
		}

		if (sd.i) {
			if (!indconstructors[sd.i]) {
				indids.push(sd.i);
				indconstructors[sd.i] = [];
			}
			indconstructors[sd.i].push(stateargs);
		}
		constructors.push(stateargs);
	}

	var setstates = function(pmsl) {
		var states = [];
		for ( var i = 0; i < constructors.length; i++) {
			var c = constructors[i];
			if ((typeof c.place != "undefined" && c.place && c.place.label && c.place.label != "USA") || c.addr)
				states.push(new PMapState(c.center, c.zoom, c.ind, c.sets,
						c.place, c.addr));
		}
		pmsl.list = states;
		/* kludge - dropdown should be decoupled from PMapStateList */
		if (typeof prevmaps != 'undefined')
			prevmaps.refresh(pmsl);
	}

	var pmsl = this;
	var needplaces = placeids.length > 0;
	var needinds = indids.length > 0;

	if (needinds) {
		PIndicatorLoader.load(indids, function(inds) {
			for ( var i = 0; i < inds.length; i++) {
				var ind = inds[i];
				var c = indconstructors[ind.id];
				for ( var j = 0; j < c.length; j++)
					c[j].ind = ind;
			}
			if (!needplaces)
				setstates(pmsl);
			needinds = false;
		});
	}

	if (placeids.length > 0) {
		PPlaceLoader.load(placeids, function(places) {
			for ( var i = 0; i < places.length; i++) {
				var place = places[i];
				var c = placeconstructors[place.id];
				for ( var j = 0; j < c.length; j++)
					c[j].place = place;
			}
			if (!needinds)
				setstates(pmsl);
			needplaces = false;
		});
	}
}

/*******************************************************************************
 * FUNCTIONS
 */

function loadDelayCheck(val) {
	if (loaddelaytotal) {
		if (loaddelaycount == loaddelaytotal)
			map.disableLoadDelay();
		if (loaddelaycount <= loaddelaytotal)
			loaddelaycount++;
	}
	map.refresh();
	if(PAGE_ID == 'a_'){
		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
	if(PAGE_ID == "w_")
		return reportLinkHolder;

	$(reportLinkHolder).addClass('point_report_link_holder');
	$(reportLinkHolder).css( {
		textAlign:'right',
		padding:'2px'
	});
	
	var reportLink = document.createElement('a');
	if(isSubscriber()) {
		if(address) {
			reportLink.innerHTML = "See Report";
			var url = "reports.jsp?area=radius&address=" + address;
		} else {
			reportLink.innerHTML = "See Radius Report";
			var url = "reports.jsp?area=radius&lat=" + lat + "&lng=" + lng;
			var overlaySets = map.getOverlaySets();
			dids = [];
			for(var i=0; i<overlaySets.length; ++i) {
				dids.push(overlaySets[i].id);
			}
			if(dids.length > 0) {
				url += "&did=" + dids.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.jsp";
		});
	}
	$(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
	if(PAGE_ID == "w_")
		return tableLinkHolder;

	$(tableLinkHolder).addClass('polygon_table_link_holder');
	$(tableLinkHolder).css( {
		textAlign:'right',
		padding:'2px'
	});
	
	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", encodeURIComponent(pname));
		session2.put("plat", plat);
		session2.put("plng", plng);
		// Load the charts page.
		window.location = "charts.jsp";
	});
	
	$(tableLinkHolder).append(tableLink);
	return tableLinkHolder;
}

// Generate the Report Links for Polygons
function generatePolygonReportLink(bid, polyid, pname, plat, plng, rtype, submsg) {
	var reportLinkHolder = document.createElement('div');
	
	// Return an empty element for the widget or a non-subscriber
	// when we're not displaying the subscribe message.
	if(PAGE_ID == "w_" || (!isSubscriber() && !submsg))
		return reportLinkHolder;

	$(reportLinkHolder).addClass('polygon_report_link_holder');
	$(reportLinkHolder).css( {
		textAlign:'right',
		padding:'2px'
	});
	
	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";
		}
		PEvent.addListener(reportLink, "click", function() {
			window.location = "reports.jsp?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 the area around the address you've selected, susbcribe now.";
		PEvent.addListener(reportLink, "click", function() {
			window.location = "subscribe.jsp";
		});
	}
	$(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 or if there are no pointsets on the map.
	if(PAGE_ID == "w_" || overlays.length == 0)
		return pointlistLinkHolder;

	$(pointlistLinkHolder).addClass('polygon_pointlist_link_holder');
	$(pointlistLinkHolder).css( {
		textAlign:'right',
		padding:'2px'
	});
	
	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].isPolySet(overlays[i].id, map))
			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.place = bid;
		PEvent.addListener(listLink, "click", function() {
			// 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(this.setid, this.place))
				return;

			// 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", encodeURIComponent(pname));
			session2.put("plat", plat);
			session2.put("plng", plng);
			// Load the charts page with the selected pointset.
			window.location = "charts.jsp?showlist=" + this.setid;
		});
		$(pointlistLinkHolder).append(listLink);
		var img = document.createElement('img');
		img.src = overlays[i].icon.image;
		$(pointlistLinkHolder).append(" ");
		$(pointlistLinkHolder).append(img);
	}
	
	return pointlistLinkHolder;
}

// Generate the 'See List of' Polygon Links for Polygons
function generatePolygonPolylistLinks(bid, pname, plat, plng) {
	var polylistLinkHolder = document.createElement('div');
	var overlays = map.getOverlaySets();
	
	// Return an empty element for the widget or if there are no pointsets on the map.
	if(PAGE_ID == "w_" || overlays.length == 0)
		return polylistLinkHolder;
	
	// Determine if there are currently any polygons on the map,
	// and if so, store which pointsets have them.
	var polygonSets = [];
	var pointSets = map.getOverlaySets();
	for(var i=0; i<pointSets.length; i++)
		if(POverlaySet.PointAndPolygonSets[pointSets[i].id])
			polygonSets.push(i);
	
	if(polygonSets.length > 0) {
		$(polylistLinkHolder).addClass('polygon_polylist_link_holder');
		$(polylistLinkHolder).css( {
			textAlign:'right',
			padding:'2px'
		});
		
		// 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++) {
			$(polylistLinkHolder).append(document.createElement('br'));
			var listLink = document.createElement('a');
			listLink.innerHTML = "See List of " + pointSets[polygonSets[i]].getLabel() + " polygons";
			listLink.setid = pointSets[polygonSets[i]].id;
			PEvent.addListener(listLink, "click", function() {
				// 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", encodeURIComponent(pname));
				session2.put("plat", plat);
				session2.put("plng", plng);
				// Load the charts page with the selected pointset.
				window.location = "charts.jsp?showlist=" + POverlaySet.PointAndPolygonSets[this.setid].polygonID;
			});
			$(polylistLinkHolder).append(listLink);
			var img = document.createElement('img');
			img.src = polyicon.image;
			$(polylistLinkHolder).append(" ");
			$(polylistLinkHolder).append(img);
		}
	}
	
	return polylistLinkHolder;
}

function createPlacesDiv(candidatePlaces, searchString) {
	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() {
				var title = "<div class='similarresults'>" + this.place.getLabel() + " (" + this.place.getType().getName() + ")</div>";
				addMarkerWindow(title, this.place);
			}));
			html.appendChild(placelink);
			html.appendChild(document.createElement("br"));
		}
	}
	map.saveInfoWindow = true;
	map.infoWindowType = 'place';
	return html;
}

function addPolygons(map, polygons, fill) {
	// keep track of polygons (so we can selecctively remove them later)
	if (!map.polygons)
		map.polygons = [];

	for ( var i = 0; i < polygons.length; i++) {
		if (fill)
			var polygon = new PPolygon(polygons[i]);
		else
			var polygon = new PPolyline(polygons[i]);
		map.addOverlay(polygon);
		map.polygons.push(polygon);
	}
}
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()) {
		if (state.indicator.getDescription() != "" && state.indicator.getDescription().length < state.indicator.getFullDisplayName().length) {
			text = state.indicator.getDescription();
			if (document.getElementById('morelink').innerHTML.search('>close<') == -1)
				var moretext = "details";
			else
				var moretext = "close";
			document.getElementById('morelink').innerHTML = "<a class='morelink' href='#' onclick='showMore(); return false'><span id='morespan' style='text-decoration:underline'>"
				+ moretext
				+ "</span><img class='morearrow' src='images/more_arrow.gif' /></a>";

		} else {
			text = state.indicator.getFullDisplayName();
			if (document.getElementById('morelink').innerHTML.search('>close<') == -1)
				var moretext = "details";
			else
				var moretext = "close";
			document.getElementById('morelink').innerHTML = "<a class='morelink' href='#' onclick='showMore(); return false'><span id='morespan' style='text-decoration:underline'>"
				+ moretext
				+ "</span><img class='morearrow' src='images/more_arrow.gif' /></a>";
		}
	} 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;
}

function mapOptionsPopulate() {
	var optsbox = document.getElementById('optsbox');

	// clear all content
	while (optsbox.hasChildNodes())
		optsbox.removeChild(optsbox.firstChild);

	var headerDiv = document.createElement('div');
	headerDiv.className = 'header'
	optsbox.appendChild(headerDiv);
	var div = document.createElement('div');
	div.innerHTML = 'Map Options';
	div.className = 'mainTitle';
	headerDiv.appendChild(div);
	// add close box
	var close = document.createElement('img');
	close.className = "optsboxclose";
	close.src = "images/close_button2.gif";
	PEvent.addListener(close, 'click', mapOptions);
	headerDiv.appendChild(close);

	var natDiv = document.createElement('div');
	natDiv.className = 'section';
	var title = document.createElement('div');
	title.innerHTML = 'National Boundaries';
	title.className = 'title';
	natDiv.appendChild(title);
	var provDiv = document.createElement('div');
	provDiv.className = 'section';
	var title = document.createElement('div');
	title.innerHTML = 'Provincial Boundaries';
	title.className = 'title';
	provDiv.appendChild(title);
	var featDiv = document.createElement('div');
	featDiv.className = 'section';
	featDiv.style.border = 'none';
	var title = document.createElement('div');
	title.innerHTML = 'Map Features';
	title.className = 'title';
	featDiv.appendChild(title);

	optsbox.appendChild(natDiv);
	optsbox.appendChild(provDiv);
	optsbox.appendChild(featDiv);

	// generate content
	var l = MAPLAYER_OPTIONS.length;
	var scale = map.getScale();
	var layerDivArray = [];
	for ( var i = 0; i < l; i++) {
		// The nulls in MAPLAYER_OPTIONS are to fill old layers that have been removed
		// This way links after a layer is removed will still work properly
		if (MAPLAYER_OPTIONS[i] == null)
			continue;

		var divMain = document.createElement('div');
		divMain.className = 'layerbox';
		divMain.layername = MAPLAYER_OPTIONS[i].title;

		// check box div
		var checkDiv = document.createElement("div");
		checkDiv.style.styleFloat = "left";
		checkDiv.style.cssFloat = "left";
		checkDiv.style.paddingTop = "3px";

		// check box
		var opt = document.createElement('input');
		opt.type = "checkbox";
		opt.value = i;
		checkDiv.appendChild(opt);
		divMain.appendChild(checkDiv);
		if (parseInt(MAPLAYER_OPTIONS_ON[i]) && (!MAPLAYER_OPTIONS[i].forSubscribers || isSubscriber()))
			opt.checked = true;
		PEvent.addListener(opt, 'click', function() {
			// teaser for subscriber map layers
			if (MAPLAYER_OPTIONS[this.value].forSubscribers && !isSubscriber()) {
				subscribeAlert();
				this.checked = false;
			}
			else
				toggleMapOptionsLayers(this.value);
		});
		if (MAPLAYER_OPTIONS[i].minScale > scale
				|| MAPLAYER_OPTIONS[i].maxScale < scale)
			opt.disabled = true;

		// label div
		var textDiv = document.createElement("div");
		textDiv.className = 'layerTitle';
		textDiv.innerHTML = MAPLAYER_OPTIONS[i].title;
		// need to fix the line height when the title is only 1 line
		if (MAPLAYER_OPTIONS[i].title.indexOf('<br') == -1) {
			textDiv.className += ' singleLineAdjust';
		}
		else
			divMain.style.padding = "3px 0";

		if (opt.disabled) {
			textDiv.title = 'Not available at this zoom level';
			textDiv.style.color = "#ccc";
		}
		divMain.appendChild(textDiv);
		// divs are put in array and then displaying order is done based on MAPLAYER_OPTIONS_ORDER array
		layerDivArray.push(divMain);
	}
	var order = MAPLAYER_OPTIONS_ORDER.national;
	var div1 = document.createElement('div');
	div1.className = 'column';
	var div2 = document.createElement('div');
	div2.className = 'column';
	natDiv.appendChild(div1);
	natDiv.appendChild(div2);
	// rearrange order, this is needed because saved links depend on original order of layer options
	for (var i=0; i<order.length; i++) {
		// this decides where to separate the columns
		if (i<8)
			var d = div1;
		else
			var d = div2;
		for (var j=0; j<layerDivArray.length; j++) {
			if (layerDivArray[j].layername == order[i].title) {
				d.appendChild(layerDivArray[j]);
				var br = document.createElement('br');
				br.style.clear = "both";
				d.appendChild(br);
				// remove from array once it's been used
				layerDivArray.splice(j,1)
				break;
			}
		}
	}

	var order = MAPLAYER_OPTIONS_ORDER.provincial;
	var d = document.createElement('div');
	d.className = 'column';
	provDiv.appendChild(d);
	// rearrange order, this is needed because saved links depend on original order of layer options
	for (var i=0; i<order.length; i++) {
		for (var j=0; j<layerDivArray.length; j++) {
			if (layerDivArray[j].layername == order[i].title) {
				d.appendChild(layerDivArray[j]);
				var br = document.createElement('br');
				br.style.clear = "both";
				d.appendChild(br);
				// remove from array once it's been used
				layerDivArray.splice(j,1)
				break;
			}
		}
	}

	var order = MAPLAYER_OPTIONS_ORDER.features;
	var div1 = document.createElement('div');
	div1.className = 'column';
	featDiv.appendChild(div1);
	var d = div1
	// rearrange order, this is needed because saved links depend on original order of layer options
	for (var i=0; i<order.length; i++) {
		for (var j=0; j<layerDivArray.length; j++) {
			if (layerDivArray[j].layername == order[i].title) {
				d.appendChild(layerDivArray[j]);
				var br = document.createElement('br');
				br.style.clear = "both";
				d.appendChild(br);
				// remove from array once it's been used
				layerDivArray.splice(j,1)
				break;
			}
		}
	}

	// break
	var br = document.createElement("br");
	br.clear = "both";
	optsbox.appendChild(br);
}

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;
	}

	var optsbox = document.getElementById('optsbox');

	if (optsbox.style.display == "block") {
		jQuery("#optsbox").slideUp();
		// jQuery("#optsbox").animate({"bottom": "-100px"}, "slow");
	} else
		jQuery("#optsbox").slideDown();
}

function toggleMapOptionsLayers(index) {
	var maplayers = map.getCurrentMapType().getMapLayers();
	var layer = MAPLAYER_OPTIONS[index];

	// add label layers for these layers
	var label = null;
	if (MAPLAYER_LABELS[layer.name])
		label = MAPLAYER_LABELS[layer.name];

	if (layer.isOn()) {
		layer.off();
		MAPLAYER_OPTIONS_ON[index] = 0;
		if (label)
			label.off();
		// removes transit points
		if (MAPLAYER_OPTIONS[index].pointDataset)
			map.removeOverlaySet(MAPLAYER_OPTIONS[index].pointDataset);
	} else {
		layer.on();
		MAPLAYER_OPTIONS_ON[index] = 1;
		if (label)
			label.on();
		// adds transit points
		if (MAPLAYER_OPTIONS[index].pointDatasetId) {
			var markerset = createTransitPoints(index);
			map.addOverlaySet(markerset);
		}
	}
	session2.put('mo', MAPLAYER_OPTIONS_ON);
}

function setMapOptionsLayers(index) {
	var layer = MAPLAYER_OPTIONS[index];
	var label = null;

	// check if layer exists in the layer array
	if (layer == null)
		return;

	if (MAPLAYER_LABELS[layer.name])
		label = MAPLAYER_LABELS[layer.name];

	if (parseInt(MAPLAYER_OPTIONS_ON[index]) && (!MAPLAYER_OPTIONS[index].forSubscribers || isSubscriber())) {
		layer.on();
		if (label)
			label.on();
		if (MAPLAYER_OPTIONS[index].pointDatasetId) {
			createTransitPoints(index);
			//the transit points are added after map is inititialized in loadMap
		}
	} else {
		layer.off();
		if (label)
			label.off();
	}
}

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() {

	// 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=';
		}

		// Get Info Window Info
		var infoWindow = map.getInfoWindow();
		var iData = "";
		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 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.source);
			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 = "";
		// Get all overlay sets on the map.
		var osets = map.getOverlaySets();
		var addSitesSize = "&ass=" + osets.length;
		// Cycle through each overlay set on the map.
		for(var i=0; i<osets.length; i++) {
			// Include the set's icon (if applicable).
			if(osets[i].icon) {
				addSitesIcons += "&asi_" + i + "=" + encodeURIComponent(filenameFromURL(osets[i].icon.image));
			}
			addSitesLabels += "&asl_" + i + "=" + 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_" + i + "_" + "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_" + i + "_" + "0" + "_" + m + "=" + encodeURIComponent(filenameFromURL(osets[i].filtericons[m].image));
						addSitesLabels += "&asl_" + i + "_" + "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) {
					addSitesLabels += "&asl_" + i + "_" + 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_" + i + "_" + k + "_" + m + "=" + encodeURIComponent(groupFilters[m].valuesDisplay);
					}
					k++;
				}
			}
		}

		// 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');
		
		// If specified, pass the argument to disable the boundary outline.
		// (Currently used for pre-determined boundaries with Island Printing.)
		if(hideOutline) {
			boundaryOutline = "&bo=0";
			hideOutline = false;
		} else
			boundaryOutline = "&bo=1";

		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.source);
					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;
			}
		}
		var newTarget = "http://" + printTemplate + "/";
		var url = newTarget + "?" + mapImageUrlTokens[1] + title + orientation
		+ expanded + boundary + source + period + dataType + dataSize
		+ data + color + visible + mergedLegendData + additionalDataSize
		+ additionalData + addSitesSize + addSitesLabels
		+ addSitesIcons + placeId + address + boundaryOutline + breadcrumbsString
		+ description + iData;
		return url;
	} else {
		customAlert("Please display a map.");
	}
	return null;
}

function filenameFromURL(url) {
	// Simple function to pull the filename from a full URL. Used above to
	// pull the icon image URL from the full path stored within the icon object.
	urlParts = url.split("/");
	return urlParts[urlParts.length - 1];
}

function customAlert(text) {
	var alerter = new PAlerter();
	var position = getAlertPosition(parseInt(alerter.box.style.width));
	alerter.popup(text, position[0], position[1], "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.jsp' class='pagelinks'>subscriber options</a>."
	var alerter = new PAlerter();
	var position = getAlertPosition(parseInt(alerter.box.style.width));
	alerter.popup(text, position[0], position[1], "OK");
}

function subscribeAlert(callback, customText, pinsetId) {
	var link = getContextPath() + (isPublicUser() ? '/register.jsp?reg_type=sub' : '/upgrade?reg_type=sub');
	if (customText)
		var text = customText;
	else
		var text = "Available to subscribers only.  If you're a subscriber, <a onclick='loginAlert(this)' class='pagelinks'>login</a> to access, or become a <a href='" + link + "' class='pagelinks'>subscriber</a>.";
	// pinsetId comes from index_sites.jsp
	if (pinsetId == 86500)
		text += "<br /><br />Click <a href='/our-data-directory.html#source56' class='pagelinks'>here</a> to learn more about National Center for Charitable Statistics Nonprofit Locations.";

	// show this copy for window widget subscribe alert
	if (PAGE_ID == "w_")
		var text = "This data is available in PolicyMap to subscribers.  <a href='/subscribe.jsp' class='pagelinks' target='_blank'>Click here</a> if you'd like to learn more.";

	var alerter = new PAlerter();
	var position = getAlertPosition(parseInt(alerter.box.style.width));
	if (callback && callback.constructor == Function) {
		alerter.popup(text, position[0], position[1], "OK", null, null, null,
				callback);
	} else {
		alerter.popup(text, position[0], position[1], "OK");
	}
}

function premiumSubscribeAlert() {
	var link = getContextPath() + (isPublicUser() ? '/register.jsp?reg_type=full' : '/upgrade?reg_type=full');
	var text = "Currently, this data is only available to selected users.";
	var alerter = new PAlerter();
	var position = getAlertPosition(parseInt(alerter.box.style.width));
	alerter.popup(text, position[0], position[1], "OK");
}

function requestMapEmbedding() {

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

	var parms = mapImageUrlTokens[1]; // contains relevant map parms.
	var pairs = parms.split('&');
	var aParms = {};
	for ( var i = 0; i < pairs.length; ++i) {
		var kv = pairs[i].split('=');
		if (kv.length == 2) {
			aParms[kv[0]] = kv[1];
		}
	}

	var alerter = new PAlerter();
	var pos = getAlertPosition(parseInt(alerter.box.style.width));

	var text = "Please define width and height of the map image( The default dimensions reflect the map you currently see ):<br/>";
	text += "Width: <input id='aParmsWidth' type='text' size='4' maxlength='4' value='" + aParms.imgwidth + "' />&nbsp;";
	text += "&nbsp;Height: <input id='aParmsHeight' type='text' size='4' maxlength='4' value='" + aParms.imgheight + "' /><br/><br/>";

	alerter.popup(text, pos[0],pos[1], "Cancel", "Embed", function() { // embed and generate link

		function embed(cb) {

			aParms.imgwidth = jQuery('#aParmsWidth').val();
			aParms.imgheight = jQuery('#aParmsHeight').val();

			if( aParms.imgWidth > 2000 ) {
				aParms.imgwidth = 2000;
			}

			if( aParms.imgheight > 2000 ) {
				aParms.imgheight = 2000;
			}


			jQuery('#aParmsWidth').remove();
			jQuery('#aParmsHeight').remove();

			// 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);

			link.url += '&ew=' + aParms.imgwidth + '&eh=' + aParms.imgheight;

			if (session2.get('cp')) { // custom poly
				parms += "&cp=" + session2.get('cp');
			}
			linkManager.embed(link, function(status, msg, lqid) {
				var alerter = new PAlerter();
				var pos = getAlertPosition(parseInt(alerter.box.style.width));
				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 = '<iframe src=&quot;http://'
						+ window.location.hostname
						+ '/embedmap.jsp?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>';

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

				} else {
					alerter.popup(msg, pos[0], pos[1], "OK");
				}
			}, parms, 'PolicyMapEmbedding');
		}
		var indicator = map.getIndicator();
		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.pinUrl + '/servlet/stringstore?str=' + MochiKit.Base.serializeJSON(obj), embed);
			} else
				embed();
		} else
			embed();
	}, null, function() {
		jQuery('#aParmsWidth').remove();
		jQuery('#aParmsHeight').remove();
	});
}

function selectPlace(geo_boundary_id) {
	if(allowSelect != false){
		if (window.session2) {
				session2.put('p', geo_boundary_id);
		}
		var func = function() {
			if (window.map) {
				var placeZoom = map.getBoundsZoomLevel(place.getBounds());
				var curZoom = map.getZoom();
				// Offer option to not recenter/rezoom when map is zoomed in and an indicator with a place is added
 				if (curZoom > placeZoom) {
					var text = "This data layer is specific to <b>" + place.getLabel() + ", " + place.getState() + "</b>.<br /><br />Do you wish to recenter the map over this location, or remain at the current position at the current zoom level?";
					var alerter = new PAlerter2();
					var position = getAlertPosition(parseInt(alerter.box.style.width));
					var yes = function() {
						var html = createPlacesDiv( [ place ]);
						addMarkerWindow(html, place);
						session2.put('p', geo_boundary_id);
					};
					alerter.popup(text,position[0],position[1],"Stay","Recenter", yes);
				}
				else {
					var html = createPlacesDiv( [ place ]);
					addMarkerWindow(html, place);
					session2.put('p', geo_boundary_id);
				}
			}
		}
		PPlaceLoader.load( [ geo_boundary_id ], func);
	}
}

function resetMap() {
	setMapOptionsToDefaultAndRefresh();

	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();
	if (map.getInfoWindow())
		map.closeInfoWindow();
	map.setCenter(new PLatLng(37.6902, -96.9129), 2);
	document.getElementById("maptitle").innerHTML = "";
	jQuery('#moretitle').hide(200);
	document.getElementById('moretitle').innerHTML = "";
	document.getElementById('morelink').innerHTML = "";

	search.reset();

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

function clearLocationAlert() {
	var text = "";
	var place = null;
	var alerter = new PAlerter();
	var position = getAlertPosition(parseInt(alerter.box.style.width));

	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.customPlacesOnMap;

	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, position[0], position[1], "No", "Yes", clearLocation);
	} else {
		if (PAGE_ID == "w_")
			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, position[0], position[1], "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 = [];
	}

	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.customPlacesOnMap;
		// remove each place from the map
		for (var i in customplaces) {
			polycreator.removeCustomRegionFromMap(customplaces[i].place);
		}
		polycreator.reset();
		polycreator.dropdown.reset();
	}

	mapstates.currentplace = null;	
	custom_place = null;
}

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

function showMore() {
	var more = document.getElementById('moretitle');
	var morelink = document.getElementById('morelink');
	var ind = map.getIndicator();
	if (morelink.innerHTML.search('>close<') == -1) {
		more.innerHTML = ind.getDescription();
		more.innerHTML += "<a class='dataLink' target='_blank' href='/our-data-directory.html#" + ind.getDataDirectory() + "'>(see data directory)</a>";
		jQuery('#moretitle').slideDown(200);
		jQuery('#moretitle').fadeIn(200);
		morelink.innerHTML = "<a class='morelink' href='#' onclick='showMore(); return false'><span id='morespan' style='text-decoration:underline'>close</span><img class='morearrow' src='images/more_arrow.gif' /></a>";
	} else {
		jQuery('#moretitle').hide(200);
		more.innerHTML = "";
		morelink.innerHTML = "<a class='morelink' href='#' onclick='showMore(); return false'><span id='morespan' style='text-decoration:underline'>details</span><img class='morearrow' src='images/more_arrow.gif' /></a>";
	}
}

function checkMore() {
	var moretitle = document.getElementById('moretitle');
	var morelink = document.getElementById('morelink');
	var ind = map.getIndicator();
	moretitle.innerHTML = ind.getDescription();
	moretitle.innerHTML += "<a class='dataLink'  target='_blank' href='/our-data-directory.html#" + ind.getDataDirectory() + "'>(see data directory)</a>";
	if (morelink.innerHTML.search('>close<') != -1) {
		jQuery('#moretitle').fadeIn(2000);
	}
}

function getAlertPosition(alertsize) {
	var mapdiv = document.getElementById("map");
	var pos = getElementPosition(mapdiv);
	x = pos[0] + (mapdiv.offsetWidth * 0.5) - (alertsize * 0.5);
	y = pos[1] + 10;

	return [ x, y ];
}

var mapstates = new PMapStateList(10, initialplace);

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')];

	// 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++)
			setMapOptionsLayers(i);
	}
	
	// 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) {
		custom_place = places[0];

		var html = function(){ return PMIdentificationPrinter.printCustomPolyPlaces(places[0]); }; 
		//polycreator.addPolyMarker(places[0].getVertices(),html,map); 
		polycreator.addPolylines(places[0], html, map);

		// 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();
		if (polycreator.buildType == polycreator.ASSEMBLE) {
			polycreator.resetBuildType();
			// 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.show();
		}
		if (polycreator.buildType == polycreator.CIRCLE) {
			polycreator.circleWidget.hide();
		}

		toggleCustomRegion();

		// animate mypolicymap link
		saveEffect();

		// refresh the drop down with the new custom place
		polycreator.dropdown.setUsersPlaces();
	});

	// Create map and go to address
	map = new PMap(document.getElementById("map"));

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

	// 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 = {};

		// iterate through all groups of sets
		var groups = sitelegends.setgroups;
		var l1 = sitelegends.setgroups.length;
		for ( var i1 = 0; i1 < l1; i1++) {
			var sets = groups[i1];
			var l2 = sets.length;
			var overlaySet;
			for ( var i2 = 0; i2 < l2; i2++) {
				overlaySet = sets[i2];
				filters[overlaySet.id] = overlaySet.filtergroups;
			}
		}

		session2.put('ofilters', filters);
	});

	// overlay set events
	PEvent.addListener(map, 'addoverlayset', function(overlayset) {
		sitelegends.refresh();
		session2.put('o', POverlaySetUtil.toIdCsv(map.getOverlaySets()));
	});
	PEvent.addListener(map, 'removeoverlayset', function(overlayset) {
		sitelegends.refresh();
		// make a csv out of id's and put in session
		session2.put('o', POverlaySetUtil.toIdCsv(map.getOverlaySets()));
	});
	// 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.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) {
			breadcrumbs.refresh(places);
		});
	});

	// 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.getVertices());
		mapstates.add(new PMapState(map.getCenter(), map.getZoom(), map.getIndicator(), null, mapstates.currentplace));
	});

	var urlParams = PWebUtil.parseQuery(window.location.search);

	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(37.6902, -96.9129), 2);
	}

	// 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, polygons);
				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();
				if (urlParams['cx'] && urlParams['cy'] && urlParams['cz']) {
					map.setCenter(new PPoint(urlParams['cx'], urlParams['cy']), urlParams['cz']);
				} else if (urlParams['cz']) {
					map.setCenter(latlng, urlParams['cz'])
				} else {
					map.setCenter(latlng, curZoom || 13);
				}
				// add see report link
				var link = generatePointReportLink(null, null, addy);
				var div = document.createElement('div');
				div.innerHTML = "<div class='similarresults'>" + addy + "</div><br />";
				div.appendChild(link);
				map.openInfoWindowHtml(latlng, div);
			}
		});
		// check if custom polygon in session
	} else 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;

				var html = function(){ return PMIdentificationPrinter.printCustomPolyPlaces(place); };
				polycreator.addPolylines(place, html, 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 overlaysets in session
	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
			if (!overlaySetHash[ids[i]])
				continue;

			var site = createSites(map, ids[i], overlaySetHash[ids[i]].name, overlaySetHash[ids[i]].icon);
			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);
	}
	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 transit = PMapLayer.UMTRANSIT;
	// zoom event to toggle transit points when layer turns off
	PEvent.addListener(map, 'zoomend', function() {
		if (map.getZoom() > 8 && transit.isOn() && !transit.pointDataset.isOn())
			transit.pointDataset.on();
		else if (map.getZoom() < 9 && transit.isOn())
			transit.pointDataset.off();
	});

	mapOptionsPopulate();

	// adds the transit points if the transit layer got added in sessions
	if (PMapLayer.UMTRANSIT.isOn())
		map.addOverlaySet(PMapLayer.UMTRANSIT.pointDataset);
}

function createTransitPoints(index) {
	var fakeIcon = new PIcon(PIcon.POINT);
	fakeIcon.image = PEnvironment.pinImageUrl + "circle_blue.png";
//	fakeIcon.image = "http://";
	fakeIcon.shadow = "http://";
	MAPLAYER_OPTIONS[index].pointDataset = new POverlaySet(MAPLAYER_OPTIONS[index].pointDatasetId, fakeIcon, 15);
	var markerset = MAPLAYER_OPTIONS[index].pointDataset;
	markerset.withLayer = true;

	return markerset;
}

function showColorOptions() {
	if (!isSubscriber()) {
		subscribeAlert();
		return;
	}
	if(editState & PIndicatorBreaks.EDITSTATE.exactBreaks) {
		var alerter = new PAlerter();
		var position = getAlertPosition(parseInt(alerter.box.style.width));
		alerter.popup("Legend colors cannot be changed for categorical data.", position[0], position[1], "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 ramp in ramps) {
		var colors = ramps[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.ramp = ramp;
			PEvent.addListener(div, 'click', function() {
				widget.changeColorRamp(this.ramp);
			});
			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);
	});
}

//NOTE: rewritten so that it only uses first argument for indicator id
//Uses that id to look up array to get the list of related indicators
function selectIndicators() {

	// get first arg and only get one indicator
	var inds = arguments[0] + "";
	var ind0 = [inds];
	var fromlist = null;
	if (arguments.length > 1)
		fromlist = true;

	// get related indicators from global array
	var indlist = ria[ind0];
	var selected = null; 
	var indarr;
	if (indlist) {
		indarr = indlist.split(",");
		var l = indarr.length;
		for (var i=0; i<l; i++) {
			if (ind0 == indarr[i]) {
				selected = i;
				break;
			}
		}
	} else {
		indarr = ind0; // use passed in list
	}

	if (PAGE_ID == "a_") { // just for analytics page
		var disableList = []; 
			//['9629002', '9628952', '9627506', '9627505', '9627501', '9629158', '9629150', '9629156', '9629155', '9627156', '196211', 
		        // '196126', '9609712', '196193', '196510', '196528', '198853', '196544', '198870', '198887', '9627551', '196300'];
		if(jQuery.inArray(ind0[0], disableList)>=0){
			allowSelect = false;
			unsupportedIndicator();
		}else{
			allowSelect = true;
			var legendIndex = legendMerger.addIndicator(indarr, selected, fromlist, this.prefLegend);
			session2.put('m' + legendIndex + 'i', ind0);
			updateTitle(0);
			if(typeof wiz != 'undefined' && wiz != null)
				wiz.next();
		
			closeCubeWindow();
		}
	} else { // used for both map and window pages
		session.indicatorIds = ind0;
		session2.put('i', ind0);

		widget.setIndicatorListByIds(indarr, selected, fromlist); 
		var ind0 = [inds];
		closeCubeWindow();
	}
}

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 style="padding-left:8px; color:#666666">' + $(filter[0]).html() + "</div>";
					if( filterColors.length > 0){
						for(var k=0;k<filterColors.length;k++){
							sitesDiv += '<div style="padding-left:16px;color:#5D83D0">' + $(filterColors[k]).html() + "</div>";
						}
					}else{
						sitesDiv += '<div style="padding-left:16px;color:#5D83D0">'
							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(hide) {
	if (hide || jQuery('#legContentHolder').css('display') != 'none') {
		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 {
		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 = "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();
	var position = getAlertPosition(parseInt(alerter.box.style.width));

	if (PAGE_ID == "a_")
		alerter.popup(text, position[0], position[1], "No", "Yes", resetAnalytics);
	else if (PAGE_ID == "w_")
		alerter.popup(text, position[0], position[1], "No", "Yes", resetWidget);
	else
		alerter.popup(text, position[0], position[1], "No", "Yes", resetMap);

}

/**************************************************************
***** Custom Region:: Build Draw, Assembled, Radius Regions ****
***************************************************************/
function toggleCustomRegion() {
	var custreg = document.getElementById("customregion");
	if (!isCustomRegionOn()) {
		map.closeInfoWindow();
		custreg.innerHTML = "Disable Custom Region";
		jQuery(custreg).parent().addClass("on");
		//jQuery('#buildregionbox').slideDown(300);
		var alerter = new PAlerter2();
		var content = "<h2>Select the type of custom region you wish to build:</h2>" +
				"<div id='customregionoptions'><input type='radio' name='customregiontype' value='1' checked/><label>Drawn Custom Region</label><br />" +
				"<input type='radio' name='customregiontype' value='2' /><label>Assembled Custom Region</label><br />" +
				"<input type='radio' name='customregiontype' value='3' /><label>Radius Region</label></div>";
		var position = getAlertPosition(parseInt(alerter.box.style.width));
		var next = function() {
			var type = jQuery("#customregionoptions").find("input[checked='true']").attr("value");
			selectCustomRegionType(type);
		};
		var cancel = function() {cancelCustomRegion()};
		alerter.popup(content,position[0],position[1],"Cancel","OK", next, cancel)
	} else {
		cancelCustomRegion();
		map.disablePolyCreator(polycreator);
//		if (polycreator.boundaryWidget)
//		polycreator.boundaryWidget.hide();
		polycreator.cancelPoly();
		polycreator.toggleWidgets();
		// enable the map options link under the map because if user was assembling region than this would've been disabled
		mapOptionsEnable();
	}
}

function selectCustomRegionType(type) {
	var alerter = new PAlerter2();
	var content = "";
	if (type == 1) {
		polycreator.buildType = polycreator.DRAW;
		content = "<h2>Drawn Custom Region</h2>" +
			"<p>To create a Drawn 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.</p>" +
			"<p>At that point you may name the region and save it to My PolicyMap. </p>" +
			"<p>To disable this feature, click \"Disable Custom Region\".</p>";
	} else if (type == 2) {
		polycreator.buildType = polycreator.ASSEMBLE
		content = "<h2>Assembled Custom Region</h2>" +
			"<p>To create an Assembled Custom Region, click inside the boundaries you wish to include.  To remove a boundary, click it again.</p>" +
			"<p>When you are finished, click \"Save Region\" to name your region and save it to My PolicyMap.</p>" +
			"<p>The map will display the default boundary for the current zoom level.  The boundary will display in the pulldown and can be changed there.</p>" +
			"<p>To disable this feature, click \"Disable Custom Region\" at the bottom of the map.</p>";
	} else if (type == 3) {
		polycreator.buildType = polycreator.CIRCLE;
		content = "<h2>Radius Region</h2>" +
			"<p>To create a Radius Region, either enter an address to center the radius, or click directly on the map.</p>" +
			"<p>The default radius is 0.5 miles, which can be changed in the white box on the map. When you are finished, click \"GO\", which will allow you to name your region and click \"Save\" to save it to My PolicyMap.</p>" +
			"<p> To disable this feature, click \"Disable Custom Region\".</p>";
	}
	var position = getAlertPosition(parseInt(alerter.box.style.width));
	var next = function() {
		map.enablePolyCreator(polycreator);
		polycreator.initCustomRegionType();

		// When radius selection show the widget with the address search in it
		if (polycreator.buildType == polycreator.CIRCLE)
			polycreator.circleWidget.show();

		// When assembling places the boundary widget should start as enabled
		// For the other custom regions it enables once the place is saved
		if (polycreator.buildType == polycreator.ASSEMBLE) {
			polycreator.boundaryWidget.enable();
			// For now we need to refresh the map options layers every time user wants to build an assembled region.
			// To fix we probably need to make the map options an object that then we can keep track of if layers were turned on before user started to build
			// and then when the user disables building a custom region those map layers can be turned back on that were on.
			setMapOptionsToDefaultAndRefresh();
			// make sure the map options box is hidden
			jQuery("#optsbox").hide();

			// disables the map options link under the map
			mapOptionsDisable();

			// Note: Put this out of this if statement when seeing polygons within custom regions is added back to the app
			polycreator.boundaryWidget.show();
		}
	};
	var cancel = function() {cancelCustomRegion()};
	alerter.popup(content,position[0],position[1],"Cancel","OK", next, cancel)
}

function cancelCustomRegion() {
	var custreg = document.getElementById("customregion");
	custreg.innerHTML = "Build Custom Region";
	jQuery(custreg).parent().removeClass("on");
}

// returns label used for link and url parameter to set the default report selected on reports page
function getPolyReportLinkInfo(id) {
	var info = {};
	if (id == 91450) {
		info.polygonOptionLabel = "See Brookings Institution LAA Report";
		info.reportParam = "&type=brookingslaa";
	} else if (id == 93400) {
		info.polygonOptionLabel = "See Wilmington Trust Report";
		info.reportParam = "&type=h";
	} 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 setMapOptionsToDefaultAndRefresh() {
	// reset map options
	var default_layer_options = [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
	for ( var i = 0; i < default_layer_options.length; i++){
		if(default_layer_options[i] != MAPLAYER_OPTIONS_ON[i]){
			MAPLAYER_OPTIONS_ON[i] = default_layer_options[i];
			setMapOptionsLayers(i);	
		}
	}
	mapOptionsPopulate();
}
