﻿/*** GLOBAL VARS ***/
var bWidth = 0;
var bHeight = 0;
var mapWidth = null;
var mapHeight = null;
var toolbarOffset = 0;
var map = null;
var layersLoaded = 0;

var currentDemographicsLayer;

var showCoverageMap = false;
var arrActiveFilters = new Array();
var showAllProvidersMode = false; //when set to true, all providers will display regardless of type

var expandedSearchResults;

var layerCheckboxes = new Array();

//zoom to previous/next vars
var mapCenters = new Array();
var mapZoomLevels = new Array();
var zoomPreviousOrNext = false;
var currentZoomSequence = 1;

var mapZoomScales = []; 

var geoQueryObj = { //used for map geoQuery
	statePlaneX: null,
	statePlaneY: null,
	shape: null,
	coordinates: null
};
var geoQueryByShapeObj = { shape: null}

var mapDrawingTool;

/*** END GLOBAL VARS ***/


/*** APP INITIALIZE ***/

$(document).ready(function(){
	//add jquery element centering function
	jQuery.fn.center = function () { 
		var top = (( $(window).height() - this.height() ) / 2+$(window).scrollTop()) - 100;
		var left = (( $(window).width() - this.width() ) / 2+$(window).scrollLeft()) - 75;
		
		if ( top <= 0 ) top = 20;
		if (left <= 0 ) left = 100;
		
	    this.css("position","absolute");     
		this.css("top", top + "px");     
		this.css("left", left + "px");     
		return this; 
	} 
	/*** ADD DOM EVENT LISTENERS ***/
	//TOOLS
		//add event listeners for selectable tools (tools that can be toggled on/off)
		$('div#Toolbar span.tool_selectable').click(toggleTool);
		$('.tool_unselect').click(unselectAllTools);
	
		$('#btnProviderReportViewAll').click(openProviderReport_ViewAll);
		$('#btnProviderReportSelectWithShape').click(openProviderReport_ViewPolygon);
		$('#btnQueryShape').click(enableGeoQueryByShape);
		$('#btnQueryPoint').click(enableGeoQueryByPoint);
		
		$('#Tool_ZoomPrevious').click(zoomPrevious);
		$('#Tool_ZoomNext').click(zoomNext);
		$('#Tool_ResetMap').click(function(){
			window.location.reload();
		});
		$('#Tool_EmailMap').click(displayEmail);
		$('#Tool_PrintMap').click(function(){
			$('#print').show();
		});
		$('#Tool_Help').click(function(){
			window.open('help.htm');
		});
		
		$('.radius_select').change(function(e){
			$('.radius_select').val(e.currentTarget.value); //when radius changes in one drop-down, we change in other drop-down too
		})
	
	//since these are often created dynamically, using the .live() method ensures they will always be assigned this event handler
	$('.hideinfobox').live('click',function(){map.HideInfoBox();});
	
	/***** END DOM EVENT LISTENERS ***/
	
	
	loadMap();
	startMapMode();

    //this allows for a javascript function updatePanelRefreshCompleteHandler() to be triggered after the .NET update panel has finished refreshing
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(updatePanelRefreshCompleteHandler);
	
});

/**** END APP INITIALIZE ***/


/*** APP ***/

	function buildSessionURL() {
		//builds a url querystring that will load site at current state

        //get base url
        var url = "http://" + window.location.host + window.location.pathname + "?";

        //get lat/lon
        var mapCenter = mapCenters[mapCenters.length - 1];
        var lat = mapCenter.Latitude.toFixed(6);
        var lon = mapCenter.Longitude.toFixed(6);
        url += "&lat=" + lat
        url += "&lon=" + lon

        //get zoom
        var zoom = mapZoomLevels[mapZoomLevels.length - 1]
        url += "&zoom=" + zoom;

        //get provider types
        var ptypes = buildActiveFiltersList('ProviderType', false, true);
        url += "&ptypes=" + ptypes;

        //get agencies
        var agencies = buildActiveFiltersList('Agency', false, true);
        url += "&agencies=" + agencies;

        //get providers
        var providers = buildActiveFiltersList('Provider', false, true);
        url += "&providers=" + providers;

        //add parameter for showAllProvidersMode if activated
        url += (showAllProvidersMode == true ? "&showall=true" : "");
        
        //get keyword
        var keyword = document.getElementById("txtKeyword").value;
        if (keyword.length > 0) url += "&key=" + keyword;

        //get layers
        url += "&layers=" + mapLayers.getActiveLayersList();

        //get basemap
        var mapStyle = map.GetMapStyle();
        var basemap;
        switch (mapStyle) {
            case VEMapStyle.Road:
                basemap = "road";
                break;
            case VEMapStyle.Aerial:
                basemap = "aerial";
                break;
            case VEMapStyle.Hybrid:
                basemap = "hybrid";
                break;
        }
        url += "&map=" + basemap;
		
		//get theme
		var theme = $('#apptheme').val();
		if (theme !== '') url += "&theme=" + theme;
	
        return url;
	}
	
	    function loadSessionURL() {
	        //loads map to same state as specified in url querystring
	
	        //since parsing querystring values in javascript is a pain, we're using ASP.NET to
	        // load the values into hidden fields that are accessed here
	        var latitude = parseFloat(document.getElementById("latitude").value);
	        var longitude = parseFloat(document.getElementById("longitude").value);
	        var zoomlevel = parseFloat(document.getElementById("zoomlevel").value);
	        var providertypes = document.getElementById("providertypes").value;
	        var agencies = document.getElementById("agencies").value;
	        var providers = document.getElementById("providers").value;
	        var showall = document.getElementById("showall").value;
	        var keyword = document.getElementById("keyword").value;
	        var layers = document.getElementById("layers").value;
	        var mapstyle = document.getElementById("mapstyle").value;
	
	        //set map center and zoom
	        var mapcenter = new VELatLong(latitude, longitude);
	        map.SetCenterAndZoom(mapcenter, zoomlevel);
	
	        addQuerystringToActiveFilters(providertypes, 'ProviderType'); //set provider types
	        addQuerystringToActiveFilters(agencies, 'Agency'); //set agencies
	        addQuerystringToActiveFilters(providers, 'Provider'); //set providers
	
	        if ((providers.length > 0 && providers != '0') || (agencies.length > 0 && agencies != '0') || (providers.length > 0 && providers != '0')) {
	            if (document.getElementById("ActiveFilters").style.display == 'none') toggleActiveFilters();
	        }
	
	        if (showall == "true") toggleShowAllProvidersMode(); //actiivate Show All Providers mode
	        
	        //set keyword
	        document.getElementById("txtKeyword").value = keyword;
	
	        updateProvidersGeorss();
	        
	        //set layers
	        mapLayers.setActiveLayers(layers);
	
	        //set basemap
	        if (mapstyle == "road" || mapstyle == "aerial" || mapstyle == "hybrid") {
	            switch (mapstyle) {
	                case "road":
	                    map.SetMapStyle(VEMapStyle.Road);
	                    break;
	                case "aerial":
	                    map.SetMapStyle(VEMapStyle.Aerial);
	                    break;
	                case "hybrid":
	                    map.SetMapStyle(VEMapStyle.Hybrid);
	                    break;
	            }
	        }
	        
	    }
	


	/*** APP.INITIALIZE ***/

	
	/*** END APP.INITIALIZE ***/

/*** END APP ***/


/*** MAP ***/

	function loadMap() {
		// create point to use as map center point
	    var centerat = new VELatLong(32.8, -96.95);
	    // new map instance
	    map = new VEMap('myMap');
	    var mapOptions = new VEMapOptions();
	    mapOptions.EnableBirdseye = false;
	    map.ShowMessageBox = false; //supress empty georss results error
	    map.EnableShapeDisplayThreshold(false); //by default VE will generalize polygons unless set to false
	
	    //register map key...  these are obtained from http://www.bingmapsportal.com/application/Index/1028099
	    map.SetCredentials("Ao0bwN6trZ35byHgGoGHJWe0pA0-LdE9SescpstzlXBkBNXdU07--JF5PD21cqyD");
	    
	    // load map
	    map.LoadMap(centerat, 9, VEMapStyle.Road, false, VEMapMode.Mode2D, false, 0, mapOptions);
		
		//retrieve map layers config for theme (querystring param)
		var mapLayerConfigPath = 'config/default_maplayers.xml';
		var theme = $('#apptheme').val();
		switch(theme) {
		case 'population':
			mapLayerConfigPath = 'config/population_maplayers.xml';
			break;
		case 'income':
			mapLayerConfigPath = 'config/income_maplayers.xml';
			break;
		}
	
		  $.ajax({
		    type: "GET",
		    url: mapLayerConfigPath,
		    dataType: "xml",
		    success: mapLayersConfigCallback
		  });

	}

	function setMapCursor(style){
		//set the map cursor to the desired style
		if (style === undefined || style === 'hand') style = '' //default map cursor is hand
		$('#myMap').get(0).childNodes[0].style.cursor = style;
	}
	
	function clearShapeLayer(layerTitle){
		//delete all shapes from input shape layer
		var shapelayer;
		for (i = 0; i < map.GetShapeLayerCount(); i++) {
		    shapelayer = map.GetShapeLayerByIndex(i);
	        if (shapelayer.GetTitle() === layerTitle) shapelayer.DeleteAllShapes();
		}
	}
	
	function getShapeLayerByTitle(layerTitle, clearShapes){
		//return shape layer matching input title.
		//if it doesn't exist, create the shapelayer and add it to the map.
		//optional clearShapes parameter will delete all shapes from layer if true.
		var shapelayer;
		for (i = 0; i < map.GetShapeLayerCount(); i++) {
		    shapelayer = map.GetShapeLayerByIndex(i);
	        if (shapelayer.GetTitle() === layerTitle){
				if (clearShapes !== undefined){
					if (clearShapes === true) shapelayer.DeleteAllShapes();
				}
				return shapelayer;
			} 
		}
		//shape layer doesn't already exist, so add one
		shapelayer = new VEShapeLayer();
		shapelayer.SetTitle(layerTitle);
		map.AddShapeLayer(shapelayer);
		
		return shapelayer;
	}
	
	function buildCoordinateString(latLonArray){
		//converts array of objects with Latitude and Longitude properties to string in format "X1 Y1, X2 Y2, X3 Y3, etc"
		var coordinates = '';
		for (var j = 0; j < (latLonArray.length); j++) {
			coordinates = coordinates + latLonArray[j].Longitude.toFixed(6) + " " + latLonArray[j].Latitude.toFixed(6) + ", ";
		}
		coordinates = coordinates.substr(0, coordinates.length - 2); //remove trailing chars
		return coordinates;
	}

	

	



	/*** MAP.EVENTS ***/
		
		function changeViewEvents() {
		    //triggered every time the map view changes
		    
		    logCenterAndZoom();
		    updateProvidersGeorss();
			//if zoom has changed from previous update the active layer details
			if (mapZoomLevels[mapZoomLevels.length - 1] !== mapZoomLevels[mapZoomLevels.length - 2]){
				mapLayers.updateActiveLayerDetails();
			}
		}


	/*** END MAP.EVENTS ***/

	/*** MAP.LAYERS ***/
	
	function mapLayersConfigCallback(xml){
		//var $groupheaderhtml, $layerhtml;
		var i = 0; //used to increment map layer id
		var $output = $('<div></div>');
		var $layerItem;
		$(xml).find('group').each(function() //loop through each group node
		{	
			$('<h2></h2>').append($(this).attr('name')) //insert name into new header element
						  .appendTo($output); 
			
			$(this).find('layer').each(function(){ //loop through each layer node
				
			
				//insert layer info into new map layer object
				var mapLayer = new MapLayer();
				mapLayer.id = i; //assign numerical id
				mapLayer.name = $(this).find('name').text();
				mapLayer.serviceType = 	$(this).find('service_type').text();
				mapLayer.serviceUrl = $(this).find('service_url').text();
				mapLayer.moreInfoUrl = $(this).find('more_info_url').text();
				mapLayer.showLegend = ($(this).find('show_legend').text() == 'true'); //convert string to boolean
				mapLayer.canDisplayWithOthers = ($(this).find('can_display_with_others').text() == 'true'); //convert string to boolean
				mapLayer.displayOnLoad = ($(this).find('display_on_load').text() == 'true'); //convert string to boolean
				mapLayer.transparency = parseFloat($(this).find('transparency').text());
				mapLayer.checkbox = $('<input>').attr('type','checkbox') //create a checkbox
					.attr('id', 'chkMapLayer' + mapLayer.id) //give checkbox an id (example: 'chkMapLayer2')
					.click(mapLayer.clickHandler); //add the 'on click' handler for checkbox
				
				$layerItem = $('<p></p>').addClass('maplayer');
				//wrap the checkbox in a label tag with layer name and append to <p>
				$('<label></label>').append(mapLayer.checkbox)
					.append(mapLayer.name)
					.appendTo($layerItem);	
	
				$layerItem.append(' ');
				//add more info link
				if (mapLayer.moreInfoUrl){
					$('<a></a>').attr('href', mapLayer.moreInfoUrl)
						.attr('target', '_blank')
						.append("<img src='images/more_info.png'>")
						.appendTo($layerItem);
				}
	
				$output.append($layerItem); 
				if (mapLayer.showLegend){
					//create a div container for items that will only be shown when layer is on
					mapLayer.layerDetails = $('<div></div>').attr('id','mapLayerInfo' + i)
						.addClass('maplayerinfo')
						.hide();
						
					mapLayer.layerDetails.appendTo($output);
				}

				mapLayers.addLayer(mapLayer);
				mapLayer.load();
	
				i++;
			});
		    
		});
		
		$('#sidebarLayers').append($output);
		//console.log($output.html());
		mapLayers.updateVisibility();
		
		//load map state from email url if there is a querystring (we have to wait for layers to have loaded to do this)
		if (document.getElementById("latitude").value.length > 0) loadSessionURL();
	}
	
	var mapLayers = function(){
		var layers = []; //array of MapLayer objects
		var pendingServiceInfoRequest = false; //used for queuing map layer service info ajax request... see mapLayer.getServiceInfo()
		
		var getMapLayerByID = function(id){
			for (var i=0; i<layers.length; i++) {
					if (layers[i].id == id) return layers[i];
			};
			return null;
		};
		
		var addMapLayer = function(mapLayer){
			layers.push(mapLayer)
		};
		
		var updateVisibility = updateLayerVisibility;
		
		var turnOffOtherLayers = function(mapLayerID){
			//unchecks all layers where 'canDisplayWithOthers' is false and id is not input
			if (getMapLayerByID(mapLayerID).canDisplayWithOthers === false) {
				for (var i=0; i<layers.length; i++) {
					if (layers[i].id !== mapLayerID && layers[i].canDisplayWithOthers === false) {
						mapLayers.layers[i].checkbox.attr('checked', false);
					}
				};
			}
	
		};
		
		var getActiveLayersList = function(){
			//returns a comma separated list of the layer indexes that are currently checked
			var $chk; 
			var activeLayers = [];
	       	for (var i = 0; i < mapLayers.layers.length; i++) {
	            $chk = mapLayers.layers[i].checkbox;
	            if ($chk.attr('checked')) activeLayers.push(i.toString());
	        }
			return activeLayers.join(',');
		}
		
		var setActiveLayers = function(layers){
			//activate all layers included in input list.   input format should be "1,3,4" etc
			
	        if (layers.length > 0) {
	            $('#sidebarLayers input:checkbox').attr('checked',false); //uncheck all
	            var layerArray = layers.split(",");
				for (x in layerArray) {  //loop through each layer in querystring
			       	for (var i = 0; i < mapLayers.layers.length; i++) {
			            if (layerArray[x] === i.toString()) {
							mapLayers.layers[i].activate();
							break;
						}
			        }
	            }
				
				this.updateVisibility();
	        }
		}
		
		var updateActiveLayerDetails = function(){
			//get the current map scale and use it to update the layer details for any active layers
			var currentZoomLevel = map.GetZoomLevel();
			
			for (var i=0; i<mapZoomScales.length; i++) {
				if (mapZoomScales[i].level === currentZoomLevel){
					var currentMapScale = mapZoomScales[i].scale;
					break;
				}
			};
			
			var mapLayer;
			for (var x=0; x<mapLayers.layers.length; x++) {
				mapLayer = mapLayers.layers[x];
				if (mapLayer.turnedOn){
					mapLayer.updateLayerDetails(currentMapScale);
				}
			};
		}
		
		return {
			layers: layers,
			pendingServiceInfoRequest: pendingServiceInfoRequest,
			getLayerByID: getMapLayerByID,
			addLayer: addMapLayer,
			updateVisibility: updateVisibility,
			turnOffOtherLayers: turnOffOtherLayers,
			getActiveLayersList: getActiveLayersList,
			setActiveLayers: setActiveLayers,
			updateActiveLayerDetails: updateActiveLayerDetails
		}
		
	}();
	
	//MapLayer object constructor
	var MapLayer = function(){
		this.id = null;	
		this.name = null;
		this.serviceType = null;
		this.serviceUrl = null;
		this.moreInfoUrl = null;
		this.showLegend = null;
		this.canDisplayWithOthers = null;
		this.displayOnLoad = null;
		this.transparency = null;
		this.checkbox = null; //UI jquery checkbox
		this.layerDetails = null; //UI jquery div
		this.serviceInfo = null;
		this.legendInfo = null;
		this.subLayers = [];
		this.turnedOn = false;
		
		this.load = function(){
			if (this.serviceType == 'ArcGIS'){
				loadArcGISLayer(this.id, this.serviceUrl)	
			}
			
			//turn on layer if displayOnLoad is true
			if (this.displayOnLoad) this.activate();
		}
		
		//click handler attached to mapLayer.checkbox
		this.clickHandler = function(e){
			var mapLayerID = parseInt(e.currentTarget.id.replace('chkMapLayer',''));
			mapLayers.turnOffOtherLayers(mapLayerID); 
			mapLayers.updateVisibility();
			var mapLayer = mapLayers.getLayerByID(mapLayerID);
			if (e.currentTarget.checked) mapLayer.activate();
			else {
				this.turnedOn = false;
				if (!mapLayer.canDisplayWithOthers) $('.maplayerinfo').hide();
			} 
		}
		
		this.activate = function(){
			if (!this.canDisplayWithOthers) $('.maplayerinfo').hide();
			$('#mapLayerInfo' + this.id).show();
			this.checkbox.attr('checked', true);
			this.turnedOn = true;
	
			if (this.serviceInfo === null) {
				this.getServiceInfo(); //request service info if we haven't already
			} 
			else mapLayers.updateActiveLayerDetails();
		}
		
		this.serviceInfoRequested = false; //used for associating serviceInfo json request with correct map layer in callback
		
		this.getServiceInfo = function(){
			//get service info if it hasn't already been obtained and there isn't already a pending request 
			
			if (this.serviceInfo === null){
				if (mapLayers.pendingServiceInfoRequest === false){
					var callback = 'loadArcGISServiceInfo';
					var url = this.serviceUrl + '/?f=json&callback=' + callback;
					this.serviceInfoRequested = true;
					mapLayers.pendingServiceInfoRequest = true;
					if (this.showLegend ) {
						//add message to notify user that legend is loading
						this.layerDetails.append($('<div>Loading legend...</div>)').addClass('legend_loading'));
					} 
					getJSON(url);
					
				}
				//if there was already a pending request, try again
				else setTimeout('mapLayers.layers[' + this.id + '].getServiceInfo();', 500);
			
			}
	
		}
		
		this.legendInfoRequested = false; //used for associating legendInfo json request with correct map layer in callback
		this.getLegendInfo = function(){
			//get legend info if it hasn't already been obtained and there isn't already a pending request 
			
			if (this.legendInfo === null){
					var callback = 'loadArcGISLegendInfo';
					var url = this.serviceUrl + '/legend?f=json&callback=' + callback;
					this.legendInfoRequested = true;
					getJSON(url);
			}
		}
		
		this.addSubLayer = function(id, name, maxScale, minScale){
			var parentLayer = this;
			var subLayer = new this.SubLayer(id,name,maxScale,minScale,parentLayer);
			
			this.subLayers.push(subLayer);
			
			this.layerDetails.append(subLayer.details);
			
		}
		
		//constructor for SubLayer object
		this.SubLayer = function(id, name, maxScale, minScale, parentLayer){
			this.id = (id !== undefined) ? id : null;
			this.name = (name !== undefined) ? name : null;
			this.maxScale = (maxScale !== undefined) ? maxScale : null;
			this.minScale = (minScale !== undefined) ? minScale : null;
			this.parentLayer = (parentLayer !== undefined) ? parentLayer : null;
			this.legendInfo = null;
			
			this.details = $('<div></div').append(this.name)
				.addClass('maplayerlegend');
		
			this.addLegendInfo = function(obj){
				if (obj !== undefined){
					var $legend = $('<table></table>');
					var imgBaseUrl = this.parentLayer.serviceUrl + '/' + this.id.toString() + '/images/';
					this.legendInfo = obj;
					var legendItem;
					for (var i=0; i<this.legendInfo.length; i++) {
						legendItem = this.legendInfo[i];
						var $tr = $("<tr></tr>").attr('valign', 'middle');
						$tr.append("<td><img src=" + imgBaseUrl + legendItem.url + " width='18px' height='13px'/></td> " );
						$tr.append("<td>" + legendItem.label + '</td>');		
						$legend.append($tr);
					};
					
					this.details.append($legend);		
				}
			}
			
		}
		
		this.updateLayerDetails = function(currentScale){
			var noneDisplayed = true;
			//hide or show sublayer details that are not displayed at input scale
			if (this.subLayers.length > 0){
				var subLayer; 
				for (var i=0; i<this.subLayers.length; i++) {
					subLayer = this.subLayers[i];
					if ((subLayer.maxScale <= currentScale || subLayer.maxScale === 0) && (subLayer.minScale >= currentScale || subLayer.minScale === 0)) 
					{
							subLayer.details.show();
							noneDisplayed = false;
					}
					else subLayer.details.hide();
	
				};
			}
			var $currentlyDisplayedDiv = $('#mapLayerInfo' + this.id.toString() + ' .displayed_layers')
			if (noneDisplayed) $currentlyDisplayedDiv.hide();
			else $currentlyDisplayedDiv.show();
		}
	}
	
	//dynamic script tag trick for avoiding cross-domain ajax restrictions (only works for json format)
	//modified example from http://www.simple-talk.com/dotnet/asp.net/calling-cross-domain-web-services-in-ajax/
	function getJSON(url){
		//json request url must include the proper parameters for the source server
		//and server must accept callback parameter. ex: http://server.com/?f=json&callback=myCallbackFunction
	    var head = document.getElementsByTagName("head").item(0);
	    var script = document.createElement("script");
	    script.setAttribute("type", "text/javascript");
	    script.setAttribute("src", url);
	    head.appendChild(script);
	}
	
	
	function loadArcGISServiceInfo(jsonresult){
		//callback function for arcgis service json response
		
		/* the response does not have a service url that we can use to associate the info with the correct layer.
		 * therefore, we only send the request when the layer is clicked on by the user and we set the serviceInfoRequested
		 * to true. Then we can see which mapLayer has is currently pending a request below to assign it the info.
		 */
		
		mapLayers.pendingServiceInfoRequest = false;
		var mapLayer;
		for (var i=0; i<mapLayers.layers.length; i++) {
			
			mapLayer = mapLayers.layers[i];
			if (mapLayer.serviceInfo === null){
				if (mapLayer.serviceInfoRequested === true){
					mapLayer.serviceInfo = jsonresult;
					
					//load layer info (if v10 or greater)
					if (jsonresult.currentVersion > 10){
						var layer;
						for (var x=0; x<jsonresult.layers.length; x++) {
							layer = jsonresult.layers[x];
							if (layer.subLayerIds === null){ //do not add group layers
								mapLayer.addSubLayer(layer.id, layer.name, layer.maxScale, layer.minScale);
							}
						}	
					
						//request legend info
						if (mapLayer.showLegend) mapLayer.getLegendInfo();
						else mapLayers.pendingServiceInfoRequest = false;
					
					}
					
					
					
					break;
				}
			}
		};
		
		mapLayers.updateActiveLayerDetails();
		
		//populate global array with map zoom levels and scales if it hasn't been done yet.
		if (mapZoomScales.length === 0){
			var lods = jsonresult.tileInfo.lods;
			for (var i=0; i<lods.length; i++) {
				mapZoomScales.push({level: lods[i].level, resolution: lods[i].resolution, scale: lods[i].scale});
			}
		}
		
	}
	
	function loadArcGISLegendInfo(jsonresult){
		mapLayers.pendingServiceInfoRequest = false;
		var mapLayer;
		//loop through all mapLayers to find the one whose legend info has been requested so we can associate this
		//response with the correct mapLayer
		for (var i=0; i<mapLayers.layers.length; i++) {
			mapLayer = mapLayers.layers[i];
			if (mapLayer.serviceInfo !== null && mapLayer.legendInfo === null){
				if (mapLayer.legendInfoRequested === true) {
					mapLayer.legendInfo = jsonresult;
					
					//loop through all layers in legend info result and assign info to matching sublayer
					if (jsonresult.layers){
						var layer;
						for (var x = 0; x < jsonresult.layers.length; x++) {
							layer = jsonresult.layers[x];
							var subLayer;
							for (var y=0; y<mapLayer.subLayers.length; y++) {
								subLayer = mapLayer.subLayers[y];
								if (layer.layerId === subLayer.id){
									subLayer.addLegendInfo(layer.legend);
									break;
								} 
							}
						}
					}
					
					break;
				}	
			}
		$('.legend_loading').hide(); //hide legend loading msg
		};
	}
	
		function updateProvidersGeorss() {
		
			var providersGeorss = getShapeLayerByTitle('providersGeorss',true);
			var coverageMapShapeLayer = getShapeLayerByTitle('coverageMapShapeLayer',true);
			
			//generate the querystring parameters for the provider feed
				var view = map.GetMapView();
			    var top = view.TopLeftLatLong.Latitude;
			    var left = view.TopLeftLatLong.Longitude;
			    var bottom = view.BottomRightLatLong.Latitude;
			    var right = view.BottomRightLatLong.Longitude;
			
			    document.getElementById('mapExtentTop').value = top;
			    document.getElementById('mapExtentLeft').value = left;
			    document.getElementById('mapExtentBottom').value = bottom;
			    document.getElementById('mapExtentRight').value = right;
			
			    var querystring = "LonLeft=" + left + "&LatTop=" + top + "&Lonright=" + right + "&Latbottom=" + bottom;
			
			    //if global variable displayProviderMode = 'All',
			    //all providers will be displayed regardless of provider type
			    if (showAllProvidersMode == true)
			    { querystring += "&ptypes=ShowAllProviders" }
			    else { 
			        var activeProviderTypes = buildActiveFiltersList('ProviderType',true,false);
			        querystring += "&ptypes=" + activeProviderTypes;
			        var activeAgencies = buildActiveFiltersList('Agency',true,false);
			        querystring += "&agencies=" + activeAgencies;
			        var activeProviders = buildActiveFiltersList('Provider', true, false);
			        querystring += "&providers=" + activeProviders;
			    }
				
			//make provider georss feed request if there is any active criteria
		    if (showAllProvidersMode == true || activeProviderTypes != '' || activeAgencies != '' || activeProviders != '') {
		        var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, 'getproviders.ashx?' + querystring, providersGeorss);
		        map.ImportShapeLayerData(veLayerSpec, onProvidersFeedLoad, false);
				
				//make service area georss feed request if coverage map tool is selected
				if (!$('#Tool_CoverageMap').hasClass('tool_unselected')) {
					veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, 'getareaserved.ashx?' + querystring, coverageMapShapeLayer);
			        map.ImportShapeLayerData(veLayerSpec, onCoverageMapFeedLoad, false);
					$('#Tool_CoverageMap_Message').hide();
					$('#Tool_CoverageMap_Loading').show();
				}
		    }
		
		    //add active provider type and agency IDs to hidden asp.net controls in order to get
		    //# of occurrences for each provider type and agency in the active providers list
		
		    activeProviderTypes = buildActiveFiltersList('ProviderType', false, false);
		    document.getElementById('hiddenFieldActiveProviderTypeFilters').value = activeProviderTypes;
		    activeAgencies = buildActiveFiltersList('Agency', false, false);
		    document.getElementById('hiddenFieldActiveAgencyFilters').value = activeAgencies;
		    activeProviders = buildActiveFiltersList('Provider', false, false);
		    document.getElementById('hiddenFieldActiveProviderFilters').value = activeProviders;
		    
		    refreshUpdatePanel();
		
		}
		
	
		function refreshUpdatePanel() {
		    //this forces the provider types update panel to refresh every time the map view changes to recalc the number of occurrences for each provider type
		    //only do it if there is a value in the txtKeyword input or items in arrActiveFilters
		    if (document.getElementById('txtKeyword').value != '' || arrActiveFilters.length > 0) __doPostBack('UpdatePanelProviderTypes', '');
		}

		function updatePanelRefreshCompleteHandler() {
		    //this function is triggered every time the .NET updatepanel completes its refresh.
		    //the command that causes this is in the OnPageLoad function:
		    //Sys.WebForms.PageRequestManager.getInstance().add_endRequest(updatePanelRefreshCompleteHandler);
		
		    var providerTypeResults = document.getElementById("ProviderTypeSearchResults").getElementsByTagName("div");
		    updateActiveFilterCounts(providerTypeResults, "ProviderType");
		
		    var agencyResults = document.getElementById("AgencySearchResults").getElementsByTagName("div");
		    updateActiveFilterCounts(agencyResults, "Agency");
		
		    var providerResults = document.getElementById("ProviderSearchResults").getElementsByTagName("div");
		    updateActiveFilterCounts(providerResults, "Provider");
		    
		    buildActiveFiltersHtml();
		    processSearchResults();
		
		}
		
		function onProvidersFeedLoad(feed){

		    var providersGeorss = feed;
			numShapes = providersGeorss.GetShapeCount();
			
			for(var i=0; i < numShapes; ++i) {
			    var currentShape = providersGeorss.GetShapeByIndex(i);
			    count = currentShape.GetMoreInfoURL();
			    if (count == 1) currentShape.SetCustomIcon(currentShape.IconId);
			    else {
			        //putting text over the icon will make it difficult for user to move mouse into the info-window of clustered point.
			        //this is a hack to get around it.
			        if (navigator.appName == 'Microsoft Internet Explorer') {
			            currentShape.SetCustomIcon("<div class='providerClusterPin'>" + count + "</div>");
			        }
			        else {
			            currentShape.SetCustomIcon("<div class='providerClusterPin'>" + count + "<div style='position: absolute;left:-1px;height:23px;width:24px;z-index:10;display: inline'></div></div>");
			        }
			    }
		    
		    }
			
			$('.hideinfobox').click(function(){ map.HideInfoBox();})
		}
		
		function showServiceArea(providerid) {
			var areaservedGeorss = getShapeLayerByTitle('areaservedGeorss',true);
            var url = "getareaserved.ashx?providers=" + providerid;
            var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, url, areaservedGeorss);
            map.ImportShapeLayerData(veLayerSpec, onServiceAreaFeedLoad, true);
		 }
		 
		 function onServiceAreaFeedLoad(feed) {
			 var s = feed.GetShapeByIndex(0);
		     s.SetCustomIcon('images/service_area.png');
			 var html = s.GetDescription();
			 html += "<div onclick='completeGeoQueryByShape();' class='fakeLink padded'>View demographic summary</div>";
			 html += "<div onclick='getShapeLayerByTitle(\"areaservedGeorss\",true);map.HideInfoBox();' class='fakeLink padded'>Hide</div>";
			 s.SetDescription(html);
			 map.ShowInfoBox(s);
			 
			 geoQueryObj.shape = s;
			 
		 }
		
		 function onCoverageMapFeedLoad(feed) {
		 	if (!$('#Tool_CoverageMap').hasClass('tool_unselected')) {
				var s;
				var color = new VEColor(255, 165, 0, .08);
		        var lineColor = new VEColor(0, 0, 0, 0);
				for (var i=0; i<feed.GetShapeCount(); i++) {
			         s = feed.GetShapeByIndex(i);
		         	 s.HideIcon();
					 s.SetFillColor(color);
		         	 s.SetLineColor(lineColor);
				}
				$('#Tool_CoverageMap_Loading').hide();
				$('#Tool_CoverageMap_Message').show();
		     }
		     else getShapeLayerByTitle('coverageMapShapeLayer',true); //clear layer
		 }
   
	    //ArcGIS layers			    
	        function loadArcGISLayer(id, url) {

	            //load arcGIS services
	            var agisve_services = new ESRI.ArcGIS.VE.ArcGISLayerFactory();
	            agisve_services.CreateLayer(url, id.toString(), onArcGISLayerLoad);
	            
	
	        }
	
	
	        function onArcGISLayerLoad(tileSourceSpec, resourceInfo) {
	            var layerID = parseInt(tileSourceSpec.ID);
				var mapLayer = mapLayers.getLayerByID(layerID);
				//if the mapLayer has a transparency specified, use it
				if (mapLayer.transparency) tileSourceSpec.Opacity = mapLayer.transparency;
				else tileSourceSpec.Opacity = 0.65;

	            /* set the zindex for layers with lower IDs to display on top of those with higher IDs.
	               don't start above 50 because this is the default zindex for VEShapes */
				tileSourceSpec.ZIndex = 40 - layerID; 
	            // add layer to map using the tile layer specification
	            map.AddTileLayer(tileSourceSpec, mapLayer.displayOnLoad); //false means tile is not immmediately visible
	
	            layersLoaded++; //used in updateLayerVisibility() to test if all layers have loaded 
	        }

	/*** END MAP.LAYERS ***/
	
	/*** MAP.GEOQUERY ***/
	
		/*** QUERY BY POINT ***/
		function enableGeoQueryByPoint(){
			$('#Tool_Query_Options').hide('fast'); //hide tool options
			$('#Tool_Query_Point_Help').show('fast'); //display tool help box
			setMapCursor('help');
			map.AttachEvent("onmousedown", geoQueryByPointHandler);
		}
	
		function geoQueryByPointHandler(mapEvent) {
		//create lat/long object and shape layer where user clicked
		    queryLL = map.PixelToLatLong(new VEPixel(mapEvent.mapX, mapEvent.mapY));
		    queryClickShape = new VEShape(VEShapeType.Pushpin, queryLL);
		    queryClickShape.SetCustomIcon('images/question_mark.png');
			var queryShapeLayer = getShapeLayerByTitle('queryShapeLayer',true);
		    
			//populate the globalgeoQueryObj properties for reuse elsewhere
		    var statePlaneCoords = GeoTools.DecimalDegreesToStatePlane(queryLL.Latitude, queryLL.Longitude);
		    geoQueryObj.statePlaneX = statePlaneCoords.x;
		    geoQueryObj.statePlaneY = statePlaneCoords.y;
		    geoQueryObj.shape = queryClickShape;
		    queryShapeLayer.AddShape(geoQueryObj.shape);
			
		    var currentRadius = Number($('.radius_select').val()); //get selected radius from drop-down box

			completeGeoQueryByPointRequest(currentRadius,geoQueryObj.statePlaneX,geoQueryObj.statePlaneY);
		
		}
		
		function changeGeoQueryByPointRadius(action, distance) {
		    map.HideInfoBox();
		    var queryShapeLayer = getShapeLayerByTitle('queryShapeLayer'); //clear out any previous shapes
			queryShapeLayer.DeleteShape(queryShapeLayer.GetShapeByIndex(1));
			
			$('.radius_select').val(distance); //set the radius drop-down to clicked value
		
			completeGeoQueryByPointRequest(distance,geoQueryObj.statePlaneX,geoQueryObj.statePlaneY);
		}
		
		function completeGeoQueryByPointRequest(radius, x, y){
			
			//draw a circle representing the buffered radius
			var queryShapeLayer = getShapeLayerByTitle('queryShapeLayer');
		    var circle = GeoTools.GeodesicCalc.CreateCircle(queryLL, parseFloat(radius), GeodesicCalc.EarthRadiusInMiles);
			circle.HideIcon();
		    var color = new VEColor(255, 0, 0, .15);
		    var lineColor = new VEColor(0, 0, 0, .5);
		    circle.SetFillColor(color)
		    circle.SetLineColor(lineColor)
		    queryShapeLayer.AddShape(circle);
		    
			//notify user that results are pending		
			var html = '<p>Calculating results...</p>';
			html += "<div class='fakeLink right' onclick='unselectAllTools();'>Cancel</div>";
	   		geoQueryObj.shape.SetDescription(html);
	    	map.ShowInfoBox(geoQueryObj.shape);
			
			//make ajax request via jquery
			var url = 'webservice_census_html.ashx?radius=' + radius + '&&XCoord=' + x + '&YCoord=' + y;
		    $.ajax({
			    type: "GET",
			    url: url,
			    dataType: "html",
				success: geoQueryByPointResultsCallback,
				error: function(xhr,err){
					   alert('There was an error retrieving the query results.'); 
				}
			});
			

		}
		
		function geoQueryByPointResultsCallback(data) {
		
		    //add option to close info window
		    var description = "<div onclick='map.HideInfoBox();' class='hideinfobox'><img border='0' alt='Close Button' src='images/close.png'/></div>"
		
		    description += data;
		
		    //add 'exit query' option to end of info window description
		    description += "<div class='fakeLink right' onclick='unselectAllTools();'>Exit</div>";

		    //remove underlining because users confuse as links
		    description = description.replace("<u>", "");
		    description = description.replace("</u>", "");
			
			//provide a better function name for radius change
			 description = description.replace(/ChangeMap/g, 'changeGeoQueryByPointRadius'); // g modifier replaces all occurrences
		
		   geoQueryObj.shape.SetDescription(description);
		    map.ShowInfoBox(geoQueryObj.shape);
		}
		/*** END QUERY BY POINT ***/
		
		/*** QUERY BY SHAPE ***/
		
		function enableGeoQueryByShape(){
			$('#Tool_Query_Options').hide('fast'); //hide tool options
			$('#Tool_Query_Shape_Help').show('fast'); //display tool help box
			
			mapDrawingTool = new MapDrawingTool();
			mapDrawingTool.setCallback(function(result){
				geoQueryObj.shape = result.polygonShape;
				completeGeoQueryByShape();
				mapDrawingTool.enableDrawing();
			});
			
			mapDrawingTool.enableDrawing();
			
		}
		
		function completeGeoQueryByShape(){
			var queryShapeLayer = getShapeLayerByTitle('queryShapeLayer',true);
			
			var points = geoQueryObj.shape.GetPoints();
			var s = new VEShape(VEShapeType.Polygon, points);
			
			s.SetFillColor(new VEColor(255, 0, 0, .15));
		    s.SetLineColor(new VEColor(0, 0, 0, .5));
			s.SetCustomIcon('images/question_mark.png');
			
			geoQueryObj.shape = s;
			queryShapeLayer.AddShape(geoQueryObj.shape);
			
			getShapeLayerByTitle('areaservedGeorss',true); //clear shapes
			
			var points_stateplane = [];
			var converted_point;
			for (var i=0; i<points.length; i++) {
				converted_point = GeoTools.DecimalDegreesToStatePlane(points[i].Latitude, points[i].Longitude);
			   	points_stateplane.push(converted_point.x.toString() + ' ' + converted_point.y.toString())	
			};
			
			geoQueryObj.coordinates = points_stateplane.join(',');
			//make ajax request via jquery
			var url = 'census_by_polygon.ashx?coords=' + geoQueryObj.coordinates;
		    $.ajax({
			    type: "GET",
			    url: url,
			    dataType: "xml",
				success: geoQueryByShapeResultsCallback,
				error: function(xhr,err){
					   alert('There was an error retrieving the query results.'); 
				}
			});
			
			//notify user that results are pending		
			var html = '<p>Calculating results...</p>'
			html += "<div class='fakeLink right' onclick='unselectAllTools();'>Cancel</div>";
	   		geoQueryObj.shape.SetDescription(html);
	    	map.ShowInfoBox(geoQueryObj.shape);
		}
		
		function geoQueryByShapeResultsCallback(xml) {
			var $output = $('<div></div>');
			var html = "<div onclick='map.HideInfoBox();' class='hideinfobox'><img border='0' alt='Close Button' src='images/close.png'/></div>";
			
			html += "<h2 style='color: #CE6500'>2000 Census Information</h2><br/>"
			html += "<table>";
			html += "<tr><td width='150'>Total Population:</td>";
			html += "<td>" + $(xml).find('Total_Population').text() + "</td></tr>";
			
			html += "<tr><td>Male:</td>";
			html += "<td>" + $(xml).find('Male').text() + "</td></tr>";
			
			html += "<tr><td>Female:</td>";
			html += "<td>" + $(xml).find('Female').text() + "</td></tr>";
			
			html += "<tr><td>Total Housing Units:</td>";
			html += "<td>" + $(xml).find('Total_Housing_Units').text() + "</td></tr>";
			
			html += "<tr><td>&nbsp;</td><td><a href='CensusByPolygon.aspx?coords=" + geoQueryObj.coordinates + "' target='_blank'>More...</a></td></tr>";
			
			html += "</table><br/>";
			
			html += "<div class='fakeLink right' onclick='unselectAllTools();'>Exit</div>";
			$output.html(html);
			
		   geoQueryObj.shape.SetDescription($output.html());
		    map.ShowInfoBox(geoQueryObj.shape);
		}
		/*** END QUERY BY SHAPE ***/

	/*** END MAP.GEOQUERY ***/
	/*** MAP.GEOCODE ***/
	
		function getAddressCoordinates(layer, resultsArray, places, hasMore, veErrorMessage) {
		    var geocodePointLayer = getShapeLayerByTitle('geocodePointLayer',true);
		    
		    geocodePointLayer.Show();
		    
		    if (places != null) {
		        //Places Were found
		        findPlaceResults = places[0].LatLong;
		        var geocodePoint = new VEShape(VEShapeType.Pushpin, findPlaceResults);
		        geocodePoint.SetTitle(places[0].Name);
		        var description
		        description = "<img src='images/close.png' alt='Close Button' border='0'/> <span class='fakeLink' onclick='getShapeLayerByTitle(\"geocodePointLayer\",true);map.HideInfoBox();'>Remove From Map</span>"
		        geocodePoint.SetDescription("<br><br><img src='images/close.png' alt='Close Button' border='0'/> <span class='fakeLink' onclick='getShapeLayerByTitle(\"geocodePointLayer\",true);map.HideInfoBox();'>Remove From Map</span>");
		        geocodePointLayer.AddShape(geocodePoint);
		        map.SetZoomLevel(14);
		    }
		    else {
		        //No places were found
		        alert("No matching address was found.");
		    }
		
		} 
		
		function deleteGeocodePoint() {
		    var shape;
		    for (var i = 0; i < layer.GetShapeCount(); i++) {
		        shape = layer.GetShapeByIndex(i);
		        //do something with the shape to make sure it is the one you want
		        layer.DeleteShape(shape);
		    }
		}

	/*** END MAP.GEOCODE ***/
	
	/*** MAP.ZOOM ***/
	
		function logCenterAndZoom() {
		    //used to capture center and zoom values for use in the zoom to previous/next functionality and toggle buttons
			
			var $zoomPreviousIcon = $('#Tool_ZoomPrevious');
			var $zoomNextIcon = $('#Tool_ZoomNext');
			
		    var maxZooms = 10;  //set how far user can go back with 'zoom to previous'
		
		    //this does not occur if user has changed map view using zoom to previous/next buttons
		    if (zoomPreviousOrNext == false) {
		        //remove first array elements if max number has been reached
		        if (mapCenters.length > maxZooms) {
		            mapCenters.shift();
		            mapZoomLevels.shift();
		        }
		
		        //if user manually changed the map view and wasn't at the end of a zoom sequence,
		        //remove the appropriate number of array elements
		        if (currentZoomSequence > 1) {
		            mapCenters.splice(mapCenters.length - currentZoomSequence+1, currentZoomSequence+1);
		            mapZoomLevels.splice(mapZoomLevels.length - currentZoomSequence+1, currentZoomSequence+1);
					$zoomNextIcon.addClass('mediumtransparency');
		            
		        }
		        
		        mapCenters.push(map.GetCenter()) //add current map center to array
		        mapZoomLevels.push(map.GetZoomLevel()) //add current zoom level to array
		        currentZoomSequence = 1; //reset zoom sequence
		    }
		    else {
		        zoomPreviousOrNext = false;
		    }
		
		    //enable/disable zoom to previous/next buttons
		    if (mapCenters.length > 1 && mapCenters.length != currentZoomSequence) {
		        $zoomPreviousIcon.removeClass('mediumtransparency');
		    }
		    else $zoomPreviousIcon.addClass('mediumtransparency'); //
		    
		
		    if (currentZoomSequence > 1) {
		        $zoomNextIcon.removeClass('mediumtransparency');
		    }
		    else $zoomNextIcon.addClass('mediumtransparency');
		     
		}
		
		function zoomPrevious() {
		    //zoom to previous map extent
		
		    //when this is set to true, the center/zoom won't be logged in the logCenterAndZoom
		    //since the change was due to the use of the tool
		    zoomPreviousOrNext = true;
		
		    var n = mapCenters.length - currentZoomSequence
		
		    if (n >= 1) {
		        currentZoomSequence = currentZoomSequence + 1
		        map.SetCenterAndZoom(mapCenters[n-1], mapZoomLevels[n-1]);
		    }
		
		}
		
		function zoomNext() {
		    //zoom to next map extent
		
		    //when this is set to true, the center/zoom won't be logged in the logCenterAndZoom
		    //since the change was due to the use of the tool
		    zoomPreviousOrNext = true;
		
		    var n = mapCenters.length - currentZoomSequence
		
		    if (n < (mapCenters.length - 1)) {
		        currentZoomSequence = currentZoomSequence - 1
		        map.SetCenterAndZoom(mapCenters[n+1], mapZoomLevels[n+1]);
		    }
		
		}

		function zoomToBoundary() {
		    var place = document.getElementById('txtLocation').value
		    if (place != '') {
		        var boundaryGeorss = getShapeLayerByTitle('boundaryGeorss',true);
		        //parse to detect whether this is a street address or a city/county/zip code
		        var addrNum = place.substr(0, place.indexOf(' '));
		        var addrStreet = place.substr(place.indexOf(' ') + 1, place.length)
		        //see if characters to left of space are numbers and if there is anything to the right of a space
		        if (isNaN(addrNum) == false && place.indexOf(' ') != -1 && addrStreet.length > 0) {
		            //since we have numbers followed by a space and then more values, we assume this is an address
		            //and use  Bing's geocode function
		            map.Find(null, place, null, null, null, null, true, true, null, true, getAddressCoordinates);
		        }
		        //otherwise, we assume it is a city, county, or zipcode and get the georss from our own database
		        else {
		            //trim trailing spaces
		            place = place.replace(/^\s*|\s*$/, "");
		            var url = "getboundaryextent.ashx?place=" + place;
		
		            var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, url, boundaryGeorss);
		            map.ImportShapeLayerData(veLayerSpec, onBoundaryExtentFeedLoad, true); //set last var to true to map auto zoom to georss extent
		        }
		    }
		}
		
     //zoom to boundary (function that requests georss feed is in FIND A LOCATION section)
        function onBoundaryExtentFeedLoad(feed) {
            //s = boundaryGeorss.GetShapeByIndex(0);
            s = feed.GetShapeByIndex(0);
			s.Hide();
        }
		
		function zoomToPoints(coordinates) {
		    //used for 'Zoom to Group' option on clustered points
		    //coordinates should be in comma-delimited string like '32.7886,-96.772,32.7908,-96.7738'
		    var arrCoordinates = new Array
		    var arrVEPoints = new Array
		    var latitude
		    var longitude
		    
		    //place input coordinate string into array
		    arrCoordinates = coordinates.split(",")
		    
		    //loop through each coordinate (increment i by 2 since each lat/long pair is split into its own array index)
		    for (var i = 0; i < arrCoordinates.length; i += 2) {
		        latitude = parseFloat(arrCoordinates[i])
		        longitude = parseFloat(arrCoordinates[i+1])
		        arrVEPoints.push(new VELatLong(latitude, longitude));
		    }
		    
		    //zoom to array of clustered VE points
		    map.SetMapView(arrVEPoints);
		}
		
		function zoomToProviders(filterType, filterID) {
		    //zooms to extent of all providers of the specified type or agency sites of a specified id.
		    //type should be 'providertype' if ID is a ProviderTypeID or 'agency' if ID is an AgencyID
		    var providerExtentGeorss = getShapeLayerByTitle('providerExtentGeorss',true);
		    var url = "getprovidersextent.ashx?" + filterType + "=" + filterID;
		
		    var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, url, providerExtentGeorss);
		    map.ImportShapeLayerData(veLayerSpec, onZoomToProvidersFeedLoad, true); //set last var to true to map auto zoom to georss extent
		    
		    }
		
		function onZoomToProvidersFeedLoad(feed) {
		
		    a = feed.GetShapeByIndex(0);
		    a.Hide();
		    b = feed.GetShapeByIndex(1);
		    b.Hide();
		
		}
	/*** END MAP.ZOOM ***/

/*** END MAP ***/


/*** UI ***/
	/*** UI.SEARCH ***/
		
		function processSearchResults() {
		    //list the total number of results for each category and choose which group to display, if any.
		
		    //****HANDLE PROVIDER TYPE SEARCH RESULTS
		        var providerTypeResults = document.getElementById("ProviderTypeSearchResults").getElementsByTagName("div");
		        var providerTypeResultTotal = providerTypeResults.length
		        for (x in providerTypeResults) {
		            if (providerTypeResults[x].className != undefined) {
		                if (providerTypeResults[x].className.indexOf('active') != -1) providerTypeResultTotal--;
		            }
		        }
		
		        //update search result header with the number of results
		        var e = document.getElementById('ProviderTypeMatchesHeader');
		        e.innerHTML += ' (' + providerTypeResultTotal + ')'
		
		        //show or hide results depending on above result
		        var providerTypeMatchesDiv = document.getElementById('ProviderTypeMatches');
		        if (providerTypeResultTotal == 0) providerTypeMatchesDiv.style.display = 'none';
		        else providerTypeMatchesDiv.style.display = '';
		    
		    //****HANDLE AGENCY SEARCH RESULTS
		        //get all div tag elements that contain the agency search results
		        var agencyResults = document.getElementById("AgencySearchResults").getElementsByTagName("div");
		        var agencyResultTotal = agencyResults.length
		        //loop through each search result
		        for (x in agencyResults) {
		            if (agencyResults[x].className != undefined) {
		                if (agencyResults[x].className.indexOf('active') != -1) agencyResultTotal--;
		            }
		        }
		
		        //update search result header with the number of results
		        e = document.getElementById('AgencyMatchesHeader')
		        e.innerHTML += ' (' + agencyResultTotal + ')'
		
		        //show or hide results depending on above result
		        var agencyMatchesDiv = document.getElementById('AgencyMatches');
		        if (agencyResultTotal == 0) agencyMatchesDiv.style.display = 'none';
		        else agencyMatchesDiv.style.display = '';
		
		   //****HANDLE PROVIDER SEARCH RESULTS
		        //get all div tag elements that contain the agency search results
		        var providerResults = document.getElementById("ProviderSearchResults").getElementsByTagName("div");
		        var providerResultTotal = providerResults.length
		        //loop through each search result
		        for (x in providerResults) {
		            if (providerResults[x].className != undefined) {
		                if (providerResults[x].className.indexOf('active') != -1) providerResultTotal--;
		            }
		        }
		
		        //update search result header with the number of results
		        e = document.getElementById('ProviderMatchesHeader')
		        e.innerHTML += ' (' + providerResultTotal + ')'
		
		        //show or hide results depending on above result
		        var providerMatchesDiv = document.getElementById('ProviderMatches');
		        if (providerResultTotal == 0) providerMatchesDiv.style.display = 'none';
		        else providerMatchesDiv.style.display = '';
		    
		    //by default, all result groups are collapsed, but if only one has results, display it.
		    //note that expandedSearchResults value can override this
		    if ((providerTypeResults.length > 0 && agencyResults.length == 0 && providerResults.length == 0) || expandedSearchResults == 'ProviderType') {
		        var p = document.getElementById("ProviderTypeSearchResults");
		        p.className = p.className.replace("hidden", "visible");
		        expandedSearchResults = "ProviderType";
		    }
		    if ((providerTypeResults.length == 0 && agencyResults.length > 0 && providerResults.length == 0) || expandedSearchResults == 'Agency') {
		        var a = document.getElementById("AgencySearchResults");
		        a.className = a.className.replace("hidden", "visible");
		        expandedSearchResults = "Agency";
		    }
		    if ((providerTypeResults.length == 0 && agencyResults.length == 0 && providerResults.length > 0) || expandedSearchResults == 'Provider') {
		        var a = document.getElementById("ProviderSearchResults");
		        a.className = a.className.replace("hidden", "visible");
		        expandedSearchResults = "Provider";
		    }
		
		    //if nothing is displayed, display the 'no matches found' span
		    var noSearchResultsMessageDiv = document.getElementById('NoSearchResultsFound');
		    if (providerTypeResultTotal == 0 && agencyResultTotal == 0 && providerResultTotal == 0) noSearchResultsMessageDiv.className = "visible";
		    else  noSearchResultsMessageDiv.className = "hidden";
		
		}
		
		function toggleSearchResults(clickedResults) {
		    var providerTypeResultsDiv = document.getElementById('ProviderTypeSearchResults');
		    var agencyResultsDiv = document.getElementById('AgencySearchResults');
		    var providerResultsDiv = document.getElementById('ProviderSearchResults');
		    
		    providerTypeResultsDiv.className = providerTypeResultsDiv.className.replace('visible', 'hidden');
		    agencyResultsDiv.className = agencyResultsDiv.className.replace('visible', 'hidden');
		    providerResultsDiv.className = providerResultsDiv.className.replace('visible', 'hidden');
		    
		    if (clickedResults != expandedSearchResults) {
		        switch (clickedResults) {
		            case "ProviderType":
		                providerTypeResultsDiv.className = providerTypeResultsDiv.className.replace('hidden', 'visible');
		                break;
		            case "Agency":
		                agencyResultsDiv.className = agencyResultsDiv.className.replace('hidden', 'visible');
		                break;
		            case "Provider":
		                providerResultsDiv.className = providerResultsDiv.className.replace('hidden', 'visible');
		                break;
		        }
		        expandedSearchResults = clickedResults;
		    }
		    else expandedSearchResults = "";
		
		}

	/*** END UI.SEARCH ***/

	/*** UI.LAYERS ***/
	
	
	    function toggleAllLayers(selected) {
		        for (x in layerCheckboxes) {
		            layerCheckboxes[x].checked = selected;
		        }
		    }
	
			function updateLayerVisibility() {
		        //only run if all the layers have been loaded 
		        //layersLoaded is incremented each time the layer load callback functions are run
		       if (layersLoaded == mapLayers.layers.length){ 
		            var $chk; 
					for (var i = 0; i < mapLayers.layers.length; i++) {
		                $chk = mapLayers.layers[i].checkbox;
	                    if ($chk.attr('checked')) map.ShowTileLayer(i.toString());
	                    else map.HideTileLayer(i.toString()); 
		            }
		        }
		        //otherwise, try again, because maybe layers have finished loading by now
		        else window.setTimeout('updateLayerVisibility()', 250)
		    }

	/*** END UI.LAYERS ***/
	
	/*** UI.LAYOUT ***/
	
		function adjustPageSize() {
		    browserSize();
		    var mywidth = bWidth;
		    var myheight = bHeight;
		
		    //the layout will stop auto-resizing once the browser window becomes smaller than the values you can set here.
		    //in other words, it won't shrink below these values.  the app should be optimized for viewing at a minimum of 1024x768 res
		    var minwidth = 825;
		    var minheight = 610;
		    
		    if (myheight < minheight) {
		        myheight = minheight;
		    }
		    if (mywidth < minwidth) {
		        mywidth = minwidth
		    }
		
		    //**horizontal adjustments**
		    var m = document.getElementById('myMap');
		        m.style.height = myheight + 'px';
		        m.style.width = mywidth + 'px';
		    var s = document.getElementById('sidebar');
		        s.style.left = mywidth - 182 + 'px';
		    document.getElementById('Toolbar').style.left = mywidth + toolbarOffset - 451 + 'px';
		    document.getElementById('ToolbarBack').style.left = mywidth + toolbarOffset - 451 + 'px';
		    document.getElementById('SidebarMinMax').style.left = mywidth - 28 + 'px';
			document.getElementById('email').style.left = mywidth + toolbarOffset - 412 + 'px';
			document.getElementById('print').style.left = mywidth + toolbarOffset - 325 + 'px';
		    document.getElementById('ContactOnestar').style.left = mywidth - 670 + 'px';
			
			//**vertical adjustments**
		    //for these divs in the right sidebar, you can shift all of them together by changing this sidebarHeightOffset value
		    var sidebarHeightOffset = 20;
		    s.style.height = myheight + sidebarHeightOffset - 65 + 'px'; //sidebar
		    document.getElementById('sidebarBack').style.height = myheight + sidebarHeightOffset - 65 + 'px';
		    document.getElementById('sidebarFront').style.height = myheight + sidebarHeightOffset - 65 + 'px';
		    document.getElementById('sidebarLayers').style.top = myheight + sidebarHeightOffset - 350 + 'px';
		    document.getElementById('sidebarOptions').style.top = myheight + sidebarHeightOffset - 160 + 'px';
		    document.getElementById('sidebarSearchResults').style.maxHeight = myheight + sidebarHeightOffset - 475 + 'px';
		    document.getElementById('sidebarLogo').style.top = myheight + sidebarHeightOffset - 95 + 'px';
		    document.getElementById('ContactOnestar').style.top = myheight - 37 + 'px';
		    document.getElementById('ActiveFiltersBack').style.height = myheight - 185 + 'px';
		    var a = document.getElementById('FiltersList');
		        a.style.height = myheight - 185 + 'px';
		        a.style.maxHeight = myheight - 220 + 'px';
		    
		    mapWidth = mywidth - 5;
		    mapHeight = myheight - 5;
		    map.Resize(mapWidth, mapHeight);
		}
		
		function browserSize() {
		  if( typeof( window.innerWidth ) == 'number' ) {
		    //Non-IE
		    bWidth = window.innerWidth;
		    bHeight = window.innerHeight;
		  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		    //IE 6+ in 'standards compliant mode'
		    bWidth = document.documentElement.clientWidth;
		    bHeight = document.documentElement.clientHeight;
		  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		    //IE 4 compatible
		    bWidth = document.body.clientWidth;
		    bHeight = document.body.clientHeight;
		  }
		}

		function startMapMode() {
		    adjustPageSize();
		    window.onresize = adjustPageSize;
		    
		    document.getElementById('Toolbar').style.display = 'block';
		    document.getElementById('ToolbarBack').style.display = 'block';
		    document.getElementById('sidebar').style.display = 'block';
		    document.getElementById('SidebarMinMax').style.display = 'block';
		    document.getElementById('ActiveFiltersMinMax').style.display = 'block';
		    document.getElementById('ContactOnestar').style.display = 'block';
		    
		    map.AttachEvent("onchangeview", changeViewEvents);

		    map.ShowDashboard();
		}
		
		 function toggleDiv(obj) {
		     //expand or collapse the input div.  input is string containing ID of div
		     var e = document.getElementById(obj);
		     if (e.className != undefined) {
		         if (e.className.indexOf('hidden') != -1) {
		            e.className = e.className.replace('hidden', 'visible');
		            return;
		         }
		         else if (e.className.indexOf('visible') != -1) {
		             e.className = e.className.replace('visible', 'hidden');
		             return;
		         }
		     }
		     if (e.style.display != "none") e.style.display = 'none';
		     else e.style.display = '';
		    
		 }

		function toggleSidebar() {
		    toggleDiv('sidebar');
		    var sidebarDiv = document.getElementById("sidebar");
		    var minMaxDiv = document.getElementById("SidebarMinMax");
		    if (sidebarDiv.style.display == 'none') {
		        minMaxDiv.style.backgroundImage = "url(images/maximize_icon.png)";
		        sidebarDiv.style.display = 'none';
		        //causes the toolbar to shift to the right to fill in the vacant space from hidden sidebar when we call AdjustPageSize below
		        toolbarOffset = 150;
		    }
		    else {
		        minMaxDiv.style.backgroundImage = "url(images/minimize_icon.png)";
		        sidebarDiv.style.display = 'block';
		        toolbarOffset = 0;
		    }
		    adjustPageSize();
		    
		}
		
		function toggleShowAllProvidersMode() {
		    //toggles between 2 modes:  1 where all providers are shown on the map regardless of provider type
		    //and 1 where only provider types that have been selected by the user are displayed
		    if (showAllProvidersMode == false) {
		        showAllProvidersMode = true;
		        document.getElementById('btnShowAllProviders').value = 'Stop Showing All Providers';
		        updateProvidersGeorss();
		        
		        //show active features div if hidden
		        if (document.getElementById('ActiveFilters').style.display == 'none') toggleActiveFilters();
		        
		        //show active provider types div if hidden
		        if (document.getElementById('ProviderTypeFilters').className == 'hidden') toggleDiv('ProviderTypeFilters');
		        document.getElementById('NoActiveFiltersMessage').className = 'hidden';
		        
		        var innerHTML = "You are currently displaying all providers without filtering the results. <br><br>";
		        innerHTML += "<input id='btnShowAllProviders2' type='button' class='x-widebutton' value='Stop Showing All Providers' onclick='toggleShowAllProvidersMode();' />"
		        document.getElementById('ProviderTypeFilters').innerHTML = innerHTML;
		        document.getElementById('AgencyFilters').className = 'hidden';
		        document.getElementById('ProviderFilters').className = 'hidden';
		    }
		    else {
		        showAllProvidersMode = false;
		        document.getElementById('btnShowAllProviders').value = 'Show All Providers on Map';
		        buildActiveFiltersHtml();
		        updateProvidersGeorss();
		        //hide active features div if displayed while no active providers have been selected
		        if (document.getElementById('ActiveFilters').style.display == 'block' && arrActiveFilters.length == 0) {
		            toggleActiveFilters();
		        }
		    }
		}
	/*** END UI.LAYOUT ***/
	
	/*** UI.ACTIVEFILTERS ***/
		
		function buildActiveFiltersList(filterType, onlyIncludeIfChecked, indicateState) {
		    //create a comma-delimited string of active filters for input filterType
		    //if checkedOnly is true, only return string of filters with checked boxes.
		    //if indicateState is true, ID's for unchecked items will be followed by an exclamation point
		    var activeFiltersList = '0';
		
		    if (arrActiveFilters.length > 0) {
		        activeFiltersList = '';
		        for (x in arrActiveFilters) {
		            if (arrActiveFilters[x].FilterType == filterType) {
		                if (onlyIncludeIfChecked == true) {
		                    if (arrActiveFilters[x].Checked == true) activeFiltersList += arrActiveFilters[x].FilterID + ','
		                }
		                //if filter is not checked, add exclamation point after ID if indicateState is true
		                else {
		                    activeFiltersList += arrActiveFilters[x].FilterID;
		                    if (arrActiveFilters[x].Checked == false && indicateState == true) activeFiltersList += '!';
		                    activeFiltersList += ',';
		                }
		            }
		        }
		        //remove trailing comma
		        activeFiltersList = activeFiltersList.substr(0, activeFiltersList.length - 1);
		    }
		    if (activeFiltersList == '') activeFiltersList = '0'
		    return activeFiltersList;
		}
		
		function toggleActiveFilters() {
		    toggleDiv('ActiveFilters');
		    var ActiveFiltersDiv = document.getElementById("ActiveFilters")
		    var minMaxDiv = document.getElementById("ActiveFiltersMinMax")
		    if (ActiveFiltersDiv.style.display == 'none' ) {
		        minMaxDiv.style.backgroundImage = "url(images/minimize_icon.png)"
		        minMaxDiv.style.left = '3px';
		        ActiveFiltersDiv.style.display = 'none';
		        
		    }
		    else {
		        minMaxDiv.style.backgroundImage = "url(images/maximize_icon.png)"
		        minMaxDiv.style.left = '145px';
		        ActiveFiltersDiv.style.display = 'block';
		
		    }
		
		}
		
		function toggleFilterCheckboxes(filterType, button) {
		    var toggle;
		    if (button.value == "Unselect All") {
		        toggle = false;
		        button.value = "Select All";
		    }
		    else {
		        toggle = true;
		        button.value = "Unselect All";
		    }
		    
		    //loop through arrActiveFilters array and check or uncheck corresponding checkbox
		    for (x in arrActiveFilters) {
		        if (arrActiveFilters[x].FilterType == filterType) arrActiveFilters[x].Checked = toggle;
		    }
		
		    var checkboxes = document.getElementById(filterType + "Filters").getElementsByTagName("input");
		    for (c in checkboxes) {
		        if (checkboxes[c].type == "checkbox") checkboxes[c].checked = toggle;
		    }
		
		    updateProvidersGeorss();
		}

		function addToActiveFilters(filterType, filterID, filterName, mapCount, checked) {
		    //creates an active filter object and adds it to the global array
		    var activeFilterObj = {
		        FilterType: filterType,
		        FilterID: filterID,
		        FilterName: filterName,
		        Checked: checked,
		        MapCount: mapCount
		    };
		    arrActiveFilters.push(activeFilterObj)
		}
		
		function addSearchResultToActiveFilters(searchResultDiv, filterType) {
		    //these values are pulled from child span elements of input div
		    var filterID = searchResultDiv.children[0].firstChild.nodeValue;
		    var filterName = searchResultDiv.children[1].firstChild.nodeValue;
		    var mapCount = searchResultDiv.children[2].firstChild.nodeValue.replace('(', '').replace(')', '');
		
		    addToActiveFilters(filterType, filterID, filterName, mapCount, true);
		    updateProvidersGeorss();
		    searchResultDiv.style.display = 'none';  //hide item in the search result list
		    if (document.getElementById('ActiveFilters').style.display == 'none') toggleActiveFilters(); //show active features div if hidden
		    if (showAllProvidersMode == true) toggleShowAllProvidersMode(); //exit ShowAllProviders mode if it is on
		}
		
		function addQuerystringToActiveFilters(querystring, filterType) {
		    if (querystring.length > 0 && querystring != '0') {
		        var filterName = '';  //we don't have the name at this point, but it will be added when update panel refreshes,
		        //if the ID is suffixed with an exclamation point, it is not currently checked in the active filters
		        var filterID, checked;
		        var a = querystring.split(",");
		        for (x in a) {  //loop through each type in querystring   
		            filterID = a[x].replace('!', '');
		            checked = (a[x].indexOf('!') == -1) ? true : false; //if the filterID is suffixed by an exclamation point, it is not checked by default
		            addToActiveFilters(filterType, filterID, filterName, 0, checked);
		        }
		    }
		}
		
		function addToFavorites(providerID) {
		    //if providerID is already in active filters, alert user and exit...
		    for (x in arrActiveFilters) {
		        if (arrActiveFilters[x].FilterType == 'Provider' && arrActiveFilters[x].FilterID == providerID.toString()) {
		            alert('This provider is already in your favorites.');
		            return;
		        }
		    }
		    //...otherwise, add it to the active provider filters
		    addToActiveFilters('Provider', providerID.toString(), '', 1, true);
		    updateProvidersGeorss();
		}
		
		function removeFromActiveFilters(filterID, filterType) {
		    for (x in arrActiveFilters) {
		        if (arrActiveFilters[x].FilterType == filterType && arrActiveFilters[x].FilterID == filterID) arrActiveFilters.splice(x, 1);
		    }
		    
		    //hide the active features div if the last item was removed
		    if (arrActiveFilters.length == 0) {
		        if (document.getElementById('ActiveFilters').style.display == 'block') toggleActiveFilters();        
		    }
		
		    updateProvidersGeorss();
		        
		}
		
		function buildActiveFiltersHtml() {
		    if (showAllProvidersMode == true) return;
		    
		    //display msg if there are no active filters
		    var noActiveFiltersDiv = document.getElementById('NoActiveFiltersMessage');
		    var providerTypeFiltersDiv = document.getElementById('ProviderTypeFilters');
		    var agencyFiltersDiv = document.getElementById('AgencyFilters');
		    var providerFiltersDiv = document.getElementById('ProviderFilters');
		    if (arrActiveFilters.length == 0 && showAllProvidersMode == false) {
		        noActiveFiltersDiv.className = "visible";
		        providerTypeFiltersDiv.className = "hidden";
		        agencyFiltersDiv.className = "hidden";
		        providerFiltersDiv.className = "hidden";
		        return;
		    }
		    else noActiveFiltersDiv.className = "hidden";
		
		    //place filters into separate arrays for each filter type
		    var activeProviderTypes = [], activeAgencies = [], activeProviders = [];
		    for (f in arrActiveFilters) {
		        switch (arrActiveFilters[f].FilterType) {
		            case 'ProviderType':
		                activeProviderTypes.push(arrActiveFilters[f]);
		                break;
		            case 'Agency':
		                activeAgencies.push(arrActiveFilters[f]);
		                break;
		            case 'Provider':
		                activeProviders.push(arrActiveFilters[f]);
		                break;
		        }
		    }
		
		    var e;
		    /**** PROVIDER TYPES ****/
		    if (activeProviderTypes.length > 0) {
		        var html = "<h2>Provider Types</h2>";
		        for (x in activeProviderTypes) html += createFilterHTML(activeProviderTypes[x]); //build checkboxes for each filter
		        if (activeProviderTypes.length > 1) html += createFilterButtonHTML('ProviderType'); //add buttons if more than one
		        providerTypeFiltersDiv.innerHTML = html;
		        providerTypeFiltersDiv.className = 'visible';
		    }
		    else providerTypeFiltersDiv.className = 'hidden';
		
		    /**** AGENCIES ****/
		    if (activeAgencies.length > 0) {
		        html = "<h2>Organizations</h2>";
		        for (y in activeAgencies) html += createFilterHTML(activeAgencies[y]); //build checkboxes for each filter
		        if (activeAgencies.length > 1) html += createFilterButtonHTML('Agency'); //add buttons if more than one
		        agencyFiltersDiv.innerHTML = html;
		        agencyFiltersDiv.className = 'visible';
		    }
		    else agencyFiltersDiv.className = 'hidden';
		
		    /**** PROVIDERS ****/
		    if (activeProviders.length > 0) {
		        html = "<h2>Providers / Favorites</h2>";
		        for (z in activeProviders) html += createFilterHTML(activeProviders[z]); //build checkboxes for each filter
		        if (activeProviders.length > 1) html += createFilterButtonHTML('Provider'); //add buttons if more than one
		        providerFiltersDiv.innerHTML = html;
		        providerFiltersDiv.className = 'visible';
		    }
		    else providerFiltersDiv.className = 'hidden';
		}
		
		function createFilterHTML(filterObj) {
		
		    var mapCount, cssClass, checked;
		    if (filterObj.MapCount == '0') {
		        cssClass = 'disabled';
		        mapCount = '';
		    }
		    else {
		        cssClass = '';
		        mapCount = " (" + filterObj.MapCount + ")";
		    }
		
		    if (filterObj.Checked == true) checked = 'checked';
		    else checked = '';
		
		    //build the filter checkbox html, with onclick event that calls toggleActiveFiltersCheckbox
		    var html = "<div id='" + filterObj.FilterType + "Filter' class='" + cssClass + "'>";
		    html += "<input type='checkbox' onclick='toggleActiveFiltersCheckbox(\"" + filterObj.FilterType + "\", \"" + filterObj.FilterID + "\");' ";
		    html += checked + "  />" + filterObj.FilterName + mapCount;
		    html += " &nbsp;<span onclick='zoomToProviders(\"" + filterObj.FilterType + "\", \"" + filterObj.FilterID + "\");' ";
		    html += "onmouseover='Tip(zoomToGroupTip)' onmouseout='UnTip(zoomToGroupTip)' style='cursor: pointer'>";
		    html += "<img src='images/zoom_small.png' alt='Zoom to All' border='0'/></span>&nbsp;";
		    html += " <span onclick='removeFromActiveFilters(\"" + filterObj.FilterID + "\",\"" + filterObj.FilterType + "\");' ";
		    html += "onmouseover='Tip(removeFromActiveProvidersTip)' onmouseout='UnTip(removeFromActiveProvidersTip)' ";
		    html += "style='cursor: pointer'><img src='images/close.png' alt='Close Button' border='0'/></span></div>";
		
		    return html;
		}
		
		function createFilterButtonHTML(filterType) {
		    //get the current value of the select/unselect all button
		    var selectOrUnselect = 'Unselect All';
		    if (document.getElementById('btnToggle' + filterType + 'Checkboxes')) {
		        selectOrUnselect = document.getElementById('btnToggle' + filterType + 'Checkboxes').value
		    }
		
		    var html = "<div style='line-height:6px'><br></div>"
		    html += "<input id='btnToggle" + filterType + "Checkboxes' type='button' value='" + selectOrUnselect + "' onclick='toggleFilterCheckboxes(\"" + filterType + "\",this)'/>"
		    html += "<input id='btnHideAll" + filterType + "Checkboxes' type='button' value='Hide All' class='narrowbutton' onclick='removeAllFilters(\"" + filterType + "\");'/><br>"
		
		    return html;
		
		}
		
		function toggleActiveFiltersCheckbox(filterType, filterID) {
		    //this function updates the arrActiveFilters array to note when a checkbox is no longer checked.
		    //that way, when the active providers checkbox list HTML gets rebuilt as new items are added,
		    //it won't check a box that was previously unchecked.
		
		    var nothingChecked = true; //if set to false in loop through arrActiveFilters array below, button will change to 'Select All'
		    var everythingChecked = true; //if set to false in loop through arrActiveFilters array below, button will change to 'Unselect All'
		    
		    for (x in arrActiveFilters) {
		        //if the provider type ID of the input checkbox matches a provider type in the arrActiveFilters array,
		        //change the corresponding value to 'checked' if checked or '' if not
		        if (arrActiveFilters[x].FilterID == filterID && arrActiveFilters[x].FilterType == filterType) {
		                arrActiveFilters[x].Checked = !arrActiveFilters[x].Checked;
		            }
		        
		        if (arrActiveFilters[x].Checked == true) nothingChecked = false;
		        else everythingChecked = false;
		    }
		    
		    //toggles the select/unselect all button appropriately if all checkboxes have been checked or unchecked
		   var e = document.getElementById("btnToggle" + filterType + "Checkboxes");
		   if (e != undefined){
		       if (nothingChecked == true) e.value = "Select All";
		       if (everythingChecked == true) e.value = "Unselect All";
		    }
		    
		    updateProvidersGeorss();
		}
		
		
		function removeAllFilters(filterType) {
		    for (var x = arrActiveFilters.length - 1; x >= 0; x--) {
		        if (arrActiveFilters[x].FilterType == filterType) {
		            arrActiveFilters.splice(x, 1);
		        }
		    }
		    document.getElementById('hiddenFieldActive' + filterType + 'Filters').value = '0';
		    buildActiveFiltersHtml();
		    updateProvidersGeorss();
		    if (arrActiveFilters.length == 0) toggleActiveFilters();
		}
		
		
		function updateActiveFilterCounts(searchResultElements, resultType) {
		    var filterID, filterName, filterMapCount;
		
		    //loop through all repeater results
		    for (x in searchResultElements) {
		        if (searchResultElements[x] != undefined) {
		            //if this is an active type, update the arrActiveFilters array with the new map count for this type
		            if (searchResultElements[x].className != undefined) {
		
		                if (searchResultElements[x].className.indexOf('active') != -1) {
		                    filterID = searchResultElements[x].children[0].firstChild.nodeValue;
		                    filterName = searchResultElements[x].children[1].firstChild.nodeValue;
		                    filterMapCount = searchResultElements[x].children[2].firstChild.nodeValue.replace("(","").replace(")","");
		
		                    //loop through arrActiveFilters array and update the map count of the matching providerTypeID
		                    for (y in arrActiveFilters) {
		                        if (arrActiveFilters[y].FilterID == filterID && arrActiveFilters[y].FilterType == resultType) {
		                            arrActiveFilters[y].FilterName = filterName;
		                            arrActiveFilters[y].MapCount = filterMapCount;
		                        }
		                    }
		                }
		            }
		        }
		    }
		}
	/*** END UI.ACTIVEFILTERS ***/

	/*** UI.TOOLS ***/
	
		function toggleTool(event){
			//selects or unselects the tool that was clicked
			var $clickedTool = $(event.target.parentNode);
			var unselected = $clickedTool.hasClass('tool_unselected');
			
			unselectAllTools();
		
			if (unselected) { //if tool was not selected, activate it
			    $clickedTool.toggleClass('tool_unselected');
				$clickedTool.children('img').removeClass('lowtransparency');
				var toolType = $clickedTool[0].id;
				
				//get the current number of providers displayed on the map
				var providerCount = getShapeLayerByTitle('providersGeorss').GetShapeCount();
				
				switch (toolType) {
					case 'Tool_Query':
						$('#' + toolType + '_Options').show('fast').center();; //display tool options
						break;
					case 'Tool_CoverageMap':
						if (!showAllProvidersMode && providerCount > 0) {
							$('#' + toolType + '_Help').show('fast'); //display tool help box
							updateProvidersGeorss();
						}
						else {
							alert('You cannot use this tool when all providers are displayed on the map or none are displayed.');
							unselectAllTools();
						}
						break;
					case 'Tool_ProviderReport':				
						if (providerCount > 0) {
							$('#' + toolType + '_Options').show('fast').center(); //display tool options
						}
						else {
							unselectAllTools();
							alert('There are no providers displayed on the map.');
						}
						break;
				}	
			} 
		}

		function unselectAllTools(){
			
			//select all spans with class 'tool_selectable' inside of Toolbar div
		    var tools = $('div#Toolbar span.tool_selectable');
			
			tools.addClass('tool_unselected');
			tools.children('img').addClass('lowtransparency'); //fix for IE where child img element does not inherit parent transparency
			
			$('.tool_help').hide('fast'); //hide tool help box
			$('.tool_options').hide('fast'); //hide tool options box
			
			setMapCursor('hand'); //reset map cursor
			
			//detach events
			try { map.DetachEvent("onmousedown", geoQueryByPointHandler); }
			catch (err) {}
			
			//clear out tool shape layers
			getShapeLayerByTitle('queryShapeLayer',true);
			getShapeLayerByTitle('coverageMapShapeLayer',true);

			map.HideInfoBox();

			if (mapDrawingTool !== undefined)  mapDrawingTool.disableDrawing();

		}
		

		function openProviderReport_ViewAll() {
		
			$('#Tool_ProviderReport_Options').hide('fast');
		    
		    //open provider report with proper querystring values
		    var view = map.GetMapView();
		    var top = view.TopLeftLatLong.Latitude;
		    var left = view.TopLeftLatLong.Longitude;
		    var bottom = view.BottomRightLatLong.Latitude;
		    var right = view.BottomRightLatLong.Longitude;
		    var points = [];
		    points.push({ Longitude: left, Latitude: top });
		    points.push({ Longitude: right, Latitude: top });
		    points.push({ Longitude: right, Latitude: bottom });
		    points.push({ Longitude: left, Latitude: bottom });
		    points.push({ Longitude: left, Latitude: top });
		    
		    var url;
		    url = 'report.aspx?';
		    if (showAllProvidersMode == false) {
		        url += '&ptypes=' + buildActiveFiltersList('ProviderType', true, false);
		        url += '&agencies=' + buildActiveFiltersList('Agency', true, false);
		        url += '&providers=' + buildActiveFiltersList('Provider', true, false);
		    }
		    else url += "&ptypes=ShowAll&agencies=0&providers=0";
		    
		    url += '&coords=' + buildCoordinateString(points);
		    window.open(url)
		}
		
		function openProviderReport_ViewPolygon() {
			$('#Tool_ProviderReport_Options').hide();
		    $('#Tool_ProviderReport_Help').show();
		    mapDrawingTool = new MapDrawingTool();
			mapDrawingTool.setCallback(function(drawingResult){
					//open provider report with proper querystring values
				    var url = 'report.aspx?';
				    if (showAllProvidersMode == false) {
				        url += '&ptypes=' + buildActiveFiltersList('ProviderType', true, false);
				        url += '&agencies=' + buildActiveFiltersList('Agency', true, false);
				        url += '&providers=' + buildActiveFiltersList('Provider', true, false);
				    }
				    else url += "&ptypes=ShowAll&agencies=0&providers=0";
				    
				    url += "&coords=" + buildCoordinateString(drawingResult.polygonShape.GetPoints());
				    window.open(url);
					mapDrawingTool.disableDrawing();
					unselectAllTools();

				});
			mapDrawingTool.enableDrawing();
		}
	/*** END UI.TOOLS ***/

	/*** UI.LAYERS ***/
	

	/*** END UI.LAYERS ***/
	
/*** END UI ***/



/*** EMAIL ***/


    function displayEmail() {
        document.getElementById("email").style.display = "block";
        document.getElementById("txtEmailSubject").value = "map";
        //document.getElementById("txtEmailBody").value = "View this map at " + generateEmailUrl();
		document.getElementById("txtEmailBody").value = "View this map at " + buildSessionURL();
    }

    function hideEmail() {
        document.getElementById("email").style.display = "none";
        document.getElementById("txtEmailSubject").value = "Texas Connector map";
        document.getElementById("txtEmailBody").value = "";

    }

    function enableSendEmailButton() {
        var f = document.getElementById("txtEmailFrom").value;
        var t = document.getElementById("txtEmailTo").value;

        if (f != null && f != "" && t != null && t != "") document.getElementById("btnSendEmail").disabled = false;
        else document.getElementById("btnSendEmail").disabled = true;

    }

/*** END EMAIL ***/


/*** PRINT ***/

    function stopPrintMode() {
        //disable Bing map printing
        var printOpt = new VEPrintOptions(false);
        try { map.SetPrintOptions(printOpt); }
        catch (ex) { }

        startMapMode();
        
        var form = document.getElementById('form1');
        var x = document.getElementById('printHeaderDiv');
        form.removeChild(x);

        map.DetachEvent("onmousedown", returnTrue);
        map.DetachEvent("onmousewheel", returnTrue);
        map.DetachEvent("onkeydown", returnTrue);
    }
    
    function startPrintMode(pageSize) {
        //configure map for printing (this function should only be run by printmap.aspx)

        //disable map moving
        map.AttachEvent("onmousedown", returnTrue);
        map.AttachEvent("onmousewheel", returnTrue);
        map.AttachEvent("onkeydown", returnTrue);

        window.onresize = null;
        
        map.HideDashboard(); //hide bing toolbar

        //enable Bing map printing
        var printOpt = new VEPrintOptions(true);
        
        //draybuck 10-8-10: although this originally worked without exception, it appears that something changed in the Bing API code that now causes an
        //exception to occur when using the map.SetPrintOptions method.  the exception is "TypeError: logo.GetURL is not a function".
        //we now handle the exception here and things still appear to work as expected.
        try { map.SetPrintOptions(printOpt); }
        catch (ex) {}

        //layout the page for printing
        var mapDiv = document.getElementById("myMap");

        var pageHeight; var pageWidth;
        switch (pageSize) {
            case "portraitletter":
                pageHeight = 908;
                pageWidth = 672;
                break;
            case "portraittabloid":
                pageHeight = 1488;
                pageWidth = 908;
                break;
            case "landscapeletter":
                pageHeight = 672;
                pageWidth = 908;
                break;
            case "landscapetabloid":
                pageHeight = 908;
                pageWidth = 1488;
                break;
            default:
                pageHeight = 908;
                pageWidth = 672;
        }
        mapWidth = pageWidth;
        mapHeight = pageHeight;
        map.Resize(mapWidth, mapHeight);

        mapDiv.style.height = mapHeight + 'px';
        mapDiv.style.width = mapWidth + 'px';

        document.getElementById('Toolbar').style.display = 'none';
        document.getElementById('ToolbarBack').style.display = 'none';
        document.getElementById('sidebar').style.display = 'none';
        document.getElementById('SidebarMinMax').style.display = 'none';
        document.getElementById('ActiveFiltersMinMax').style.display = 'none';
        document.getElementById('ContactOnestar').style.display = 'none';

        document.getElementById('print').style.display = 'none';

        var activeFiltersDiv = document.getElementById("ActiveFilters");
        if (activeFiltersDiv.style.display == 'none') toggleActiveFilters();
        document.getElementById('ActiveFiltersBack').style.height = pageHeight - 185 + 'px';
        var a = document.getElementById('ActiveFiltersFront');
        a.style.height = pageHeight - 185 + 'px';
        a.style.maxHeight = pageHeight - 220 + 'px';
        
        var form = document.getElementById('form1');
        var newdiv = document.createElement('div');
        newdiv.setAttribute('id', 'printHeaderDiv');
        form.appendChild(newdiv);
      
        //we must add the style and innerHTML after appending the child in order to work in IE
        var x = document.getElementById('printHeaderDiv');


        var html = "<img alt='Texas Connector - By OneStar Foundation' src='images/connectorlogo.png'/><br><br>"
        html += "<h1 onclick='stopPrintMode()' class='fakeLink'>Exit Print View</span>";
        x.innerHTML = html;

        //add delay before printing so that firefox will render tiles.
        //not doing so causes firefox to print blank map.
        //another option would be to implement this: http://social.msdn.microsoft.com/Forums/en-US/vemapcontroldev/thread/ac5636eb-6497-423e-89ec-66976a3b021c
        //window.setTimeout('window.print()', 2000);
    }
	
	function returnTrue(){return true;}

/*** END PRINT ***/
