function widgetOnLoad() {
	var urlParams = PWebUtil.parseQuery(window.location.search);
	// retrieve the widget parameters so we can set the widget with all its features
	PAsync.call('/servlets/widget/?sid=' + urlParams['sid'] + '&wkey=' + urlParams['wkey'], this, function(params) {
		// For now using the PEnvironment object to store the widget params globally since they have to be retrieved many times in different places
		PEnvironment.widgetParams = params;
		// this object exists for widgets that have an indicator list that should go in all indicator identifies.
		// only really used for widget with siteid 74 for now
		if (globalIndListBubble) {
			loadIndicatorsForCustomizedIdentify();
		}
		else {
			loadWidget();
		}
	});
}

// preload the indicators that will appear in all the identify bubbles
function loadIndicatorsForCustomizedIdentify() {
	var ids = globalIndListBubble.allIds;
	PIndicatorLoader.load(ids, function(inds) {
		globalIndListBubble.inds = inds;
		loadWidget();
	});
}

function loadWidget() {
	var urlParams = getUrlParams();

	addAllSites();

        // set scrolling for indicator menu
        setMenuScroll();

	// giving subscriber user rights so all features don't need to be kluged for now
	session2.put("_userid", 2);
	// sets the parameters from the url
	// well actually not the url anymore since it uses the widget params from the db
	session2.checkUrl();

	if (typeof index_delayed != 'undefined') index_delayed();

	// This function will be used to customize specific indicator color ramps for widgets that won't we don't to apply to the app
	customizeColorRampsForWidget(urlParams);
	// This adds map layers that aren't used in the app
	customizeMapLayersForWidget(urlParams);

	// option to turn off the parks layers
	if (urlParams['disableParksLayer']) {
		PMapLayer.POLY.off();
		PMapLayer.POLY_LABEL.off();
	}

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

	// see if we should show the menus
	// for indicator menu we check one param that can hide it, and also the altLayout since the menu is structured differently
	// in the horizontal menu if the li's have children it means there are items in the menu
	// in the vertical menu we check it differently, that's done later on where the alt layout is set up
	if (!urlParams['hideimenu'] && !urlParams['altLayout'] && $('#ind_menu_widget').find('li').children().size() > 0) {
		$('#ind_menu_widget').show();
	}
	if (!urlParams['hidepmenu']) {
		// Show the Add Sites menu only if we have at least one visible pincat.
		for(var i=0; i<pincats.length; i++) {
			if(pincats[i].display) {
				jQuery('#addsites_widget').show();
				break;
			}
		}
	}

	if (urlParams['textonly'])
		jQuery('#textOnlyLink').show();

	// Create an instance of the WidgetComment object if comments have been enabled
	// for this widget. Otherwise, hide the comments td (because of its padding).
	if(urlParams["comments"]) {
		widgetComment = new WidgetComment();
	} else {
		$(".commentsTD").hide();
	}
	
	// Display the print link if printing has been enabled for this widget.
	// (The backend will also verify printing has been enabled for this
	// widget before running a print job.)
	if(urlParams["print"]) {
		$("#widgetPrintButton").show();
	}

	// set up click events for legend toggles
	jQuery("#legend_toggle").click(function() {
		toggleOnMapLegend(this);
	});

	var curZoom = urlParams["curZoom"];
	// create polycreator
	var options = new PPolyCreatorOptions();
	options.poly.weight = 1;
	options.poly.opacity = 0.5;
	polycreator = new PPolyCreator(options);

	// need to set the height for the map div before the PMap is instantiated
	if (urlParams && urlParams['height'])
		jQuery('#map').css('height',urlParams['height'] + 'px');

	// make the layout adjustment before creating the map so the size of the map is known before centering and manipulating the map
	if (urlParams['altLayout']) {
		jQuery('#widgetcolumn').hide();
		jQuery('#mapcolumn').css('padding-left','10px');
		jQuery('#bc_td').css('padding-left','10px');
		jQuery('#maptitlebox').css('padding-left','10px');
		jQuery('#moretitle').css('left','70px');
	}

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

	PEvent.addListener(map.logo, 'click', function() { window.open("http://www.policymap.com","policymap"); });

	// Set up the charts
	if (urlParams['charts']) {
		chartoptions = new PChartOptions();
		chartoptions.xAxis = PChartOptions.PERIOD;
		chartoptions.group = PChartOptions.PLACE;
		chartoptions.type = PChartOptions.LINE;
		chartoptions.displayTitle = true;
		$('#trendchart').show();
		map.chart1 = new PChart(document.getElementById("trendchart"), chartoptions);

		$('#barchart').show();
		var barchartoptions = new PChartOptions();
		barchartoptions.displayTitle = true;
		barchartoptions.barSingleDatasetColor = true;
		map.chart2 = new PChart(document.getElementById("barchart"), barchartoptions);
	}

	var options = {};
	// adds different style for the rankings popup
	if (urlParams['rstyle'])
		options.style = urlParams['rstyle'];
	pagePopUp = new PopUp(options);

	// sites legend
	sitelegends = new PTRFSiteLegendGroup(map);
	// build the map legend for sites, only used for when the menus are above the map
	sitelegends.buildMapLegend();

	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);
		
		// Map labels may need to be updated when filters are changed.
		labelManager.updateMapLabels();
	});

	var options = {};
	options.noStartOver = true;
	if (urlParams['hidestypes'])
		options.noSearchTypes = true;

	// if the widget is going to use the alternate layout then we have to shift some things around
	if (urlParams['altLayout']) {
		// don't show the search tabs
		options.altlayout = true;
		//options.noSearchTypes = true;

		$('#top-menus').append($('#ind_menu_widget')[0]);
		$('#top-menus').append($('#addsites')[0]);

		var indMenuIsVisible = false;
		var sitesMenuIsVisible = false;
		// see if menus will be visible so we can calculate the width of the top section for adding the search box and positioning it properly
		if (!shouldWidgetMapDataButtonsBeAdded()) {
			if ($('#ind_menu_widget').find('a.clickable').length > 0) {
				indMenuIsVisible = true;
				// show the menu
				$('#ind_menu_widget').show();
			}
			if (sitelegends.legends.length > 0)
				sitesMenuIsVisible = true;
		}

		// only use the menu width if it's being displayed
		var iwidth = (indMenuIsVisible) ? $('#ind_menu_widget').outerWidth(true) : 0;
		var awidth = (sitesMenuIsVisible) ? $('#addsites_widget').outerWidth(true) : 0;
		var totalwidth = iwidth + awidth + 2;

		// if we're not showing the menus
		if (shouldWidgetMapDataButtonsBeAdded())
			totalwidth = 2;

		// store what the width is so we can know if there's enough room for a full search bar with tabs or not
		options.topMenuWidth = totalwidth;

		$('#top-menus').parent().css('width', totalwidth + 'px');
		
		// for now the only way to get how many items are in the indicator menu
		if (shouldWidgetMapDataButtonsBeAdded()) {
			// we don't need the menu when there's only one dataset
			// a toggle button will be added to the map when the legend isn't on
			$('#addsites').hide();

			// if there's an indicator then create the button
			if (doesIndMenuHaveOneItem()) {
				jQuery('#ind_menu_widget').hide();
				var indid = urlParams['i'];

				var func = function() {
					selectIndicators(indid);
				}

				// create button to turn on the indicator, only used when one indicator is in the menu
				map.indbutton = new WidgetMapDataButton('Add Data Layer', func, true);

				// if the indidcator isn't on as default then show the on button
				if (!indid)
					jQuery('#widgetAddDataButton').show();
			}

		        // add map button for when we're not showing the menu because there's only one dataset in it
		        if (sitelegends.doesSitesMenuHaveOneItem())
                		sitelegends.addMapButton();

			sitelegends.refreshMapLegend();
		}
	}

	if (urlParams['search']) {
		jQuery('#widgetSearchboxContainer').show();
		initSearchBox(options);
		// When there's a menu the search aligns next to the menus
		// Otherwise if there are no menus then keep it centered
		if (urlParams['altLayout'] && (indMenuIsVisible || sitesMenuIsVisible)) {
			$('.searchContainer').css('margin', '0px');
		}
	}

	// Check if load delay necessary
	// We can check the session to get the value because the session was populated with the url params above
	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();
	});

	// overlay set events
	PEvent.addListener(map, 'addoverlayset', function(overlayset) {
		// update the legend with the latest sites info
		if (urlParams['altLayout'])
			sitelegends.refreshMapLegend();

		sitelegends.refresh();
		session2.put('o', POverlaySetUtil.toIdCsv(map.getOverlaySets()));
	});
	PEvent.addListener(map, 'removeoverlayset', function(overlayset) {
		// update the legend with the latest sites info
		if (urlParams['altLayout']) {
			sitelegends.refreshMapLegend();
		}
		sitelegends.refresh();
		session2.put('o', POverlaySetUtil.toIdCsv(map.getOverlaySets()));
	});
	// overlay set events
	PEvent.addListener(map, 'setoverlaysets', function(overlaysets) {
		// update the legend with the latest sites info
		if (urlParams['altLayout'])
			sitelegends.refreshMapLegend();

		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() {
		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) {
		if(textOnlyIsOn) {
			textOnlyLoadPlace([place])
		}
		mapstates.currentplace = place;
		map.closeInfoWindow();
		clearPolygons(map);
		addPolygons(map, place);
		mapstates.add(new PMapState(map.getCenter(), map.getZoom(), map.getIndicator(), null, mapstates.currentplace));
	});

	if (urlParams['cx'] && urlParams['cy'] && urlParams['cz']) {
		if ((urlParams['p'] || urlParams['cp']) && loaddelaytotal > 1)
			loaddelaycount++;
		else if (urlParams['p'] || urlParams['cp'])
			map.disableLoadDelay();
		map.setCenter(new PLatLng(urlParams['cy'], urlParams['cx']), urlParams['cz']);
	} else {
		map.setCenter(new PLatLng(37.6902, -96.9129), 2);
	}

	// check if break number in url
	if (urlParams['nb'])
		map.getLegend().setNumberOfBreaks(parseInt(urlParams['nb']));
	else
		map.getLegend().setNumberOfBreaks(DEFAULT_NUMBREAKS);

	// check if indicator will need to load before using identify to open
	// infowindow
	if (urlParams['iwx'] && !urlParams['i'] && urlParams['iwtype'] == 'identify')
		PMIdentificationModule.showInfoWindow(urlParams);

	PEvent.addListener(map, 'setindicator', function(ind) {
		// if indicator has extra indicators attached to it then load them so they can be viewable in the identify
		var indbubble = ria[ind.id].indBubble;
		if (indbubble) {
			map.indBubble = indbubble;
			var ids = indbubble.allIds;
			var periods = indbubble.periods;
			PIndicatorLoader.load(ids, function(inds) {
				// the latest period is added as default, but if one was specified in then this sets the indicator to that period
				if (periods) {
					for (var i=0; i<inds.length; i++) {
						if (periods[i]) {
							inds[i].setPeriod(periods[i]);
						}
					}
				}

				// store indicators so when map is clicked we can use them
				map.indBubble.inds = inds;
			});
		}
		else if (globalIndListBubble) {
			// very custom, only widget site id 74 uses this for now
			map.indBubble = globalIndListBubble;
		} else {
			// clear the identify indicators so they don't carry over to other indicators identify
			map.indBubble = null;
		}

		// add indicator to global variable for text-only option
		global_indicators = [ind];
		var period = ind.getPeriod();

		// add periods to global variable for text-only option
		// but first make sure the period is allowed, if not than just add the earliest period
		// this is only for Claritas data where there's 2000,2009,2014 data. 2000 is public and allowed for all users.
		if (allowPeriod(ind, period))
			global_period = ind.getPeriod();
		else
			global_period = periods[periods.length-1];

		// Only for text only version
		if (textOnlyIsOn) {
			refreshWidgetCube();
			//pagePopUp.hide();
			$("#noDataAvailable").hide();
		}

		var legend = map.getLegend();
		legend.clearStoredScale();
		var ind = map.getIndicator();

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

		// hide button since indicator is on
		if (urlParams['altLayout'] && map.indbutton) {
			map.indbutton.hide();
		}


		// Show the download button if specified and if the indicator is allowed to be downloaded according to the users taxonomy.
		if(ind.allowDL)
			jQuery('#widgetDownload').show();
		else
			jQuery('#widgetDownload').hide();

		// hide the legend
		// This should only be done when the map is first loaded and urlparams are initiated, hence the map.winWidgetInitialized
		if (urlParams['hideleg'] && !map.windowWidgetInitialized) {
			toggleOnMapLegend(null, true);
		}
		map.windowWidgetInitialized = true;

		if (urlParams['hideSitesLegend'])
			toggleOnMapSitesLegend(null, true);

		// update the trends chart with the ind
		if (urlParams['charts']) {
			refreshWidgetCharts();
		}

		var placetype = map.getLegend().getCurrentPlaceType();
		// have to first check if it's in text-only mode, then if place the list of places is on then show that otherwise check if rankings should be on
		if (textOnlyIsOn && rPlaces.elm.css("display")!="none")
			rPlaces.load("gb", global_places[0].id, ind.id, placetype.id, ind.getPeriod(), global_places[0].getLabel(), 50);
		else if (map.widgetRankingsOn)
			refreshWidgetRankings();
	});

	PEvent.addListener(map, 'removeindicator', function(ind) {
		document.getElementById("maptitle").innerHTML = "";
		jQuery('#moretitle').hide(200);
		document.getElementById('moretitle').innerHTML = "";
		resetDetailsButton();

		// show button to turn ind back on
		if (urlParams['altLayout'] && map.indbutton) {
			map.indbutton.show();
		}
		global_indicators = [];
	});

	// indicator events
	widget = new PTRFIndicatorLegend(map, map.getLegend(),{enableToggle:true, enableShade:true, enableBreaks:true});
	var indElm = $("#legend");
	var indToggle = widget.getIndicatorToggle();
	var indicatorShade = widget.getIndicatorShade();
	var indicatorBreaks = widget.getIndicatorBreaks();

	var legendContainer = new PLegendContainer(indElm);
	widget.addListener('refresh',legendContainer.show,legendContainer);

	widget.addListener('clear',legendContainer.hide,legendContainer);

	var toggleWidget = new PIndicatorToggleWidget(indElm.find('#toggle_container'));
	indToggle.addListener('refresh', toggleWidget.refresh, toggleWidget);
	indToggle.addListener('clear', toggleWidget.clear, toggleWidget);

	var breaksWidget = new PBreaksWidget(indElm.find('#breaks_container'));
	breaksWidget.removeEditRangesLinks();
	indicatorBreaks.addListener('refresh', breaksWidget.refresh, breaksWidget);
	indicatorBreaks.addListener('clear', breaksWidget.clear, breaksWidget);

	var shadeWidget = new PIndicatorShadeWidget(indElm.find("#shade_container"));
	indicatorShade.addListener('refresh',shadeWidget.update,shadeWidget);
	indicatorShade.addListener('clear',shadeWidget.clear,shadeWidget);
	shadeWidget.addListener('change', indicatorShade.changeShade, indicatorShade);

	legendContainer.init();
	//legendContainer.show();

	// Widget object that populates the map with data from the db and from the url
	var eoptions = new EmbeddingMapOptions(map, widget, urlParams);

	PEvent.addListener(map, 'zoomend', function() {
		//session2.put('curZoom', map.getZoom());
		var legend = map.getLegend();
		
		// Map labels may need to be updated when the zoom changes.
		labelManager.updateMapLabels();
		
		legend.clearStoredScale();
		if( legend.boundaryTypeIsLocked() ) {
			if( !legend.isValidBoundaryType( map.getLegend().getBoundaryType() ) ) {
				legend.unlockBoundaryType();
			}
		}
		// refreshes map layers checkboxes
		eoptions.refreshMapOptionsLayers();
		if( map.getLegend().getBoundaryType() ) {
			widget.getIndicatorShade().setOldBoundaryTypeId(map.getLegend().getBoundaryType().id);
		}
		if( widget.legend.getBoundaryType() && widget.getIndicatorShade().getOldBoundaryTypeId() != widget.legend.getBoundaryType().id ){
			widget.getIndicatorShade().setOldBoundaryTypeId(widget.legend.getBoundaryType().id);
		}

		widget.refresh();
		map.refresh();
	});

	// Create the dataset search box.
	datasetSearch = new DatasetSearch();
	
	// See if a default search dataset has been specified.
	var dsearch = urlParams['dsearch'];
	if(dsearch) {
		// One has. Turn on searching for the specified dataset (if it exists).
		$("#dsearch" + dsearch).click();
	}

	// Adding the zoom controls after the page has been built because when it's added before it makes the zoom bar get positioned a bit off because of the absolute positioning i think.
	// Eventually should figure out how to make the positioning of the zoom bar work properly no matter what, just couldn't get it to work right yet.
	map.addControl(new PLargeMapControl());

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

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

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

// Rankings initializing function is called from MapCommon.js after everything is done loading
// And so only when rankings is set in the url will initializing go through
function initWidgetRankings() {
	var urlParams = getUrlParams();
	// Hide the rankings td when neither rankings nor text only are enabled, as it has
	// a large padding.
	if(!urlParams['ranking']) {
		if(!urlParams['textonly']) {
			$(".rankingsTD").hide();
			return;
		}
	} else {
		map.widgetRankingsOn = true;
	}
	
	rRanks = new ReportRanks();
	if (urlParams['search']) {
		search.addListener('response', function(places) {
			var placetype = map.getLegend().getCurrentPlaceType();
			// If an address is searched find the containing place and show that in rankings.
			if (places instanceof PAddress) {
				if (places.wasFound()) {
					var point = new PLatLng(places.y, places.x);
					point.getPlacesContaining(placetype, function(places) {
						refreshWidgetRankings(places[0]);
					});
				}
			}
			else {
				global_places = [places[0]];
				var ind = map.getIndicator();
				// for text-only if popup is already open then refresh it, this will replace the rankings
				if (textOnlyIsOn && rPlaces.elm.css("display")!="none")
					rPlaces.load("gb", places[0].id, ind.id, placetype.id, ind.getPeriod(), places[0].getLabel(), 50);
				else {
					refreshWidgetRankings();
				}
			}
		});
	}
	refreshWidgetRankings();
}

function refreshWidgetRankings(place) {
	// only refresh rankings if it was set up
	if (!map.widgetRankingsOn || !map.getIndicator())
		return;
	
	var currentLegend = map.getLegend();
	var currentInd = currentLegend.getIndicator();
	var currentIndId = currentInd.getID();
	var currentPeriod = currentInd.getPeriod();
	var currentPlaceTypeId = currentLegend.getCurrentPlaceType().id;

	// Replace the place used everytime a place is added to the map.
	if (place) 
		global_places = [place];
	
	// If no place was specified, then we just want to bring up a ranking box for the current placetype.
	// Our entire ranks system is based on us passing a place, and the ranks being returned revolving
	// around that place. Changing that to support just getting ranks without a place is far too big of
	// an undertaking for how quickly this needed to get done, so instead, a servlet was written that
	// will return the id of any place of a given indicator, period, placetype, and rank. We'll request
	// the place in the #1 ranking spot, and use that to build the rankings.
	if(global_places.length > 0) {
		generateRankings(currentInd, global_places[0], currentPeriod);
	} else {
		PAsync.call(PEnvironment.servletsUrl + '/rank/?ind=' + currentIndId + '&per=' + currentPeriod + '&type=' + currentPlaceTypeId + '&rank=1', this, function(places) {
			// As long as we received our place, send it off to generate the rankings.
			// Multiple places may have been returned if more than one place is tied
			// for first. They are returned in the order that they appear in the
			// ranking list, so we just want to use the first one.
			if(places.length > 0) {
				PPlaceLoader.load([places[0]], function(placeObject) {
					generateRankings(currentInd, placeObject[0], currentPeriod);
				});
			}
		});
	}
}

function generateRankings(ind, place, period) {
	rankingCube = new PRankingCube([ind], [place], [period]);
	rankingCube.setOptions(new PRankingCubeOptions( {
		loadValues : true,
		loadRanks : true
	}));
	rankingCube.loadValues(function(v) {
		this.loading = false;
		this.values = v;
		var val = v[this.getPeriods()[0]][this.getPlaces()[0].id][this.getIndicators()[0].id];
		var rankValue = new PRankingValue({value:val.value,rank:val.rank,position:val.position,totalRanked:val.totalRanked,totalBoundaries:val.totalBoundaries})
		rRanks.load(this.getPlaces()[0], this.getIndicators()[0], this.getPeriods()[0], rankValue);
	});
}

function clearIndicatorData() {
	var urlParams = getUrlParams();
	widget.clear();
	if (pagePopUp) {
		pagePopUp.hide();
		$("#noDataAvailable").hide();
	}

	if (map.indbutton && (urlParams['altLayout'] || urlParams['hideimenu'])) {
		map.indbutton.show();
	}
}

function resetWidget() {
	clearIndicatorData();
	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 = "";
	resetDetailsButton();

	search.reset();

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

	global_places = [];
	global_period = null;
	global_indicators = [];
	if (pagePopUp) {
		pagePopUp.hide();
		$("#noDataAvailable").hide();
	}
	
	if (textOnlyIsOn) {
		table.clear();
		jQuery("#similarbox").html("");
	}
}

function textOnlyToggle(elem) {
	var urlParams = getUrlParams();
	if (!textOnlyIsOn) {
		textOnlyIsOn = true;
		// create table and set search event
		if (!table) {
			var tableoptions = new PTableOptions();
			tableoptions.removeButton.src = 'images/createtable-header-close.png';
			tableoptions.removeButton.style.padding = '0px 2px';
			tableoptions.removeButton.alt = "Remove";
			tableoptions.rowHeading = "";
			tableoptions.displayPeriods = false;
			tableoptions.disableToggles = true;

			table = new PTable(document.getElementById("table"), tableoptions);
		        rPlaces = new ReportPlaces();
		        rPins = new ReportPins();

			if (!search)
				initSearchBox();

			table.searchEvent = search.addListener('response', function(places) {
				textOnlyLoadPlace(places);
			});
		}
		
		refreshWidgetCube();
		jQuery("#widgetcolumn").css({"width":"260px","font-size":"11px"});
		jQuery(".horMenu_widget").removeClass("horMenu");
		jQuery(".horMenu_widget").addClass("textOnlyMenu");
		jQuery(elem).html("Back to Original Version");

		// add class that will somewhat take care of adding the style for the text only version
		jQuery(".WidgetPageContent").addClass("TextOnlyOn");
	}
	else {
		textOnlyIsOn = false;
		jQuery("#widgetcolumn").css({"width":"175px","font-size":"medium"});
		jQuery("#similarbox").html("");
		if (!urlParams['search'])
			jQuery('#widgetSearchboxContainer').hide();
		
		jQuery(".horMenu_widget").removeClass("textOnlyMenu");
		jQuery(".horMenu_widget").addClass("horMenu");
		jQuery(elem).html("Text-Only");

		jQuery(".WidgetPageContent").removeClass("TextOnlyOn");
	}
}

function textOnlyLoadPlace(places) {
	// Moved this into its own function so it can also be called by the
	// autosuggest dropdown and by clicking on one of the breadcrumbs.
	global_places = [places[0]];
	var html = createSimilarResultsDiv(places);
	jQuery("#similarbox").html(html);
	refreshWidgetCube();
}

function refreshWidgetCube() {
	var ind = global_indicators[0];
	if (rPlaces.elm.css("display") != "none") {
		var placetype = map.getLegend().getCurrentPlaceType();
		rPlaces.load("gb", global_places[0].id, ind.id, placetype.id, ind.getPeriod(), global_places[0].getLabel(), 50);
	}

	cube = new PCube(global_indicators,global_places,[global_period]);
	cube.loadValues(function(values) {
		this.values = values;
		table.setData(this);
		table.refresh();
	});
}

function createSimilarResultsDiv(places) {
	var box = document.createElement("div");
	box.className = "similarresults";

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

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

	// Display other results if more than 1
	if (places.length > 1) {
		var similar = document.createElement("div");
		similar.innerHTML = "<br><b>Similar Results:</b><br>";
		html.appendChild(similar);
		for (var i=1; i<places.length; i++) {
			var anchor = document.createElement("a");
			anchor.innerHTML = places[i].getLabel() + getState(places[i]) + " (" + places[i].getType().getName() + ")";
			anchor.place = places[i];
			PEvent.addListener(anchor, 'click', function() {
				global_places = [this.place];
				refreshWidgetCube();
			});

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

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

function downloadData() {
	// Generates a CSV containing all data for the current indicator
	// at the currently selected placetype level.
	
	// Get the current indicator, period, and selected placetype.
	var currentLegend = map.getLegend();
	var currentInd = currentLegend.getIndicator();
	var currentIndPeriod = currentInd.periods[currentInd.curPerIndex];
	var currentPlaceType = currentLegend.getCurrentPlaceType();

	// if indicator is not allowed to be downloaded for this widget
	// and somehow this function is called.
	if (!currentInd.allowDL) {
		var alerter = new PAlerter();
		alerter.popup("This data is not downloadable.", null, null, "OK");
		return;
	}

	// Send the request.
	var geocoder = new PClientGeocoder();
	geocoder.getAllPlacesCSV(currentPlaceType, currentInd, currentIndPeriod);
	
	// Display an alert letting the user know the CSV will take a few moments.
	var alerter = new PAlerter();
	alerter.popup("Your data is being prepared and will be ready in a few moments.", null, null, "OK");
}

function printWidget() {
	// Called when the user wants to generate a print of the widget. A form exists on the
	// JSP that has hidden fields for the different arguments. This is used to submit the
	// print request to the WidgetPrint servlet (so it can use POST in case the arguments
	// are too long for certain browsers). The servlet responds with the generated image
	// as an attachment so the browser won't actually leave the current page.
	
	// First put together the print arguments.
	var args = genMapJpgLink("PolicyMapWidgetPage");
	// Set the action of the hidden form if it hasn't been set already.
	if($("#widgetprint").attr("action") == "") {
		$("#widgetprint").attr("action", PEnvironment.widgetPrintUrl);
	}
	// Set the hidden fields of the form to be our POST arguments.
	$("#p_act").val("print");
	$("#p_type").val("jpg");
	$("#p_template").val("PolicyMapWidgetPage");
	$("#p_sid").val(PEnvironment.widgetParams.sid);
	$("#p_parms").val(args);
	// Submit the form.
	$("#widgetprint").submit();
}

function customizeLegendZoomsAndContainments() {
	// Legend and containment settings for DePaul widget
	// Can't use the getUrlParams function here because it messes up the widget params since this function is called globally
	// and then the merge of the url and widget params are done too soon.
	var sid = PWebUtil.parseQuery(window.location.search)['sid'];
	if (sid == 52) {
		// add cumstom boundary to global placetype array
		P_PLACETYPES.push(PPlaceType.COMMUNITY_AREA);
		PPlaceTypeConfig.PLEGEND = new PPlaceTypeConfig();
		PPlaceTypeConfig.PLEGEND.zooms[0] = PPlaceType.CITY;
		PPlaceTypeConfig.PLEGEND.zooms[8] = PPlaceType.COMMUNITY_AREA;
		PPlaceTypeConfig.PLEGEND.zooms[11] = PPlaceType.CENSUSTRACT;

		// add custom boundary to containments so it shows in identify
		PPlaceTypeConfig.containmentOrder = [PPlaceType.COUNTRY, PPlaceType.STATE, PPlaceType.CDBG, PPlaceType.CONGRESSIONAL,
				PPlaceType.CBSA_07, PPlaceType.COUNTY, PPlaceType.MD, PPlaceType.COUNTY_SUBDIVISION,
				PPlaceType.SLD_UPPER, PPlaceType.SLD_LOWER, PPlaceType.CITY, PPlaceType.SCHOOL,
				PPlaceType.ZIP, PPlaceType.COMMUNITY_AREA, PPlaceType.CENSUSTRACT, PPlaceType.BLOCKGROUP];
        }
	else if (sid == 70) {
		// add cumstom boundary to global placetype array
		PPlaceType.APPSTATE = new PPlaceType(103,"Appalachian States", "boundary_type_appstate");
		PPlaceType.APPSSUBR = new PPlaceType(104,"Appalachian Subregions", "boundary_type_appsubr");
		P_PLACETYPES.push(PPlaceType.APPSTATE);
		P_PLACETYPES.push(PPlaceType.APPSSUBR);
		PPlaceTypeConfig.PLEGEND = new PPlaceTypeConfig();
		PPlaceTypeConfig.PLEGEND.zooms[0] = [PPlaceType.APPSSUBR,PPlaceType.APPSTATE];
		PPlaceTypeConfig.PLEGEND.zooms[3] = [PPlaceType.CITY,PPlaceType.SLD_LOWER,PPlaceType.SLD_UPPER,PPlaceType.MD,PPlaceType.CBSA_07,PPlaceType.CONGRESSIONAL, PPlaceType.CDBG];
		PPlaceTypeConfig.PLEGEND.zooms[4] = [PPlaceType.APPSTATE,PPlaceType.COUNTY];
		PPlaceTypeConfig.PLEGEND.zooms[5] = [PPlaceType.COUNTY,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;

		// add custom boundary to containments so it shows in identify
		PPlaceTypeConfig.containmentOrder = [PPlaceType.COUNTRY, PPlaceType.APPSSUBR, PPlaceType.APPSTATE, PPlaceType.STATE, PPlaceType.CDBG, PPlaceType.CONGRESSIONAL,
				PPlaceType.CBSA_07, PPlaceType.COUNTY, PPlaceType.MD, PPlaceType.COUNTY_SUBDIVISION,
				PPlaceType.SLD_UPPER, PPlaceType.SLD_LOWER, PPlaceType.CITY, PPlaceType.SCHOOL,
				PPlaceType.ZIP, PPlaceType.COMMUNITY_AREA, PPlaceType.CENSUSTRACT, PPlaceType.BLOCKGROUP];
        }
	else if (sid == 71) {
		// add cumstom boundary to global placetype array
		PPlaceType.APPSTATE = new PPlaceType(103,"Appalachian States", "boundary_type_appstate");
		PPlaceType.APPSSUBR = new PPlaceType(104,"Appalachian Subregions", "boundary_type_appsubr");
		P_PLACETYPES.push(PPlaceType.APPSTATE);
		P_PLACETYPES.push(PPlaceType.APPSSUBR);
		PPlaceTypeConfig.PLEGEND = new PPlaceTypeConfig();
		PPlaceTypeConfig.PLEGEND.zooms[0] = [PPlaceType.APPSSUBR,PPlaceType.APPSTATE];
		PPlaceTypeConfig.PLEGEND.zooms[4] = [PPlaceType.APPSTATE,PPlaceType.COUNTY];
		PPlaceTypeConfig.PLEGEND.zooms[5] = PPlaceType.COUNTY;

		// add custom boundary to containments so it shows in identify
		PPlaceTypeConfig.containmentOrder = [PPlaceType.COUNTRY, PPlaceType.APPSSUBR, PPlaceType.APPSTATE, PPlaceType.STATE, PPlaceType.CDBG, PPlaceType.CONGRESSIONAL,
				PPlaceType.CBSA_07, PPlaceType.COUNTY, PPlaceType.MD, PPlaceType.COUNTY_SUBDIVISION,
				PPlaceType.SLD_UPPER, PPlaceType.SLD_LOWER, PPlaceType.CITY, PPlaceType.SCHOOL,
				PPlaceType.ZIP, PPlaceType.COMMUNITY_AREA, PPlaceType.CENSUSTRACT, PPlaceType.BLOCKGROUP];
        }
	else if (sid == 79) {
		// add cumstom boundary to global placetype array
		PPlaceType.BALTIMORE_CSA = new PPlaceType(105,"Baltimore CSA", "boundary_type_baltimore_csa");
		P_PLACETYPES.push(PPlaceType.BALTIMORE_CSA);
		PPlaceTypeConfig.PLEGEND = new PPlaceTypeConfig();
		PPlaceTypeConfig.PLEGEND.zooms[0] = [PPlaceType.BALTIMORE_CSA];
		PPlaceTypeConfig.PLEGEND.zooms[12] = [PPlaceType.BALTIMORE_CSA];

		// add custom boundary to containments so it shows in identify
		PPlaceTypeConfig.containmentOrder = [PPlaceType.COUNTRY, PPlaceType.STATE, PPlaceType.CDBG, PPlaceType.CONGRESSIONAL,
				PPlaceType.CBSA_07, PPlaceType.COUNTY, PPlaceType.MD, PPlaceType.COUNTY_SUBDIVISION,
				PPlaceType.SLD_UPPER, PPlaceType.SLD_LOWER, PPlaceType.CITY, PPlaceType.SCHOOL, PPlaceType.BALTIMORE_CSA, 
				PPlaceType.ZIP, PPlaceType.COMMUNITY_AREA, PPlaceType.CENSUSTRACT, PPlaceType.BLOCKGROUP];
        }
	else if (sid == 94) {
		// make state the only available boundary type for this widgets indicators
		PPlaceTypeConfig.PLEGEND.zooms[0] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[1] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[2] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[3] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[4] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[5] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[6] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[7] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[8] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[9] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[10] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[11] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[12] = PPlaceType.STATE;
	}
	else if (sid == 95) {
		// make cbsa available at the US view zoom level
		PPlaceTypeConfig.PLEGEND.zooms[2] = PPlaceType.CBSA_07;
	}
	else if (sid == 97) {
		// make cbsa and state only available boundary types for this widget
		PPlaceTypeConfig.PLEGEND.zooms[0] = PPlaceType.STATE;
		PPlaceTypeConfig.PLEGEND.zooms[2] = PPlaceType.CBSA_07;
		PPlaceTypeConfig.PLEGEND.zooms[3] = PPlaceType.CBSA_07;
	}
}

function customizeColorRampsForWidget(urlParams) {
	if (urlParams['sid'] == 46) {
		PColorRamp.MVA[9850220] = [new PColor('f7736f'),new PColor('838282')];
		PColorRamp.MVA[9850206] = [new PColor('f7736f'),new PColor('838282')];
	}
}

function customizeMapLayersForWidget(urlParams) {
	if (urlParams['sid'] == 61) {
		// Set up custom county labels for this widget
		PMapLayer.COUNTY_NONMETRO_LABEL = new PMapLayer();
		PMapLayer.COUNTY_NONMETRO_LABEL.name = 'countylabels_nonmetros';
		PMapLayer.COUNTY_NONMETRO_LABEL.title = 'Non-Metro County Labels';
		PMapLayer.COUNTY_NONMETRO_LABEL.minScale = 72000;
		PMapLayer.COUNTY_NONMETRO_LABEL.maxScale = 9216000;

		// turn off layer
		PMapLayer.COUNTY_NONMETRO_LABEL.off();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.COUNTY_NONMETRO_LABEL);
		// change the label layer used with the county bounds layer
		MAPLAYER_LABELS[PMapLayer.COUNTY.name] = PMapLayer.COUNTY_NONMETRO_LABEL;
	}
	else if (urlParams['sid'] == 62 || urlParams['sid'] == 65 || urlParams['sid'] == 67 || urlParams['sid'] == 68 || urlParams['sid'] == 88 || urlParams['sid'] == 91) {
		// Set up custom hartford neighborhoods layers for this widget
		PMapLayer.HARTFORD_HOOD = new PMapLayer();
		PMapLayer.HARTFORD_HOOD.name = 'hartford_nhoodbounds';
		PMapLayer.HARTFORD_HOOD.title = 'Hartford Neighborhoods';
		PMapLayer.HARTFORD_HOOD.maxScale = 144000;

		PMapLayer.HARTFORD_HOOD_LABEL = new PMapLayer();
		PMapLayer.HARTFORD_HOOD_LABEL.name = 'hartford_nhoodlabels';
		PMapLayer.HARTFORD_HOOD_LABEL.title = 'Hartford Neighborhoods Labels';
		PMapLayer.HARTFORD_HOOD_LABEL.maxScale = 144000;

		// turn off layer
		PMapLayer.HARTFORD_HOOD.off();
		PMapLayer.HARTFORD_HOOD_LABEL.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.HARTFORD_HOOD);
		PMapType.DEFAULT.addMapLayer(PMapLayer.HARTFORD_HOOD_LABEL);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.HARTFORD_HOOD);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.HARTFORD_HOOD.name] = PMapLayer.HARTFORD_HOOD_LABEL;
	}
	else if (urlParams['sid'] == 66) {
		PMapLayer.FLOODHIGH = new PMapLayer();
		PMapLayer.FLOODHIGH.name = 'floodmap_high';
		PMapLayer.FLOODHIGH.title = 'High';

		// turn off layer
		PMapLayer.FLOODHIGH.off();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.FLOODHIGH, 3);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.FLOODHIGH);

		PMapLayer.FLOODMOD = new PMapLayer();
		PMapLayer.FLOODMOD.name = 'floodmap_moderate';
		PMapLayer.FLOODMOD.title = 'Moderate';

		// turn off layer
		PMapLayer.FLOODMOD.off();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.FLOODMOD, 3);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.FLOODMOD);

		PMapLayer.FLOODUND = new PMapLayer();
		PMapLayer.FLOODUND.name = 'floodmap_undetermined';
		PMapLayer.FLOODUND.title = 'Undetermined';

		// turn off layer
		PMapLayer.FLOODUND.off();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.FLOODUND, 3);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.FLOODUND);
		
		PMapLayer.FLOODMIN = new PMapLayer();
		PMapLayer.FLOODMIN.name = 'floodmap_minimal';
		PMapLayer.FLOODMIN.title = 'Minimal';

		// turn off layer
		PMapLayer.FLOODMIN.off();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.FLOODMIN, 3);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.FLOODMIN);
	}
	else if (urlParams['sid'] == 70 || urlParams['sid'] == 71) {
		PMapLayer.APP_LDDBOUNDS = new PMapLayer();
		PMapLayer.APP_LDDBOUNDS.name = 'app_lddbounds';
		PMapLayer.APP_LDDBOUNDS.title = 'Local Development Districts';
		PMapLayer.APP_LDDBOUNDS.maxScale = 9216000;

		PMapLayer.APP_LDDLABELS = new PMapLayer();
		PMapLayer.APP_LDDLABELS.name = 'app_lddlabels';
		PMapLayer.APP_LDDLABELS.title = 'Local Development Districts Labels';
		PMapLayer.APP_LDDLABELS.maxScale = 1152000;

		// turn off layer
		PMapLayer.APP_LDDBOUNDS.off();
		PMapLayer.APP_LDDLABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.APP_LDDBOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.APP_LDDLABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.APP_LDDBOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.APP_LDDBOUNDS.name] = PMapLayer.APP_LDDLABELS;
	}
	else if (urlParams['sid'] == 59) {
		// we don't want to show the county labels so remove them
		MAPLAYER_LABELS[PMapLayer.COUNTY.name] = null;

		// Custom layer that shades around philly so philly stands out
		PMapLayer.PHILLY_HOLE = new PMapLayer();
		PMapLayer.PHILLY_HOLE.name = 'philly_hole';
		PMapLayer.PHILLY_HOLE.title = 'Philadelphia';
		PMapLayer.PHILLY_HOLE.minScale = 4500;

		// turn on layer
		PMapLayer.PHILLY_HOLE.on();
		PMapLayer.COUNTY.on();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_HOLE);
	}
	else if (urlParams['sid'] == 79) {
		PMapLayer.BALTIMORE_CSABOUNDS = new PMapLayer();
		PMapLayer.BALTIMORE_CSABOUNDS.name = 'baltimore_csabounds';
		PMapLayer.BALTIMORE_CSABOUNDS.title = 'Baltimore Community Statistical Area';
		PMapLayer.BALTIMORE_CSABOUNDS.maxScale = 576000;

		PMapLayer.BALTIMORE_CSALABELS = new PMapLayer();
		PMapLayer.BALTIMORE_CSALABELS.name = 'baltimore_csalabels';
		PMapLayer.BALTIMORE_CSALABELS.title = 'Baltimore Community Statistical Area Labels';
		PMapLayer.BALTIMORE_CSALABELS.maxScale = 72000;

		// turn off layer
		PMapLayer.BALTIMORE_CSABOUNDS.off();
		PMapLayer.BALTIMORE_CSALABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.BALTIMORE_CSABOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.BALTIMORE_CSALABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.BALTIMORE_CSABOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.BALTIMORE_CSABOUNDS.name] = PMapLayer.BALTIMORE_CSALABELS;
		
		// Custom layer that shades around baltimore so it stands out
		PMapLayer.BALTIMORE_HOLE = new PMapLayer();
		PMapLayer.BALTIMORE_HOLE.name = 'baltimore_hole';
		PMapLayer.BALTIMORE_HOLE.title = 'Baltimore';
		PMapLayer.BALTIMORE_HOLE.minScale = 4500;

		// turn on layer
		PMapLayer.BALTIMORE_HOLE.on();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.BALTIMORE_HOLE);
	}
	else if (urlParams['sid'] == 76) {
		PMapLayer.PHILLY_CA_BOUNDS = new PMapLayer();
		PMapLayer.PHILLY_CA_BOUNDS.name = 'philly_ca_bounds';
		PMapLayer.PHILLY_CA_BOUNDS.title = 'Civic Associations';
		PMapLayer.PHILLY_CA_BOUNDS.maxScale = 576000;

		PMapLayer.PHILLY_CA_LABELS = new PMapLayer();
		PMapLayer.PHILLY_CA_LABELS.name = 'philly_ca_labels';
		PMapLayer.PHILLY_CA_LABELS.title = 'Civic Associations Labels';
		PMapLayer.PHILLY_CA_LABELS.maxScale = 144000;

		// turn off layer
		PMapLayer.PHILLY_CA_BOUNDS.off();
		PMapLayer.PHILLY_CA_LABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_CA_BOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_CA_LABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_CA_BOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.PHILLY_CA_BOUNDS.name] = PMapLayer.PHILLY_CA_LABELS;
		
		PMapLayer.PHILLY_CD_BOUNDS = new PMapLayer();
		PMapLayer.PHILLY_CD_BOUNDS.name = 'philly_cd_bounds';
		PMapLayer.PHILLY_CD_BOUNDS.title = 'Council District (2000)';
		PMapLayer.PHILLY_CD_BOUNDS.maxScale = 576000;

		PMapLayer.PHILLY_CD_LABELS = new PMapLayer();
		PMapLayer.PHILLY_CD_LABELS.name = 'philly_cd_labels';
		PMapLayer.PHILLY_CD_LABELS.title = 'Council District (2000) Labels';
		PMapLayer.PHILLY_CD_LABELS.maxScale = 144000;

		// turn off layer
		PMapLayer.PHILLY_CD_BOUNDS.off();
		PMapLayer.PHILLY_CD_LABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_CD_BOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_CD_LABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_CD_BOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.PHILLY_CD_BOUNDS.name] = PMapLayer.PHILLY_CD_LABELS;
		
		PMapLayer.PHILLY_NHOOD_BOUNDS = new PMapLayer();
		PMapLayer.PHILLY_NHOOD_BOUNDS.name = 'philly_nhood_bounds';
		PMapLayer.PHILLY_NHOOD_BOUNDS.title = 'Neighborhoods';
		PMapLayer.PHILLY_NHOOD_BOUNDS.maxScale = 576000;

		PMapLayer.PHILLY_NHOOD_LABELS = new PMapLayer();
		PMapLayer.PHILLY_NHOOD_LABELS.name = 'philly_nhood_labels';
		PMapLayer.PHILLY_NHOOD_LABELS.title = 'Neighborhoods Labels';
		PMapLayer.PHILLY_NHOOD_LABELS.maxScale = 144000;

		// turn off layer
		PMapLayer.PHILLY_NHOOD_BOUNDS.off();
		PMapLayer.PHILLY_NHOOD_LABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_NHOOD_BOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_NHOOD_LABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_NHOOD_BOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.PHILLY_NHOOD_BOUNDS.name] = PMapLayer.PHILLY_NHOOD_LABELS;
		
		PMapLayer.PHILLY_PD_BOUNDS = new PMapLayer();
		PMapLayer.PHILLY_PD_BOUNDS.name = 'philly_pd_bounds';
		PMapLayer.PHILLY_PD_BOUNDS.title = 'Planning Districts';
		PMapLayer.PHILLY_PD_BOUNDS.maxScale = 576000;

		PMapLayer.PHILLY_PD_LABELS = new PMapLayer();
		PMapLayer.PHILLY_PD_LABELS.name = 'philly_pd_labels';
		PMapLayer.PHILLY_PD_LABELS.title = 'Planning Districts Labels';
		PMapLayer.PHILLY_PD_LABELS.maxScale = 144000;

		// turn off layer
		PMapLayer.PHILLY_PD_BOUNDS.off();
		PMapLayer.PHILLY_PD_LABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_PD_BOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_PD_LABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_PD_BOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.PHILLY_PD_BOUNDS.name] = PMapLayer.PHILLY_PD_LABELS;
		
		PMapLayer.PHILLY_REGIONALRAIL_LINES = new PMapLayer();
		PMapLayer.PHILLY_REGIONALRAIL_LINES.name = 'philly_regionalrail_lines';
		PMapLayer.PHILLY_REGIONALRAIL_LINES.title = 'Regional Rail';
		PMapLayer.PHILLY_REGIONALRAIL_LINES.maxScale = 288000;

		// turn off layer
		PMapLayer.PHILLY_REGIONALRAIL_LINES.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_REGIONALRAIL_LINES);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_REGIONALRAIL_LINES);
		
		PMapLayer.PHILLY_BUS_LINES = new PMapLayer();
		PMapLayer.PHILLY_BUS_LINES.name = 'philly_bus_lines';
		PMapLayer.PHILLY_BUS_LINES.title = 'Bus Routes';
		PMapLayer.PHILLY_BUS_LINES.maxScale = 288000;
		
		// turn off layer
		PMapLayer.PHILLY_BUS_LINES.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_BUS_LINES);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_BUS_LINES);
		
		PMapLayer.PHILLY_BIKE_LINES = new PMapLayer();
		PMapLayer.PHILLY_BIKE_LINES.name = 'philly_bike_lines';
		PMapLayer.PHILLY_BIKE_LINES.title = 'Bike Networks';
		PMapLayer.PHILLY_BIKE_LINES.maxScale = 288000;

		// turn off layer
		PMapLayer.PHILLY_BIKE_LINES.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_BIKE_LINES);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_BIKE_LINES);
		
		PMapLayer.PHILLY_BROADRAIL_LINES = new PMapLayer();
		PMapLayer.PHILLY_BROADRAIL_LINES.name = 'philly_broadrail_lines';
		PMapLayer.PHILLY_BROADRAIL_LINES.title = 'Broad Street Line';
		PMapLayer.PHILLY_BROADRAIL_LINES.maxScale = 288000;
		PMapLayer.PHILLY_BROADRAIL_LINES.pointDataset = new POverlaySet(112300, PinIcons.circle_blue, 15);
		PMapLayer.PHILLY_BROADRAIL_LINES.pointDataset.withLayer = true;
		PMapLayer.PHILLY_BROADRAIL_LINES.pointDataset.off();
		
		// turn off layer
		PMapLayer.PHILLY_BROADRAIL_LINES.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_BROADRAIL_LINES);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_BROADRAIL_LINES);

		PMapLayer.PHILLY_MARKETRAIL_LINES = new PMapLayer();
		PMapLayer.PHILLY_MARKETRAIL_LINES.name = 'philly_marketrail_lines';
		PMapLayer.PHILLY_MARKETRAIL_LINES.title = 'Market-Frankford Line';
		PMapLayer.PHILLY_MARKETRAIL_LINES.maxScale = 288000;
		PMapLayer.PHILLY_MARKETRAIL_LINES.pointDataset = new POverlaySet(112250, PinIcons.circle_blue, 15);
		PMapLayer.PHILLY_MARKETRAIL_LINES.pointDataset.withLayer = true;
		PMapLayer.PHILLY_MARKETRAIL_LINES.pointDataset.off();
		
		// turn off layer
		PMapLayer.PHILLY_MARKETRAIL_LINES.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PHILLY_MARKETRAIL_LINES);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PHILLY_MARKETRAIL_LINES);
	}
		else if (urlParams['sid'] == 82) {
		PMapLayer.DVGBC_BRANCHESBOUNDS = new PMapLayer();
		PMapLayer.DVGBC_BRANCHESBOUNDS.name = 'dvgbc_branchesbounds';
		PMapLayer.DVGBC_BRANCHESBOUNDS.title = 'DVGBC Branches';
		PMapLayer.DVGBC_BRANCHESBOUNDS.maxScale = 2304000;

		PMapLayer.DVGBC_BRANCHESLABELS = new PMapLayer();
		PMapLayer.DVGBC_BRANCHESLABELS.name = 'dvgbc_brancheslabels';
		PMapLayer.DVGBC_BRANCHESLABELS.title = 'DVGBC Branches Labels';
		PMapLayer.DVGBC_BRANCHESLABELS.maxScale = 2304000;

		// turn off layer
		PMapLayer.DVGBC_BRANCHESBOUNDS.off();
		PMapLayer.DVGBC_BRANCHESLABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.DVGBC_BRANCHESBOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.DVGBC_BRANCHESLABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.DVGBC_BRANCHESBOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.DVGBC_BRANCHESBOUNDS.name] = PMapLayer.DVGBC_BRANCHESLABELS;
		
		PMapLayer.PA_CHAPTERSBOUNDS = new PMapLayer();
		PMapLayer.PA_CHAPTERSBOUNDS.name = 'pa_chaptersbounds';
		PMapLayer.PA_CHAPTERSBOUNDS.title = 'Pennsylvania Chapters';
		PMapLayer.PA_CHAPTERSBOUNDS.maxScale = 2304000;

		PMapLayer.PA_CHAPTERSLABELS = new PMapLayer();
		PMapLayer.PA_CHAPTERSLABELS.name = 'pa_chapterslabels';
		PMapLayer.PA_CHAPTERSLABELS.title = 'PA Chapters Labels';
		PMapLayer.PA_CHAPTERSLABELS.maxScale = 2304000;

		// turn off layer
		PMapLayer.PA_CHAPTERSBOUNDS.off();
		PMapLayer.PA_CHAPTERSLABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PA_CHAPTERSBOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.PA_CHAPTERSLABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PA_CHAPTERSBOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.PA_CHAPTERSBOUNDS.name] = PMapLayer.PA_CHAPTERSLABELS;
		
		PMapLayer.PA_HOUSEBOUNDS = new PMapLayer();
		PMapLayer.PA_HOUSEBOUNDS.name = 'pa_housebounds';
		PMapLayer.PA_HOUSEBOUNDS.title = 'PA House Districts';
		PMapLayer.PA_HOUSEBOUNDS.maxScale = 1152000;

		PMapLayer.PA_HOUSELABELS = new PMapLayer();
		PMapLayer.PA_HOUSELABELS.name = 'pa_houselabels';
		PMapLayer.PA_HOUSELABELS.title = 'PA House District Labels';
		PMapLayer.PA_HOUSELABELS.maxScale = 288000;

		// turn off layer
		PMapLayer.PA_HOUSEBOUNDS.off();
		PMapLayer.PA_HOUSELABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PA_HOUSEBOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.PA_HOUSELABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PA_HOUSEBOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.PA_HOUSEBOUNDS.name] = PMapLayer.PA_HOUSELABELS;
		
		PMapLayer.PA_SENATEBOUNDS = new PMapLayer();
		PMapLayer.PA_SENATEBOUNDS.name = 'pa_senatebounds';
		PMapLayer.PA_SENATEBOUNDS.title = 'PA Senate Districts';
		PMapLayer.PA_SENATEBOUNDS.maxScale = 1152000;

		PMapLayer.PA_SENATELABELS = new PMapLayer();
		PMapLayer.PA_SENATELABELS.name = 'pa_senatelabels';
		PMapLayer.PA_SENATELABELS.title = 'PA Senate District Labels';
		PMapLayer.PA_SENATELABELS.maxScale = 288000;

		// turn off layer
		PMapLayer.PA_SENATEBOUNDS.off();
		PMapLayer.PA_SENATELABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.PA_SENATEBOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.PA_SENATELABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.PA_SENATEBOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.PA_SENATEBOUNDS.name] = PMapLayer.PA_SENATELABELS;
	}
	else if (urlParams['sid'] == 85) {
		PMapLayer.WK_MDMSABOUNDS = new PMapLayer();
		PMapLayer.WK_MDMSABOUNDS.name = 'wk_mdmsabounds';
		PMapLayer.WK_MDMSABOUNDS.title = 'MD/MSA';
		PMapLayer.WK_MDMSABOUNDS.maxScale = 4608000;

		PMapLayer.WK_MDMSALABELS = new PMapLayer();
		PMapLayer.WK_MDMSALABELS.name = 'wk_mdmsalabels';
		PMapLayer.WK_MDMSALABELS.title = 'MD/MSA';
		PMapLayer.WK_MDMSALABELS.maxScale = 2304000;

		// turn off layer
		PMapLayer.WK_MDMSABOUNDS.off();
		PMapLayer.WK_MDMSALABELS.off();
		// add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.WK_MDMSABOUNDS);
		PMapType.DEFAULT.addMapLayer(PMapLayer.WK_MDMSALABELS);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.WK_MDMSABOUNDS);
		// assign the labels to the bounds layer
		MAPLAYER_LABELS[PMapLayer.WK_MDMSABOUNDS.name] = PMapLayer.WK_MDMSALABELS;
		
		PMapLayer.FLOODHIGH = new PMapLayer();
		PMapLayer.FLOODHIGH.name = 'floodmap_high';
		PMapLayer.FLOODHIGH.title = 'High';

		// turn off layer
		PMapLayer.FLOODHIGH.off();
		// and add it to the default maptype
		PMapType.DEFAULT.addMapLayer(PMapLayer.FLOODHIGH, 3);
		// add it to the global map layers array, only the bounds needs to be added
		MAPLAYER_OPTIONS.push(PMapLayer.FLOODHIGH);
	}
}

function getWidgetParams(urlParams) {
	// this way we don't merge the 2 objects every time this function is called
	if (PEnvironment.isWidgetParamsSet)
		return PEnvironment.widgetParams;

	// Removing these from original widget urls so we can override them with the values that are now in the db
	// For now the other remaining url parameters will override what's in the db
	delete urlParams["i"];
	delete urlParams["o"];
	delete urlParams["ofilters"];
	delete urlParams["ml"];
	delete urlParams["mlon"];
	delete urlParams["mltitle"];

	// for now merging the 2 but i think in the end i'll just use the widget params and maybe specific url parameters will be able to override what's in the db
	var widgetParams = jQuery.extend(PEnvironment.widgetParams, urlParams);
	PEnvironment.widgetParams = widgetParams;
	PEnvironment.isWidgetParamsSet = true;
	return widgetParams;
}

function toggleOnMapSitesLegend(elem, hide) {
	if (elem)
		$(elem).toggleClass("hide");

	if (hide || (elem && $(elem).hasClass("hide"))) {
		$(sitelegends.mapLegend).find('.toggleText').html('Show Legend');
		$(sitelegends.mapLegendContent).hide();
	}
	else {
		$(sitelegends.mapLegend).find('.toggleText').html('Hide Legend');
		$(sitelegends.mapLegendContent).show();
	}
}

/* if the indicator menu has one item in the menu it means we shouldn't show the menu */
function doesIndMenuHaveOneItem() {
	if ($('#ind_menu_widget').find('a.clickable').length == 1)
		return true;
	else
		return false;
}

// Check if buttons should be added on the map to add the data.
// Buttons get added only when both menus have 1 or no items in them
// So if one of the menus has more than 1 item then no buttons are added
function shouldWidgetMapDataButtonsBeAdded() {
	if ($('#ind_menu_widget').find('a.clickable').length <= 1 && sitelegends.legends.length <= 1)
		return true;
	else
		return false;
}

function refreshWidgetCharts(place) {
	var urlParams = getUrlParams();
	if (urlParams['charts']) {
		// need to set the width once we konw the map div width
		$('.mapcharts').css('width',$('#map').width() + "px");

                // set the global place so when an indicator is added we know the place to get the data for
//		if (place)
//	                global_places = [place];

		$('.rankingsTD').hide();
		var ind = map.getIndicator();

		// Only if there's a place selected and an indicator selected show the charts
		if ((place || (global_places && global_places.length > 0)) && ind) {

			var p = ind.getPeriods();
			var periods = [];
			// fix the order of the periods so it's earliest to latest from left to right
			for (var i=0; i<p.length; i++) {
				periods.unshift(p[i]);
			}

			var p = place || global_places[0];

			var trendscube = new PCube([ind], global_places, periods);
			trendscube.loadValues(function(v) {
				this.values = v;
				map.chart1.setData(this);
				map.chart1.refresh();

				// use the period that's currently on the map in the bar chart
				this.periods = [ind.getPeriod()];

				map.chart2.setData(this);
				map.chart2.refresh();

				if ($('.mapcharts').css('visibility') == 'hidden') {
					$('.mapcharts').hide();
					$('.mapcharts').css('visibility','visible');
					$('.mapcharts').slideDown();
				}
			});
		}
	}
}

