﻿/// <reference path="googlemaps-intellisense.js" />
/// <reference path="GoogleStreetViewControl.js" />
/// <reference path="PolygonDrawerPrototype.js" />
/// <reference path="Identify.js" />
/// <reference path="Measure.js" />
/// <reference path="LocalLayerController.js" />

//----------------------------------Constant Decleration------------------------------------------------------
window._log = function () { };

var GISP = this.GISP || {};
GISP.MapUtilities = GISP.MapUtilities || {};

var GISP_MAPMODE_MAP = "MAP";
var GISP_MAPMODE_POLY = "POLY";
var GISP_MAPMODE_STREET = "STREET";
var GISP_MAPMODE_IDENTIFY = "IDENTIFY";
var GISP_MAPMODE_MEASURE = "MEASURE";
//var GISP_MAPMODE_POINT = "POINT";
var GISP_MAPMODE_POINT = "LOCAL";

var GISP_LOCATION_SCRIPTS = "/common/scripts/";
var GISP_LOCATION_IMAGES = "/common/images/";
var GISP_LOCATION_CSS = "/common/styles/";

var GISP_TIME_TO_WAIT_WHEN_CHECKING_LOAD_OF_SCRIPT = 300;

var _scriptType = _scriptType || "";
var _AssemblyVersion = _AssemblyVersion || "0";

var GISP_STREETVIEW_CONTROLLER = "StreetViewController" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_MEAUSRE_TOOL = "measure" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_IDENTIFY_TOOL = "identify" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_FIND_BY_LOCATION_TOOL = "findbylocation" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_LOCAL_LAYER_CONTROLLER = "locallayercontroller" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_POLYGON_DRAWER_TOOL = "polygondrawer" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_DRAGZOOM_TOOL = "DragZoom" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_CIRCLEDRAW_TOOL = "CircleDrawer" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_REPORT_EXPORTER = "ReportExporter" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_BUSINESS_REPORT_FUNCTIONS = "BusinessReportFunctions" + _scriptType + ".js?V=" + _AssemblyVersion;
var GISP_DEMOGRAPHIC_REPORT_FUNCTIONS = "DemographicReportFunctions" + _scriptType + ".js?V=" + _AssemblyVersion;

var GISP_PROPERTY_WIDTH = 190;
var GISP_PROPERTY_HEIGHT = 500;
var GISP_PROPERTY_CONTAINER_MARGIN = 48; //what is this for?
var GISP__mapMARGIN = 28;
var GISP_PROPERTY_PAGE_BUFFER = 3; //the number of times the page size results are kept active
var GISP_PROPERTY_PAGER_BUFFER = 2; //the number of pages shown on eiter side of the active page

var GISP_MILES_PER_METER = 0.000621371192;

var GISP_ReloadingReportQueue = [];

var _propertyMarkers = [];
var _bounds;
var _popupTracker = new GISPlanning_PopupTracker();
var _GISP_Filtering_Poly_Overlay;
var map;
var _mapBar;
var _windowResizeTimer = null;
var _inputKeyUpTimer = null;
var _inputKeyDownTimer = null;
var _JavascriptSessionID = GISPlanning_MapUtilities_GUID();
var _largeControl3D;
var _smallControl3D;
var _defaultUIOptions;
var _windowWidth;
var _infoWindow = new google.maps.InfoWindow();
var _currentGeoList = { List: null, Anchor: null };

//extend the infoWindow with a helper function
_infoWindow.show = function (latLng, html, options) {
    var myOptions = $.extend({ maxWidth: 500 }, options);
    var myPoint = new google.maps.MVCObject();
    myPoint.set("position", latLng);
    _infoWindow.open(map, myPoint);
    _infoWindow.setContent(html);
    _infoWindow.setOptions(myOptions);
};
var _businessMap = { hide: function () { } }; //a palce holder for the business map. Will be actually instantiated.

var addthis_options = 'email, facebook, twitter, favorites, delicious, digg, google, myspace, live, stumbleupon, more';
var addthis_exclude = 'print';

var _currentLayer = null;
var _currentOverlayType = null;
var _currentCheckedDataItem = null;

//This sections deals with the business map.
var _businessMapClickHandlers = {}; //an object to hold the possible handlers
var _currentBusinessMapClickHander = ""; //A reference to the currently selected handler
var _currentBusinessMapRequestID = ""; //The currentRequestID
var _currentBusinessMapQueryParams = {}; //The query used to build the current business map

var _SubsetAttributes = null;
function GISPLoad() {
    //Set up the modals
    $('#dynamicModalWindow').attr("ready", true);
    $("#dynamicModalWindow").draggable({ handle: "#moveDynamicWindow" });

    //Set up mouseover menus
    InitMouseOverMenus();

    //Bind to the browser resize(only for width resize)
    _windowWidth = $(window).width(); //capture the current width
    $(window).bind('resize', onWindowResizeDelegate);

    //add the right click option to my folder to clear it out
    $("#myFolder").rightClick(function () {
        if (confirm("Do you really want to reset My Folder?")) {
            ClearSavedResults('SITES_SAVED', false, false);
            ClearSavedResults('BUILDINGS_SAVED', false, false);
            ClearSavedResults('REPORTS_SAVED', false, false);
            ClearSavedResults('BUSINESSES_SAVED', false, false);
            //note, on this last one, we want to call persist trackers to avoid parallel errors.
            ClearSavedResults('COMMUNITIES_SAVED', false, true);
        }
    });

    ExecuteClientHeaderLoadScript();

    var _isFindByLocationEnabled = function () {
        var result = false;
        if (window._EnableFindByLocation === null) {
            result = false;
        }
        else {
            result = window._EnableFindByLocation;
        }
        // Querystring override
        if (/fbl=1/.exec(location.href) !== null) {
            result = true;
        }
        return result;
    };

    //TWW Create Map object
    var myMapOptions = {
        MapBarColor: '#c0c0c0',
        SearchBar: false,
        StreetView: true,
        Satellite: true,
        Terrain: true,
        Earth: true,
        PolySelect: true,
        Identify: true,
        FindByLocation: window._EnableFindByLocation === null ? false : window._EnableFindByLocation,
        LocalData: true,
        Pinpoint: true,
        Distance: true,
        CircleDraw: true,
        DragZoom: true,
        PolyOptions: {},
        GMapOptions: null,
        ScrollWheelZoom: false,
        ClickHandler: null,
        StreetOptions: {
            PanoDiv: $("#streetView")[0],
            ShowFunction: function () {
                $("#googleMap").removeClass("hide").addClass("show");
                //restore the map
                map.checkResize();
            },
            HideFunction: function () {
                $("#googleMap").removeClass("show").addClass("hide");
                //restore the map
                map.checkResize();
                map.addControl(_largeControl3D);
                map.removeControl(_smallControl3D);
            }
        },
        PolyStartedHandler: function () {
            RemovePoly(); //remove any existing permanent polygon
            HideSearch(); //in case you are coming to this from the search screen
        },
        PolySelectedHandler:
					function (poly) {
					    var polyPointsString = '';
					    var myPoints = poly.getPath().getArray();
					    var numVertex = myPoints.length;
					    for (i = 0; i < numVertex; i++) {
					        var vertex = myPoints[i];
					        var lat = vertex.lat().toString().substr(0, vertex.lat().toString().indexOf('.', 0) + 5);
					        var lng = vertex.lng().toString().substr(0, vertex.lng().toString().indexOf('.', 0) + 5);
					        polyPointsString += lat + ":" + lng;

					        if (i < numVertex - 1) {
					            polyPointsString += ",";
					        } //end if not last point
					    } //end for each point in polygon

					    document.getElementById('hfldPolyPoints').value = polyPointsString;
					    AddPersistantPolygonInidicatingSearchArea();
					    DisplaySearch(true, _SSR._CurrentViewType.toLowerCase());
					},
        LocalOptions: { LoadedHandler: LayerControlLoaded, IsOpenByDefault: true }
    };

    _mapBar = new MapBar(document.getElementById('googleMap'), myMapOptions);
    ClearLegend();
} //end function load

function unloadMap() {
    //_mapBar.googleEarth = null;
    _mapBar = null;
}

function AddNewTileLayer(pFolderName, pSubFolderName, pName, pDesc, pSender) {
    var overlay = new GISP_POIOverlay(pFolderName, _GISP_StaticSubsetTilesBaseURL + pSubFolderName, { opacity: 0.7 });
    pSender.AddLayer(new GISPlanning_MapUtilities_LocalLayer(pName, pDesc, overlay, "TILEOVERLAY", null, false, null, {}, [{}]));
}
function LayerControlLoaded(sender) {
    //National Layers
    var myAirports = new GISP_POIOverlay("AIRPORTS", _GISP_POITileBaseURL);
    var myColleges = new GISP_POIOverlay("COLLEGES", _GISP_POITileBaseURL);
    var myHospitals = new GISP_POIOverlay("HOSPITALS", _GISP_POITileBaseURL);
    var myPorts = new GISP_POIOverlay("PORTS", _GISP_POITileBaseURL);

    sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("AIRPORTS", "Airports", myAirports, "TILEOVERLAY", null, false, null, {}, [{}]));
    sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("COLLEGES", "Colleges", myColleges, "TILEOVERLAY", null, false, null, {}, [{}]));
    sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("HOSPITALS", "Hospitals", myHospitals, "TILEOVERLAY", null, false, null, {}, [{}]));
    sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("PORTS", "Ports", myPorts, "TILEOVERLAY", null, false, null, {}, [{}]));

    var _TileSST = "?SST=";

    if (typeof (_ZPEAltTileSST) !== "undefined" && _ZPEAltTileSST !== null) {
        _TileSST += _ZPEAltTileSST;
    }
    else {
        _TileSST += _GISP_Theme;
    }

    AddNewTileLayer("POP", _TileSST, "POPULATION", "Population", sender);
    AddNewTileLayer("BACHDEGREE", _TileSST, "BACHDEGREE", "Bachelors Degrees", sender);
    AddNewTileLayer("BUSEST", _TileSST, "BUSEST", "Total Business Establishments", sender);
    AddNewTileLayer("MEDHHINC", _TileSST, "MEDHHINC", "Median Household Income", sender);
    AddNewTileLayer("NATION", "?SST=SMALL_BIZ_PER_10K_CNTY", "SMALLBIZ", "Small businesses per 10k people", sender);
    AddNewTileLayer("NATION", "?SST=SOLE_PROPRIETORSHIP", "SOLEPROPRIETOR", "Sole Proprietors", sender);
    AddNewTileLayer("NATION", "?SST=STARTUP_PER_10K_COUNTY", "STARTUPS", "Startups per 10k people", sender);
    AddNewTileLayer("NATION", "?SST=HH_EXPENDITURES", "HHEXP", "Median household expenditures", sender);
    AddNewTileLayer("NATION", "?SST=MUSEUMS_COUNTY", "MUSEUMS", "Museums", sender);
    AddNewTileLayer("NATION", "?SST=RESTAURANTS_COUNTY", "RESTAURANTS", "Restaurants", sender);

    var myRRLayer = new GISP_POIOverlay("RAILROAD", _GISP_StaticSubsetTilesBaseURL + _TileSST, { opacity: 0.7 });
    var myCountiesLayer = new GISP_POIOverlay("COUNTIES", _GISP_StaticSubsetTilesBaseURL + _TileSST, { opacity: 0.7 });
    var myCitiesLayer = new GISP_POIOverlay("CITIES", _GISP_StaticSubsetTilesBaseURL + _TileSST, { opacity: 0.7 });

    sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("RAILROAD", "Railroads", myRRLayer, "TILEOVERLAY", null, false, null, {}, [{}]));
    sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("CITIES", "Cities", myCitiesLayer, "TILEOVERLAY", null, false, null, {}, [{}])); sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("COUNTIES", "Counties", myCountiesLayer, "TILEOVERLAY", null, false, null, {}, [{}]));

    var uncheckLayer = function () {
        var $this = $(this);
        $this.removeClass("set");
        myLayerID = $this.attr("LayerID");
        sender.HideLayer(myLayerID);
        $(".layerCheck", $this).removeClass("set");
        $("#tblLegend tr[layerID='" + myLayerID + "']").remove();
        $("#tblLegend tr[layerID='" + myLayerID + "']").remove();
        $("#" + myLayerID).remove();
    };
    var createLocalLayerLegend = function () {
        //create a new legend for each heat map
        var myBaseLegendHTML, myLegendRows, myBaseLegendRow, myLegendHtml, myLegendObject, myLayerID;
        var i, dataLength, myLegendItem, myRow;
        myLegendObject = this.myLegendObject;
        myLayerID = this.myLayerID;
        myLegendRows = myLegned = "";
        myBaseLegendHTML = '\
        <td valign="top" id="@ID">\
          <table width="220" border="0" cellspacing="0" cellpadding="0">\
            <tr>\
              <td>\
                <span class="legendTitle">@LABEL</span>\
              </td>\
            </tr>\
            @ROWS\
          </table>\
        </td>';
        myBaseLegendRow = '\
        <tr>\
          <td style="background:url(common/helpers/legendGenerator.ashx?color=@COLOR) no-repeat;">\
            <span class="colorBlock"></span>\
            <span class="legendLabels">@VALUE</span>\
          </td>\
        </tr>';
        if (typeof (myLegendObject) !== "undefined" && myLegendObject !== null && typeof (myLegendObject.Data) !== "undefined" && myLegendObject.Data !== null) {
            dataLength = myLegendObject.Data.length;
            for (i = 0; i < dataLength; i++) {
                myLegendItem = myLegendObject.Data[i];
                myRow = myBaseLegendRow.replace("@COLOR", myLegendItem.Color).replace("@VALUE", myLegendItem.Label);
                myLegendRows += myRow;
            }
            myLegendHtml = myBaseLegendHTML.replace("@ROWS", myLegendRows).replace("@LABEL", myLegendObject.Title).replace("@ID", myLayerID);
        }
        else {
            // If no data, hide the rows, set the label and id.
            myLegendHtml = myBaseLegendHTML.replace("@ROWS", "").replace("@LABEL", myLegendObject.Title).replace("@ID", myLayerID);
        }
        $("#trLegend").append(myLegendHtml);
    };
    var checkLayer = function () {
        var thisParentTR, myLayerID, myBackgroundImage, myLegendRaw, myLegendObject, $this;
        $this = $(this);
        $this.addClass("set"); //mark as active
        myLayerID = $this.attr("LayerID");
        sender.ShowLayer(myLayerID); //show the layer

        //add to the legend
        myBackgroundImage = $this.children("td:first").children("a:first").css("background-image");
        myLegendRaw = $this.attr("legend");
        myLegendObject = null;
        if (myLegendRaw !== null && myLegendRaw !== "") {
            myLegendObject = eval("(" + myLegendRaw + ")");
        }

        //set the layer current
        $(".layerCheck", $this).addClass("set"); //check the box

        //add the appropriate legend type
        if (typeof (myLegendObject) === "undefined" || myLegendObject === null) {
            // No legend data supplied, e.g. not a local layer 
            var myItem = '\
                <tr layerID="@layerID">\
                  <td class="@layerClass">\
                    <span class="layerIcon" style=\'background:@backgroundImage no-repeat;\'>\
                      <b>@layerName</b>\
                    </span>\
                    <span class="layerLabel">@layerName</span>\
                  </td>\
                </tr>';
            myItem = myItem.replace(/@layerID/g, myLayerID);
            myItem = myItem.replace(/@layerClass/g, $this.attr("class").replace(" GISPTileLayer", ""));
            myItem = myItem.replace(/@layerName/g, $this.attr("label").replace(/_/g, " "));
            myItem = myItem.replace("@backgroundImage", myBackgroundImage);
            $("#tblLegend").append(myItem);
        }
        else {
            this.myLayerID = myLayerID;
            this.myLegendObject = myLegendObject;
            createLocalLayerLegend.call(this);
        }

    };
    //setup toggeling of layer menu
    $("tr.GISPTileLayer").click(
		function () {
		    var isChecked = $(this).hasClass("set");
		    var myLayerID = null;
		    if (isChecked) {
		        uncheckLayer.call(this);
		    } else {
		        checkLayer.call(this);
		    } //end else
		    ResizeLegend();
		} //end click function callback
	);          //end click

    LoadLayersBasedOnSubsite(sender);
    ShowSubsetBoundary(sender);
}


function ResizeLegend() {
    var myAvailableWidth = GetClientWidth() - 500;
    var myLegendCols = $("#trLegend td").length;

    if (myLegendCols * 220 > myAvailableWidth) {
        var numCanShow = Math.floor(myAvailableWidth / 220);
        $("#legendHolder li:first").css("width", (numCanShow * 220 - 40) + "px");
    }
    else {
        $("#legendHolder li:first").css("width", "100%");
    }


    var myMaxHeight = 320;
    //loop thru each table in the legend and count the rows. Add 50 + 28 a row up to 320
    var myMaxRows = 0;
    $("#trLegend table").each(function () {
        var myNumRows = $("tr", $(this)).length;
        if (myNumRows > myMaxRows) {
            myMaxRows = myNumRows;
        }
    });

    var myHeight = 50 + 28 * myMaxRows;
    if (myHeight > myMaxHeight) {
        myHeight = myMaxHeight;
    }
    $("#legendHolder li:first").css("height", myHeight + "px");


}

function ToggleLocalLayer(pLayerID) {
    _mapBar.ToggleLocalLayer(pLayerID);
}

function RemoveMarkers(pMap, pMarkers) {
    for (var i = 0; i < pMarkers.length; i++) {
        pMarkers[i].setMap(null);
    } //end for

    //reset the property markers
} //end method

function ZoomToProperty(pPropertyID, REF_bounds, pZoomModifier) {
    log.info("ZoomToProperty()");
    log.info("- PropertyID: " + pPropertyID);
    log.info("- Ref_Bounds: " + REF_bounds);
    var myMarker = FindPropertyMarker(pPropertyID);
    var myBounds = new google.maps.LatLngBounds();
    log.info("- Marker type?: " + typeof (myMarker));
    if (typeof (myMarker) !== "undefined" && myMarker !== null) {
        myBounds.extend(myMarker.getPosition());

        map.fitBounds(myBounds);
        var myZoomModifier = (pZoomModifier !== undefined && pZoomModifier !== null) ? pZoomModifier : 0;
        var currentZoom = map.getZoom();
        var newZoom = currentZoom - (4 + myZoomModifier);
        newZoom = newZoom >= 22 ? 22 : newZoom;
        newZoom = newZoom <= 1 ? 1 : newZoom;
        map.setZoom(newZoom); //zooms it out a bit
    } //end if marker found

    //What does this do
    REF_bounds = myBounds;
    log.info("- Done ZoomToProperty()");
}

function ZoomToPropertyModal(pPropertyID) {
    tb_show("Interactive Map", '#TB_inline?height=460&width=960&inlineId=mapContainer');
    ZoomToProperty(pPropertyID);
} //end function



function GetStaticMapURL(pLat, pLng, pOptions) {

    var myLink = "http://maps.google.com/staticmap?size=@WIDTHx@HEIGHT&maptype=@TYPE&key=@KEY&sensor=false&markers=@LAT,@LNG,@COLOR&zoom=@ZOOM";
    myLink = myLink.replace("@LAT", pLat);
    myLink = myLink.replace("@LNG", pLng);

    var myOptions = {
        Width: 300,
        Height: 188,
        Type: 'Roadmap',
        Key: myGoogleAPIKey,
        Color: 'green',
        Zoom: 12
    };

    //get the passed in option, or use the default and update the link
    for (var o in myOptions) {
        if (typeof (pOptions[o]) != "undefined") {
            myOptions[o] = pOptions[o];
        } //end if option was passed in
        myLink = myLink.replace("@" + o.toUpperCase(), myOptions[o]);

    } //end for each option

    return myLink;

}



function CheckMapType(element) {
    jqElem = null;
    isSet = false;
    if (element !== null) {
        jqElem = $(element);
        isSet = jqElem.find(".layerCheck").hasClass("set");
    }

    //uncheck all elements
    checkMeItems = $(".layerCheck", $(element).parents("table:first"));
    checkMeItems.each(function (key, val) {
        $(val).removeClass("set");
    });
    if (element !== null) {
        jqElem.find(".layerCheck").toggleClass("set", !isSet);
    }

    if (!isSet) {
        setTimeout(function () {
            var oldText = $("a", element)[1].innerHTML;
            $("a", element)[1].innerHTML = "loading map...";
            setTimeout(function () { $("a", element)[1].innerHTML = oldText; }, 2000);
        }, 100); //run out of process
    }
}

function GetMapInformationByType(pType) {
    var myService, myLegendType, myLegendValues, myLegend;
    switch (pType) {
        case 0:
            myService = "STATIC_POPULATION";
            myLegendType = 'S';
            myLegendValues = GISP_GetSubsetAttribute(_GISP_Theme, "LEGEND_POPULATION");
            myLegend = "Population by Block Group";
            break;
        case 1:
            myService = "STATIC_BACHDEGREE";
            myLegendType = 'S';
            myLegendValues = GISP_GetSubsetAttribute(_GISP_Theme, "LEGEND_BACHDEGREE");
            myLegend = "Bachelors Degree % by Block Group";
            break;
        case 2:
            myService = "STATIC_BUSEST";
            myLegendType = 'S';
            myLegendValues = GISP_GetSubsetAttribute(_GISP_Theme, "LEGEND_BUSEST");
            myLegend = "Total Business Establishments by Block Group";
            break;
        case 3:
            myService = "STATIC_MEDHHINC";
            myLegendType = 'S';
            myLegendValues = GISP_GetSubsetAttribute(_GISP_Theme, "LEGEND_HHINCOME");
            myLegend = "Median Household Income by Block Group";
            break;
        case 4:
            myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicDotMaps/MapServer";
            myLayer = 2;
            myLegendValues = ["1.0% - 2.6%", "2.7% - 3.6%", "3.7% - 4.1%", "4.2% - 4.9%", "5.0% - 5.7%", "5.8% - 7.1%", "7.2% - 18.5%"];
            myLegend = "Young and Educated % by County";
            break;
        case 5:
            myService = "STATIC_SMALLBIZ";
            //myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematictalent/MapServer";
            myLegendType = 'S';
            myLegendValues = ["0.0 - 223.5", "223.6 - 269.3", "269.4 - 304.2", "304.3 - 338.5", "338.6 - 384.3", "384.4 - 456.0", "456.1 - 1962.5"];
            myLegend = "Small Business per 10K People By County";
            break;
        case 6:
            myService = "STATIC_SOLEPROPRIETOR";
            //myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicCOsoleprop11/MapServer";
            myLegendType = 'S';
            myLegendValues = ["0 - 435", "436 - 816", "817 - 1,272", "1,273 - 2,079", "2,080 - 3,445", "3,446 - 8,227", "8,228 - 799,108"];
            myLegend = "Sole Proprietors by County";
            break;
        case 7:
            myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicDotMaps/MapServer";
            myLegendValues = ["$75,000 - $1,770,000", "$1,770,000 - $4,000,000", "$4,000,000 - $8,000,000", "$8,000,000 - $16,770,000", "$16,770,000 - $36,500,000", "$36,500,000 - $80,740,000", "$80,740,000 - $994,077,000"];
            myLegend = "Venture Capital By City";
            break;
        case 8:
            //myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicCOstartups1/MapServer";
            myService = "STATIC_STARTUPS";
            myLegendType = 'S';
            myLegendValues = ["0.0 - 13.4", "13.5 - 16.3", "16.4 - 18.6", "18.7 - 21.3", "21.4 - 25.0", "25.1 - 30.6", "30.7 - 153.6"];
            myLegend = "Startups per 10K People by County";
            break;
        case 9:
            //myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicCOavghhexp11/MapServer";
            myService = "STATIC_HHEXP";
            myLegendType = 'S';
            myLegendValues = ["$28,454 - $39,652", "$39,652 - $41,655", "$41,655 - $43,400", "$43,400 - $45,309", "$45,309 - $47,657", "$47,657 - $51,946", "$51,946 - $87,003"];
            myLegend = "Median Household Expenditures by County";
            break;
        case 10:
            //myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicmusuemszoos/MapServer";
            myService = "STATIC_MUSEUMS";
            myLegendType = 'T';
            myLegendValues = ["0", "1 - 5", "6 - 10", "11 - 50", "51 - 100", "101 - 200", "201 - 301"];
            myLegend = "Museums by County";
            break;
        case 11:
            //myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicrestaurants/MapServer";
            myService = "STATIC_RESTAURANTS";
            myLegendType = 'S';
            myLegendValues = ["0 - 10", "11 - 50", "51 - 100", "101 - 500", "501 - 1,000", "1,001 - 5,000", "5,001+"];
            myLegend = "Restaurants by County";
            break;
        case 12:
            myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicDotMaps/MapServer";
            myLegendType = 'S';
            myLegendValues = ["0 - 600", "601 - 1,800", "1,801 - 3,934", "3,935 - 7,800", "7,801 - 15,612", "15,613 - 39,254", "39,255 - 82,340"];
            myLegend = "Stimulus Projects: Proposed New Jobs by City";
            break;
        case 13:
            myService = "http://gpvm002.gisplanning.net/ArcGIS/rest/services/zpdc_thematicDotMaps/MapServer";
            myLegendType = 'S';
            myLegendValues = ["$40,000 - $69,539,100", "$69,539,100 - $223,758,769", "$223,758,769 - $473,000,000", "$473,000,000 - $884,492,300", "$884,492,300 - $1,882,706,520", "$1,882,706,520 - $3,693,249,885", "$3,693,249,885 - $6,985,021,458"];
            myLegend = "Stimulus Projects: Proposed Spending by City";
            break;
        default:
            break;
    }

    return { service: myService,
        legendType: myLegendType,
        legendValues: myLegendValues,
        legendTitle: myLegend
    };
}
function ChangeMapType(pMapType) {
    log.info("Changing mapTpe to :" + pMapType);
    var myService = '';
    var myLegendType = 'R';
    var myLegendValues = null;
    var myLegend = '';
    var myLayer = 0;

    var mapTypeInfo = GetMapInformationByType(pMapType);
    myService = mapTypeInfo.service;
    myLegendType = mapTypeInfo.legendType;
    myLegendValues = mapTypeInfo.legendValues;
    myLegend = mapTypeInfo.legendTitle;

    if (pMapType > 10000) {
        var myLayerInfo = GetSubsetLayerInfo(pMapType);
        myService = myLayerInfo.Service;
        myLegendType = myLayerInfo.LegendType;
        myLegendValues = [""];
        myLegend = myLayerInfo.LegendTitle;
    }

    if (typeof (_currentLayer) !== "undefined" && _currentLayer !== null) {
        if (_currentLayer.url === undefined || _currentLayer.url === null) {
            _mapBar.GetLayerController().HideLayer(_currentLayer.ID);
        }
        else {
            _currentLayer.setMap(null);
        }
    }

    //If the current overlay being displayed is also the requested overlay. Hide the overlay.
    //This is equivalent to an "un-check", as in, "I no longer want to see this overlay."
    if (_currentOverlayType != pMapType) {
        var myLayerID, myResponse, myLayers, myDynamicMap;
        //show the layer
        //Currently two possibilities exist, our own static stiles or the Dynamic tile service
        if (myService.indexOf("STATIC", 0) === 0) {
            myLayerID = myService.split("_")[1];
            _mapBar.GetLayerController().ShowLayer(myLayerID);
            _currentLayer = _mapBar.GetLayerController().GetLayer(myLayerID);
        } else {
            // Create an ID from the service url
            myLayerID = myService.replace(/(http:\/\/)|\/|\./g, "");
            myResponse = function (overlay) {
                _currentLayer = overlay;
                overlay.setMap(map)
                myLayers = [];
                myLayers.push(myLayer);
                overlay.setVisibleLayers(myLayers);
                overlay.show();
            };
            myDynamicMap = new esri.arcgis.gmaps.DynamicMapServiceLayer(myService, null, 0.4, myResponse);
        }

        //update the legend
        UpdateLegend(myLegend, myLegendValues, myLegendType, myLayerID);
    }
    else {
        _currentOverlayType = null;
        ClearLegend();
        return;
    }
    _currentOverlayType = pMapType;
}

function ShowSubsetBoundary(sender) {
    var myBounaryLayer = new GISP_POIOverlay("SUBSETBOUNDARY", _GISP_LocalTilesBaseURL + '?SST=' + _GISP_Theme, { opacity: 1 });
    sender.AddLayer(new GISPlanning_MapUtilities_LocalLayer("SUBSETBOUNDARY", "Subset Boundary", myBounaryLayer, 'TILEOVERLAY', null, false, null, {}, [{}]));
    sender.ShowLayer("SUBSETBOUNDARY");
}
function ClearLegend() {
    var myLegendHolder = $("ul#legendHolder");
    var myLegendLabel = $("#legendLabel", myLegendHolder);
    var myLegendItems = $("#legendHeatItems", myLegendHolder);
    myLegendItems.hide();
    var myColors = ["purple", "blue", "lightblue", "yellow", "lightorange", "orange", "red"];
    for (i = 0; i < myColors.length; i++) {
        var myIncomeLabel = $("td." + myColors[i] + " span.legendLabels");
        myIncomeLabel.parent().removeClass("T").removeClass("R").removeClass("S");
        myIncomeLabel.html("");
    }
}
function UpdateLegend(pLegendLabel, pLegendValues, pLegendType, pLayerID) {
    ClearLegend();
    // this html is not on the page yet.
    var myLegendHolder = $("ul#legendHolder");
    //todo: need to get legend area by id of the layerid
    var myLegendLabel = $("#legendLabel", myLegendHolder);
    var myLegendItems = $("#legendHeatItems", myLegendHolder);
    myLegendItems.show();
    var myColors = ["purple", "blue", "lightblue", "yellow", "lightorange", "orange", "red"];

    myLegendLabel.html(pLegendLabel);

    for (i = 0; i < myColors.length; i++) {
        var myIncomeLabel = $("td." + myColors[i] + " span.legendLabels");
        myIncomeLabel.parent().addClass(pLegendType);
        myIncomeLabel.html(pLegendValues[i]);
    }
    myLegendItems.show();
}




/* A general function that associates an object instance with an event
handler. The returned inner function is used as the event handler.
The object instance is passed as the - obj - parameter and the name
of the method that is to be called on that object is passed as the -
methodName - (string) parameter.
*/
function GISPlanning_MapUtilities_AssociateObjWithEvent(obj, methodName, args) {
    /* The returned inner function is intended to act as an event
    handler for a DOM element:-
    */
    return (function (e) {
        /* The event object that will have been parsed as the - e -
        parameter on DOM standard browsers is normalised to the IE
        event object if it has not been passed as an argument to the
        event handling inner function:-
        */
        e = e || window.event;
        /* The event handler calls a method of the object - obj - with
        the name held in the string - methodName - passing the now
        normalised event object and a reference to the element to
        which the event handler has been assigned using the - this -
        (which works because the inner function is executed as a
        method of that element because it has been assigned as an
        event handler):-
        */
        return obj[methodName](e, this, args);
    });
}


//attaches an event listener
function AddEventHandler(obj, eventName, handler) {
    //add event handlers
    if (obj.addEventListener == undefined) {//this occurs when using IE
        obj.attachEvent(eventName, handler);
    }
    else {//hopefully everything else
        obj.addEventListener(eventName, handler, false);
    } //end attaching events
}


//adds a click handler (specialized version of AddEventHandler)
function AddClickHandler(obj, handler) {
    //add event handlers
    if (obj.addEventListener == undefined) {//this occurs when using IE
        obj.attachEvent("onclick", handler);
    }
    else {//hopefully everything else
        obj.addEventListener("click", handler, false);
    } //end attaching events
}



function GISP_MapUtilities_PrintMap() {
    var myMapGuid = GISPlanning_MapUtilities_GUID();

    //NOTE: Must use jquery clone in order to remove the event references so that removing the nonexportable and nonpopout methods
    //doesnt destroy the events
    var myMapClone = $("#map").clone()[0];
    GISP_RemoveNonExportable(myMapClone);
    GISP_RemoveNonPopout(myMapClone);
    var myMapContent = myMapClone.innerHTML;


    _popupTracker.AddContent(myMapGuid, myMapContent);

    GISPlanning_Popup_Window('main/reportViewers/map.aspx?id=' + myMapGuid, { width: 960, height: 420 });

} //end function


function GISP_RemoveNonExportable(pHtml) {
    $("body").append("<div id='GISP_RemoveNonExportable' style='display:none;'>" + pHtml + "</div>");

    var $nonExportable = $("#GISP_RemoveNonExportable");

    $nonExportable.find(".nonexportable").remove();
    $nonExportable.find("#__VIEWSTATE").remove();
    $nonExportable.find(".saveSlider").remove();
    $nonExportable.find(".propertyInfofg h4").remove();

    var html = $nonExportable.html();
    $nonExportable.remove();
    return html;
} //end function

function GISP_RemoveNonPopout(pDomElement) {
    $("body").append("<div id='GISP_RemoveNonPopout' style='display:none;'>" + pDomElement + "</div>");

    $("#GISP_RemoveNonPopout").find(".nonpopout").remove();

    var html = $("#GISP_RemoveNonPopout").html();

    $("#GISP_RemoveNonPopout").remove();
    return html;
} //end function

function GISP_RemoveFunctionHyperlinks(pHtml) {
    var $input = $("<div>" + pHtml + "</div>");
    //modify all hyperlinks to remove JS Functions
    $input.find("a").each(function () {
        if (this.href.indexOf("javascript:") != -1) {
            this.setAttribute("href", "");
        } //end if function link
        else if (this.href.indexOf("admin.zoomprospector.com") != -1) {
            this.setAttribute("href", "");
        }

    });
    return $input.html();
} //end function



//This function takes a collection of attributes and sets each one on the HTML element
function GISPlanning_MapUtilities_SetHTMLAttributes(element, attributeCollection) {
    for (var attribute in attributeCollection) {
        element[attribute] = attributeCollection[attribute];
    } //end for each attribute
} //end function




//------------------------ Tooltip Service --------------------------------------------------------------------------
GISP.MapUtilities = this.GISP.MapUtilities || {};
GISP.MapUtilities.TooltipOverlay = function () {

    this._Message = "";
    /**
    * Offset the control container from the mouse by this amount.
    */
    this.ANCHOR_OFFSET_ = new google.maps.Point(8, 8);

    /**
    * Pointer to the HTML container.
    */
    this._node = this._createHtmlNode();

    // Add control to the map. Position is irrelevant.
    map.controls[google.maps.ControlPosition.TOP].push(this._node);

    // Bind this OverlayView to the map so we can access MapCanvasProjection
    // to convert LatLng to Point coordinates.
    this.setMap(map);

    // Register an MVC property to indicate whether this custom control
    // is visible or hidden. Initially hide control until mouse is over map.
    this.set('visible', false);
}
GISP.MapUtilities.TooltipOverlay.prototype = new google.maps.OverlayView();
GISP.MapUtilities.TooltipOverlay.prototype.draw = function () { };

GISP.MapUtilities.TooltipOverlay.prototype._createHtmlNode = function () {
    var divNode = document.createElement('div');
    divNode.id = 'tooltip-control';
    divNode.index = 1700;
    divNode.className = "GISPlanning_MapUtilities_Tooltip";
    return divNode;
};




GISP.MapUtilities.TooltipOverlay.prototype.show = function () {
    // Register event listeners
    var me = this;
    me.set('visible', true);
    me._node.style.display = "block";
    me._mapMouseOverListener = google.maps.event.addListener(map, 'mouseover', function () {
        me.set('visible', true);
    });
    me._mapMouseOutListener = google.maps.event.addListener(map, 'mouseout', function () {
        me.set('visible', false);
    });
    me._mapMouseMoveListener = google.maps.event.addListener(map, 'mousemove', function (mEvent) {
        me.updatePosition(mEvent.latLng);
    });
}
GISP.MapUtilities.TooltipOverlay.prototype.remove = function () {
    log.info("tooltip was removed");
};

GISP.MapUtilities.TooltipOverlay.prototype.hide = function () {

    var me = this;
    me.set('visible', false);

    me._node.style.display = "none";
    //remove any eventHandlers
    if (me._mapMouseOverListener)
        google.maps.event.removeListener(me._mapMouseOverListener);
    if (me._mapMouseOutListener)
        google.maps.event.removeListener(me._mapMouseOutListener);
    if (me._mapMouseMoveListener)
        google.maps.event.removeListener(me._mapMouseMoveListener);

}


/**
* Specified LatLng value is used to calculate pixel coordinates and
* update the control display. Container is also repositioned.
* @param {google.maps.LatLng} latLng Position to display
*/
GISP.MapUtilities.TooltipOverlay.prototype.updatePosition = function (latLng) {
    var projection = this.getProjection();
    if (projection != null) {
        var point = projection.fromLatLngToContainerPixel(latLng);

        // Update control position to be anchored next to mouse position.
        this._node.style.left = point.x + this.ANCHOR_OFFSET_.x + 'px';
        this._node.style.top = point.y + this.ANCHOR_OFFSET_.y + 'px';

        // Update control to display latlng and coordinates.
        this._node.innerHTML = this._Message;
    } //end if projection exists
};

GISP.MapUtilities.TooltipOverlay.prototype.setMessage = function (pMessage) {
    this._Message = pMessage;
}

GISP.MapUtilities.TooltipService = function (map) {
    this._map = map;
    this.tooltip = new GISP.MapUtilities.TooltipOverlay();
    var me = this;


    /**
    * Constructor
    */
    return new function () {
        this.HideTooltip = function () {
            me.tooltip.setMessage("");
            me.tooltip.hide();
        };   //end function

        this.DisplayTooltip = function (tooltipText) {
            me.tooltip.setMessage(tooltipText);
            me.tooltip.show();
        };      //end function
    } //end constructor
}    //end function class




function GISPlanning_MapUtilities_latLonInMapBounds(lat, lon) {
    var bounds = map.getBounds();
    if (lat < bounds.minY || lat > bounds.maxY ||
		 lon < bounds.minX || lon > bounds.maxX) {
        return false;
    } else {
        return true;
    } //end if/else
} //end function

function GISPlanning_MapUtilities_RegisterCSSFile(pURL) {
    var myHead = document.getElementsByTagName("head").item(0);
    var myCSSLink = document.createElement("link");
    myCSSLink.setAttribute("href", pURL);
    myCSSLink.setAttribute("rel", "stylesheet");
    myCSSLink.setAttribute("type", "text/css");
    myHead.appendChild(myCSSLink);
} //end function register CSS

function GISPlanning_MapUtilities_RegisterScript(pURL) {
    //append the script
    var myHead = document.getElementsByTagName("head").item(0);
    var myLink = document.createElement("script");
    myLink.setAttribute("src", pURL);
    myLink.setAttribute("type", "text/javascript");
    myHead.appendChild(myLink);
} //end method

function GISPlanning_MapUtilities_GUID() {
    this._R4 = function () {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }; //end function R4
    this._GetNewRequestID = function GetRequestID() {
        return (this._R4() + this._R4() + "-" + this._R4() + "-" + this._R4() + "-" + this._R4() + "-" + this._R4() + this._R4() + this._R4());
    }; //end function GetNewRequestID

    return this._GetNewRequestID();
} //end



function GISPlanning_GetListboxOptionsAsList(pListbox, pDelimiter) {
    var myReturnString = '';
    for (var i = 0; i < pListbox.options.length; i++) {
        myReturnString = myReturnString + pListbox.options[i].value;
        if (i < pListbox.options.length - 1) {
            myReturnString = myReturnString + pDelimiter;
        } //end if not last option
    } //end for each option

    return myReturnString;
}

function GISPlanning_GetListboxDisplayItemsAsList(pListbox, pDelimiter) {
    var myReturnString = '';
    for (var i = 0; i < pListbox.options.length; i++) {
        myReturnString = myReturnString + pListbox.options[i].text;
        if (i < pListbox.options.length - 1) {
            myReturnString = myReturnString + pDelimiter;
        } //end if not last option
    } //end for each option

    return myReturnString;
}


function GISPlanning_Popup_Window(pURL, pOptions) {
    var myWindowOptions = { toolbar: "0", scrollbars: "1", location: "0", statusbar: "0", menubar: "0", resizable: "1", width: "970", height: "650", left: "300", top: "0" };
    pOptions = pOptions !== null ? pOptions : {};
    for (var o in myWindowOptions) {
        if (typeof (pOptions[o]) != "undefined") {
            myWindowOptions[o] = pOptions[o];
        } //end if option was passed in
    } //end for each option
    var myDay = new Date();
    var myId = myDay.getTime();
    window.open(pURL, myId, 'toolbar=' + myWindowOptions["toolbar"] + ',scrollbars=' + myWindowOptions["scrollbars"] + ',location=' + myWindowOptions["location"] + ',statusbar=' + myWindowOptions["statusbar"] + ',menubar=' + myWindowOptions["menubar"] + ',resizable=' + myWindowOptions["resizable"] + ',width=' + myWindowOptions["width"] + ',height=' + myWindowOptions["height"] + ',left =' + myWindowOptions["left"] + ',top = ' + myWindowOptions["top"]);
} //end function

function GISPlanning_PopupTracker() {
    this.Container = {};
    this.GetContent = function (pKey) {
        return this.Container[pKey];
    }; //end method
    this.AddContent = function (pKey, pContent) {
        this.Container[pKey] = pContent;
    }; //end method
} //end class GISPlanning_PopupTracker



function GISPlanning_AddPopup(pElement, pEM_HTML) {
    $(pElement).append(pEM_HTML);

    $(pElement).click(function () {
        $(this).find("em").animate({ opacity: "show" }, "slow");
    });
    $(pElement).hover(function () { }, function () {
        $(this).find("em").animate({ opacity: "hide" }, "fast");
    });
} //end function

function GISPlanning_HidePopup(pID) {
    var myPopup = $("#" + pID)[0];
    $(myPopup).find("em").animate({ opacity: "hide" }, "fast");
} //end function


function GISPlanning_CreateGCircle(pLat, pLng, pRadius, pOptions) {
    var myOptions = $.extend({ clickable: true, shouldFill: true }, pOptions);

    var circleObj = {
        map: map,
        center: new google.maps.LatLng(pLat, pLng),
        radius: pRadius * 1609.344,
        strokeColor: "#01277d",
        strokeOpacity: .8,
        fillColor: "#01277d",
        fillOpacity: 0.1,
        clickable: myOptions.clickable
    };


    if (myOptions.shouldFill == false) {
        circleObj.fillColor = "";
        circleObj.fillOpacity = 0;
    }
    var myCircle = new google.maps.Circle(circleObj);

    return myCircle;

} //end function

function GISP_NullOrInputValue(pElementID) {
    var myInputElement = $("#" + pElementID)[0];
    var myReturnValue = null;
    switch (myInputElement.type) {
        case "text":
            myReturnValue = myInputElement.value; break;
        case "select-one":
            for (var i = 0; i < myInputElement.options.length; i++) {
                if (myInputElement.options[i].selected) {
                    myReturnValue = myInputElement.options[i].value;
                    break;
                } //end if selected
            } //end for
            break;
        case "checkbox":
            myReturnValue = myInputElement.checked; break;
        default:
            myReturnValue = "";
            break;
    } //end switch
    return myReturnValue !== "" ? myReturnValue : null;
}


function GISP_GetDropDownSelectedDisplayValue(pDropDown) {
    var myReturnValue = null;
    for (var i = 0; i < pDropDown.options.length; i++) {
        if (pDropDown.options[i].selected) {
            myReturnValue = pDropDown.options[i].text;
            break;
        } //end if selected
    } //end for
    return myReturnValue;
} //end function

function DisplayInlineTable(pTableID) {
    if ($.browser.msie) {
        $("#" + pTableID).css("display", "inline");
    } else {
        $("#" + pTableID).css("display", "inline-table");
    } //end ifelse IE
} //end function

function GetClientWidth() {
    var x = 0;
    if (self.innerHeight) {
        x = self.innerWidth;
    }
    else if (document.documentElement && document.documentElement.clientHeight) {
        x = document.documentElement.clientWidth;
    }
    else if (document.body) {
        x = document.body.clientWidth;
    }
    return x;
}
function GetClientHeight() {
    var y = 0;
    if (self.innerHeight) {
        y = self.innerHeight;
    }
    else if (document.documentElement && document.documentElement.clientHeight) {
        y = document.documentElement.clientHeight;
    }
    else if (document.body) {
        y = document.body.clientHeight;
    }
    return y;
}

function FixIE7IndexingContainer(pContainer, pStartZIndex) {
    if (($.browser.msie && jQuery.browser.version < 8) || ($.browser.msie && $("meta[content='IE=EmulateIE7']").length == 1)) {
        //pContainer is a jquery container, pStartZIndex is optional
        var zIndexNumber = (typeof (pStartZIndex) != "undefined" && pStartZIndex !== null) ? pStartZIndex : 1000;
        $('div:not(.zSpecial), ul:not(.zSpecial), li:not(.zSpecial), span:not(.zSpecial), a:not(.zSpecial)', pContainer).andSelf().each(function () {
            $(this).css('zIndex', zIndexNumber);
            zIndexNumber -= 1;
        });
    }
}

function formatNumber(nStr) {
    if (isNaN(nStr)) { return nStr; }
    nStr += ''; x = nStr.split('.'); x1 = x[0]; x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ',' + '$2'); }
    return x1 + x2;
} //end function

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function (from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};


function ExecuteClientHeaderLoadScript() {
    if (typeof (HeaderLoad) != "undefined") {
        HeaderLoad();
        return true;
    }
    else {
        return false;
    }
}


function ExecuteHeaderCommand(pCommand, pOptions) {
    switch (pCommand) {
        case "FINDPROPERTIES": DisplaySearch(false, "SITES"); break;
        case "FINDBUILDINGS": DisplaySearch(false, "BUILDINGS"); break;
        case "FINDCOMMUNITIES": DisplaySearch(false, "COMMUNITIES"); break;
        case "FINDBUSINESSES": DisplaySearch(false, "BUSINESSES"); break;
        case "RESOURCES": throw "Not implemented yet"; break;
        case "COMMUNITYREPORTS": DisplaySearch(false, "COMMUNITIES"); break;
        case "ADMINLOGIN": throw "Not implemented yet"; break;
        default: throw "Invalid header commmand"; break;
    }
}


function GetStateAbbreviation(pStateID) {
    var myAbbrev = {
        "01": "AL",
        "02": "AK",
        "04": "AZ",
        "05": "AR",
        "06": "CA",
        "08": "CO",
        "09": "CT",
        "10": "DE",
        "11": "DC",
        "12": "FL",
        "13": "GA",
        "15": "HI",
        "16": "ID",
        "17": "IL",
        "18": "IN",
        "19": "IA",
        "20": "KS",
        "21": "KY",
        "22": "LA",
        "23": "ME",
        "24": "MD",
        "25": "MA",
        "26": "MI",
        "27": "MN",
        "28": "MS",
        "29": "MO",
        "30": "MT",
        "31": "NE",
        "32": "NV",
        "33": "NH",
        "34": "NJ",
        "35": "NM",
        "36": "NY",
        "37": "NC",
        "38": "ND",
        "39": "OH",
        "40": "OK",
        "41": "OR",
        "42": "PA",
        "44": "RI",
        "45": "SC",
        "46": "SD",
        "47": "TN",
        "48": "TX",
        "49": "UT",
        "50": "VT",
        "51": "VA",
        "53": "WA",
        "54": "WV",
        "55": "WI",
        "56": "WY",
        "72": "PR"
    };

    return myAbbrev[pStateID];
}



function GISP_GetSubsetAttribute(pSubsetToken, pAttributeToken) {


    var myAttributeValue = null;
    $.ajax({
        url: "/common/services/Utilities.asmx/GetSubsetAttribute",
        async: false,
        data: "{'pSubsetToken': '" + pSubsetToken + "','pAttributeToken':'" + pAttributeToken + "'}",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        type: "POST",
        cache: false, //TODO: insures the latest version (we may want to consider turning this off after development)
        success: function (result) {
            myAttributeValue = result.d;
        }
    });

    return myAttributeValue.split('|');
}




function ShowBusinessMapTileLayer(pRequestID) {

    //create a POI layer and add the additinoal querystring options
    _businessMap = new GISP_POIOverlay(null, "/common/helpers/GetBusinessTile.ashx", { QS: "R=" + pRequestID });
    _businessMap.show(); //makes it visible.
    _mapBar.SetMapMode("GISP_BUSINESS");
}

function GetAllBusinessTypes(pCallback) {
    var myBusinessTypes = null;
    $.ajax({
        type: "POST",
        dataType: "json",
        data: "{}",
        async: true,
        contentType: "application/json; charset=utf-8",
        url: "/common/services/Business.asmx/GetAllBusinessTypes",
        success: function (msg, status) {
            myBusinessTypes = msg.d;
            pCallback(myBusinessTypes);
        }
    });
}

//Get's all NAICS 2-digit classes, and returns them to a callback function
function GetAllNaicsClasses(pCallback) {
    var myNaicsClasses = null;
    $.ajax({
        type: "POST",
        dataType: "json",
        data: "{}",
        async: true,
        contentType: "application/json; charset=utf-8",
        url: "/common/services/Business.asmx/GetAllNAICS",
        success: function (msg, status) {
            myNaicsClasses = msg.d;
            pCallback(myNaicsClasses);
        },
        error: function () { }
    });
}

//Get's all NAICS 6 digits, and returns them to a callback function
function GetAllNAICS(pCallback) {
    var myNaicsClasses = null;
    $.ajax({
        type: "POST",
        dataType: "json",
        data: "{}",
        async: true,
        contentType: "application/json; charset=utf-8",
        url: "/common/services/Business.asmx/GetAllNAICSCodes",
        success: function (msg, status) {
            myNaicsCodes = msg.d;
            pCallback(myNaicsCodes);
        },
        error: function () { }
    });
}


function FindBusinessByClick(pPoint) {
    $.ajax({
        type: "POST",
        async: true,
        url: "/common/services/Business.asmx/FindBusinessIDByLatLngRequestID",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        data: "{'pLat':'" + pPoint.lat() + "','pLng':'" + pPoint.lng() + "','pRequestID':'" + _currentBusinessMapRequestID + "' }",
        success: function (msg) {
            //call the currently set click handler for business mapping.

            delete msg.d.__type;  //remove this pesky attribute that causes seralization failure when present
            _businessMapClickHandlers[_currentBusinessMapClickHander](msg.d);
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            log.info("FindBusinessByClick: No business found for that point.");
        }
    });
} //end function

function GetBusinessInformation(pBusinessID, pSuccessCallback, pFailCallback) {
    //Ajax request to get additional business info
    $.ajax({
        type: "POST",
        async: true,
        url: "/common/services/Business.asmx/GetAdditionalBusinessInformation",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        data: "{'pBusinessID':'" + pBusinessID + "'}",
        success: function (msg) {
            delete msg.d.__type;  //remove this pesky attribute that causes seralization failure when present
            pSuccessCallback(msg);
        },
        error: pFailCallback
    });
}


function ShowErrorMessage(pError) {
    var myMessage = JSON.stringify(pError);
    $("#errorMessage").html(myMessage);
}

function LogUsage(pUsage) {
    pUsage.SubsetTOKEN = _GISP_Theme;
    pUsage.SessionID = _JavascriptSessionID;
    var myUsage = { "pUsage": pUsage };
    //record usage and move on, nothing to see here.
    $.ajax({
        type: "POST",
        async: true,
        url: "/common/services/Analysis.asmx/RecordUsage",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(myUsage),
        success: function (msg) {
            //Do nothing
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            // alert(XMLHttpRequest);
        }
    });
}

function LogReportUsage(pID, pReport, pValue) {
    var myUsageType = "";
    switch (pReport) {
        case "FULL": myUsageType = "FULLPROPERTYRPT"; break;
        case "COMMUNITY": myUsageType = "COMMUNITYRPT"; break;
        case "BUSINESS": myUsageType = "BUSINESSRPT"; break;
        case "CONSUMERSPENDING": myUsageType = "CONSUMERRPT"; break;
        case "DEMOGRAPHICS": myUsageType = "DEMOGRAPHICSRPT"; break;
        case "LABORFORCE": myUsageType = "LABORFORCERPT"; break;
        case "WAGES": myUsageType = "WAGESRPT"; break;
        default: myUsageType = ""; break;
    } //end switch
    LogUsage({ "Type": myUsageType, "ID": pID, "Value": pValue });
}
// from: http: //sajjadhossain.com/2008/10/31/javascript-string-trimming-and-padding/
String.prototype.rpad = function (padString, length) {
    var str = this;
    while (str.length < length) {
        str = str + padString;
    }
    return str;
};

// from http://www.codingforums.com/showthread.php?p=178077#post178077
Number.prototype.toDecimal = function (n) {
    n = (isNaN(n)) ? 2 : n;
    var nT = Math.pow(10, n);
    function pad(s) {
        s = s || '.';
        return (s.length > n) ? s : pad(s + '0');
    }
    return (isNaN(this)) ? this : ((Math.round(this * nT) / nT)).toString().replace(/(\.\d*)?$/, pad);
};

var $get = $get || function (id) {
    return $("#" + id)[0];
};
var $find = $find || function (id) {
    return $("#" + id);
};

var PostToService = function (url, parameters, success, error) {
    $.ajax({
        url: url,
        type: "POST",
        dataType: "json",
        data: parameters,
        contentType: "application/json; charset=utf-8",
        success: success,
        error: error
    });
};

var debug_mode = false;
if (!(/debug=1/i).exec(location.href)) {
    window.log = {
        toggle: function () { },
        move: function () { },
        resize: function () { },
        clear: function () { },
        debug: function () { },
        info: function () { },
        warn: function () { },
        error: function () { },
        profile: function () { }
    };
}
else {
    debug_mode = true;
}


//if the browser supports postMessage, we will listen for RPC calls
if (typeof (window.postMessage) == "function") {
    window.addEventListener("message", function (event) {
        try {
            var myData = JSON.parse(event.data);
            if (myData.cmd) {
                switch (myData.cmd) {
                    case "SEARCH":
                        DisplaySearch(false, myData.args);
                        break;
                } //end switch
            } //end if
        } //end try
        catch (err) {
            //do nothing
        } //end catch
    }, false);
} //end for html5 browsers
