﻿//cosgis namespace
var cosgis = {};
//Google maps
cosgis.map = null;
cosgis.polyline = null;
cosgis.geocoder = null;
cosgis.marker;
//Map servers
//cosgis.map_server1 = "198.1.35.120";
cosgis.map_server1 = window.cosgis_map_server;
//Dynamic map
cosgis.dynamic_map_overaly = null;
cosgis.dynamic_map = null;
cosgis.dynamic_map_name = "COS_OverlayCityMap_WM";
cosgis.dynamic_url = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/" + cosgis.dynamic_map_name + "/MapServer";
cosgis.dynamic_service_url = "http://" + cosgis.map_server1 + "/arcgis/services/" + cosgis.dynamic_map_name + "/MapServer";
cosgis.dynamic_opacity = 0.5;
//Tiled maps
cosgis.tile_url_base = "http://" + cosgis.map_server1 + "/arcgis/rest/services/COS_BasemapParcel_WM_Cache/MapServer";
cosgis.tile_url_ortho_2007 = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/COS_Ortho2007_WM_Cache/MapServer";
cosgis.tile_url_ortho_2008 = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/COS_Ortho2008_WM_Cache/MapServer";
cosgis.tile_url_ortho_2009 = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/COS_Ortho2009_WM_Cache/MapServer";
cosgis.tile_url_lidar = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/COS_LIDAR2007_WM_Cache/MapServer";
cosgis.tile_url_aerial_1958 = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/COS_Aerial1958_WM_Cache/MapServer";
cosgis.tile_url_street = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/COS_Street_WM_Cache/MapServer";
cosgis.tile_url_street_name = "http://" + cosgis.map_server1 + "/ArcGIS/rest/services/COS_StreetName_WM_Cache/MapServer";
//Custom map types
cosgis.map_type_count = 6;
cosgis.map_types = [];
//Custom map tiles
cosgis.map_tiles = [];
//Toc
cosgis.toc = null;
cosgis.TOC_IMAGE_PLUS = "_images/plus.gif";
cosgis.TOC_IMAGE_MINUS = "_images/minus.gif";
//Overlays
cosgis.map_extension = null;
cosgis.map_overlays = null;
//Identify
cosgis.id_task = null;
cosgis.id_point = null;
cosgis.id_overlays = [];
cosgis.id_oids = [];
cosgis.search_new = true;
cosgis.PARCEL_LAYER = "Parcel";
cosgis.PARCEL_FIELD_LIST = ["Parcel Number", "Acreage", "Owner Name", "Site Address", "Assessed Value", "Zoning", "Jurisdiction"];
cosgis.ASSESSOR_LINK = "http://www.spokanecounty.org/pubpadal/Search.aspx?Identify=spokanecity&txtSelParcel=";
cosgis.ZONING_LINK = "http://www.spokaneplanning.org/current.htm#Zoning%20Table";
//Ajax
cosgis.ajax_host = null;
cosgis.ajax_toc = null;
cosgis.ajax_search = null;
cosgis.search_time = null;
//Form data
cosgis.form_data = [];
cosgis.form_data["NavTab"] = "Layers"; //preloaded value
cosgis.form_data["SearchTab"] = "Address"; //preloaded value
//Measure;
cosgis.measure_dist = 0;
//Map Start Coords
cosgis.LAT = 47.676;
cosgis.LNG = -117.424;
//Results
cosgis.result_tables = [];
//Street View
cosgis.sv_overlay = null;
cosgis.sv_marker = null;
cosgis.sv_pano = null;
cosgis.sv_client = null;
cosgis.sv_pano_div = null;
//Include layers
cosgis.include_layers = [];
cosgis.has_map_overlay = false;

//------------------------------------------------------------//
//--GOOGLE MAPS--//
//------------------------------------------------------------//
//Init Map
function load() {
    if (GBrowserIsCompatible()) {
        //hideShowLeft();
        resizeApp();
        loadCustomMapTiles();      
    }
}

//Zoom
function zoomHome() {
    zoomTo(cosgis.LAT, cosgis.LNG, 12);
}

function zoomTo(lat, lng, zlevel) {
    var pt = new GLatLng(lat, lng);
    cosgis.map.setCenter(pt, zlevel);
}

//Tile Layer
function makeStaticTileLayer(url, minzoom, maxzoom, opacity) {
    var tilelayer = new GTileLayer(new GCopyrightCollection(), minzoom, maxzoom);
    tilelayer.getTileUrl = function(tile, zoom) {
        return url;
    };
    tilelayer.getOpacity = function() { return opacity; }
    return tilelayer;
}

//Add point and info window to map
function addMarker(pnt, html) {
    //Remove other markers
    removeMarker();
    //Set zoom
    if (cosgis.map.getZoom() < 17)
        cosgis.map.setZoom(17);
    //Center
    cosgis.map.setCenter(pnt);
    //Create marker and add to map
    cosgis.marker = new GMarker(pnt);
    cosgis.map.addOverlay(cosgis.marker);
    //Info windows options
    var opts = { maxWidth: 250 };
    //Open info window
    cosgis.marker.openInfoWindowHtml(html, opts);
    //Open onclick
    GEvent.addListener(cosgis.marker, "click", function() {
        cosgis.marker.openInfoWindowHtml(html, opts);
    });
}

function removeMarker() {
    if (typeof (cosgis.marker) != 'undefined')
        cosgis.map.removeOverlay(cosgis.marker);
}

//Geocode
function geocodeAddress(address) {
    var typ = escape(document.getElementById('sTab').value);
    if (cosgis.geocoder) {
        switch (typ) {
            case "Address":
                address = address + " Spokane, WA";
                cosgis.geocoder.getLocations(address, addAddressToMap);
                break;
        }
    }
}


//Add structured address to map
function addAddressToMap(response) {
    //cosgis.map.clearOverlays();
    if (!response || response.Status.code != 200) {
        alert("Address not found");
        cosgis.search_new = false;
    } else {
        var place = response.Placemark[0];
        var addr = place.address.split(",");
        var point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
        
        //Write html
        var html = "<div id=\"divResultsWindow\" ><h3>Address:</h3><p>" + addr[0] + "<br>" + addr[1] + ", " + addr[2] + "</p></div>";

        //Add points to map
        addMarker(point, html);

        //Write to results div
        e('txtSearch').value = addr[0];
        if (cosgis.search_new)
            writeResults("divAddressSearch", "ulAddressSearch", 'Address');
    }
}

//------------------------------------------------------------//
//--ESRI REST API--//
//------------------------------------------------------------//
//Dynamic layer opacity
function setOp() {
    var val = parseFloat(document.getElementById("divHorizontalSlider").value);
    val = val / 100;
    cosgis.toc.SetLegendOpacity(val);
    cosgis.dynamic_map.setOpacity(val);
    //changeOpacity(e("tocSpokane"), val);
}

//Dynamic map
function addDynamicMap(service) {
    //Turn dynamic layers on by default
    cosgis.include_layers = getQueryLayers();
    //Image parameters
    var imageParams = new esri.arcgis.gmaps.ImageParameters();
    imageParams.format = "png24";
    if (cosgis.include_layers.length > 0) {
        imageParams.layerIds = cosgis.include_layers;
        imageParams.layerOption = "include";
    }
    //Dynamic map
    cosgis.dynamic_map = new esri.arcgis.gmaps.DynamicMapServiceLayer(service, imageParams, cosgis.dynamic_opacity, dynMapCallBack);
    //cosgis.dynamic_map.setVisibleLayers([999]);
    
    //TOC
    getTOC();
}

function dynMapCallBack(groundov) {
    cosgis.map.addOverlay(groundov);
    cosgis.dynamic_map_overaly = groundov;
}

//Cached map tiles
function loadCustomMapTiles() {
    //Date
    var dt = new Date();
    var year = dt.getFullYear();
    
    //Copyright
    var cosCopyrightCollection = new GCopyrightCollection("@" + year + " - ");
    var cosCopyright = new GCopyright('cos', new GLatLngBounds(new GLatLng(-90, -180), new GLatLng(90, 180)), 0, "City of Spokane GIS");
    cosCopyrightCollection.addCopyright(cosCopyright);
    
    //Options
    var mapOptions = { opacity: 1.0, minResolution: 11, maxResolution: 19, copyrights: cosCopyrightCollection };
    var mapOptions2 = { opacity: 0.6, minResolution: 12, maxResolution: 17 };
    var mapOptions3 = { opacity: 1.0, minResolution: 12, maxResolution: 19 };

    //Tiles
    var street_tiles = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_street, mapOptions2);
    var streetname_tiles = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_street_name, mapOptions3);
    
    cosgis.map_tiles[0] = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_base, mapOptions,
    function(tiles) {
        callback_loadCustomMapTiles([tiles], "Spokane", 11, 19, 0);
    });
    
    cosgis.map_tiles[1] = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_ortho_2007, mapOptions,
    function(tiles) {
        callback_loadCustomMapTiles([tiles, street_tiles, streetname_tiles], "2007 Photo", 11, 19, 1);
    });

    cosgis.map_tiles[2] = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_ortho_2008, mapOptions,
    function(tiles) {
        callback_loadCustomMapTiles([tiles, street_tiles, streetname_tiles], "2008 Photo", 11, 19, 2);
    });

    cosgis.map_tiles[3] = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_ortho_2009, mapOptions,
    function(tiles) {
        callback_loadCustomMapTiles([tiles, street_tiles, streetname_tiles], "2009 Photo", 11, 19, 2);
    });

    cosgis.map_tiles[4] = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_aerial_1958, mapOptions,
    function(tiles) {
        callback_loadCustomMapTiles([tiles, street_tiles, streetname_tiles], "1958 Photo", 13, 18, 3);
    });

    cosgis.map_tiles[5] = new esri.arcgis.gmaps.TiledMapServiceLayer(cosgis.tile_url_lidar, mapOptions, 
    function(tiles) {
        callback_loadCustomMapTiles([tiles, street_tiles, streetname_tiles], "LIDAR", 11, 19, 4);
    });
}

function callback_loadCustomMapTiles(tiles, name, min, max, sort) {
    var opts = { errorMessage: "No data available", minResolution: min, maxResolution: max };
    cosgis.map_types.push([new GMapType(tiles, new GMercatorProjection(20), name, opts),sort]);
    mapInit();
}

function getSortedMapTypes() {
    var map_types = [];
    var numItems = cosgis.map_types.length;
    var count = 0;

    while (count < numItems) {
        for (typ in cosgis.map_types) {
            if (count == cosgis.map_types[typ][1])
                map_types.push(cosgis.map_types[typ][0]);
        }
        count++;
    }

    return map_types;
}

//Map initilization
function mapInit() {
    if (cosgis.map_types.length == cosgis.map_type_count) {
        var map_types = getSortedMapTypes();
        //Google map tiles
        var opts = { errorMessage: "No data available", minResolution: 1, maxResolution: 19 };
        var tileSat = G_SATELLITE_MAP.getTileLayers()[0];
        var tileHyb = G_HYBRID_MAP.getTileLayers()[1];
        var tileNor = G_NORMAL_MAP.getTileLayers()[0];
        var tileTer = G_PHYSICAL_MAP.getTileLayers()[0];
        map_types.push(new GMapType([tileNor], G_NORMAL_MAP.getProjection(), "Google Map", opts));
        map_types.push(new GMapType([tileSat, tileHyb], G_NORMAL_MAP.getProjection(), "Satellite", opts));
        map_types.push(new GMapType([tileTer], G_NORMAL_MAP.getProjection(), "Terrain", opts));

        //Init gmap object with custom map types
        var gmap_opts = { backgroundColor: '#FFFFFF', mapTypes: map_types };
        cosgis.map = new GMap2(document.getElementById("map"), gmap_opts);

        //Customize gmap object
        var customUI = cosgis.map.getDefaultUI();
        customUI.controls.scalecontrol = true; //Scale
        customUI.controls.largemapcontrol3d = true; //Zoom
        customUI.controls.maptypecontrol = false; //Default map type control
        customUI.controls.menumaptypecontrol = true; //Menu map type control
        customUI.zoom.scrollwheel = true;  //Scroll zoom
        cosgis.map.setUI(customUI);

        //Remove google map tiles
        removeDefaultMaps();

        //Create MapExtension utility class
        cosgis.map_extension = new esri.arcgis.gmaps.MapExtension(cosgis.map);

        //Geocoder
        cosgis.geocoder = new GClientGeocoder();

        //Streetview client
        cosgis.sv_client = new GStreetviewClient();

        //Add dynamic maps
        addDynamicMap(cosgis.dynamic_url);

        //Set up Identify
        GEvent.addListener(cosgis.map, "click", function(overlay, point) {
            if (getFormData("mapTool") == "Identify")
                doIdentify(overlay, point);
            if (getFormData("mapTool") == "StreetView")
                cosgis.sv_client.getNearestPanorama(point, showPanoData);
        });
        //Update TOC scale dependent rendering
        GEvent.addListener(cosgis.map, "zoomend", function() {
            if (cosgis.toc != null) {
                cosgis.toc.UpdateScaleRendering();
            }
        });

        //Streetview panorama
        GEvent.addListener(cosgis.map, "infowindowbeforeclose", function() {
            if (cosgis.sv_pano != null) {
                cosgis.sv_pano.remove();
            }
        });

        //Setup resize event       
        if (window.attachEvent) {
            window.attachEvent("onresize", function() { resizeApp(); });
        } else {
            window.addEventListener("resize", function() { resizeApp(); }, false);
        }

        //Set Map Center
        var center = new GLatLng(cosgis.LAT, cosgis.LNG);
        cosgis.map.setCenter(center, 12);

        //Search
        loadWithSearch();

        //Turn off map loading notice
        toggleDiv("mapLoading", "off");
    }
}

function removeDefaultMaps() {
    cosgis.map.removeMapType(G_NORMAL_MAP);
    cosgis.map.removeMapType(G_HYBRID_MAP);
    cosgis.map.removeMapType(G_SATELLITE_MAP);
    cosgis.map.removeMapType(G_PHYSICAL_MAP);
}

//------------------------------------------------------------//
//--PRINT--//
//------------------------------------------------------------//
function printMap() {
    //location.href = "print.htm";
    printWin = window.open("print.htm", "_blank");
    printWin.map = cosgis.map;
    printWin.dynamic_map = cosgis.dynamic_map;
    printWin.dynamic_opacity = cosgis.dynamic_opacity;
    printWin.map_types = cosgis.map_types;
    printWin.map_tiles = cosgis.map_tiles;
    printWin.dynamic_service_url = cosgis.dynamic_service_url;
    printWin.toc = cosgis.toc;
    printWin.id_oids = cosgis.id_oids;
}

//------------------------------------------------------------//
//--MEASURE--//
//------------------------------------------------------------//
function enableMeasuring() {
    if (getFormData("mapTool") == "Measure") {
        cosgis.polyline && cosgis.polyline.disableEditing();
        cosgis.polyline && cosgis.map.removeOverlay(cosgis.polyline);

        cosgis.polyline = new GPolyline([], "#FF0000", 2, 1.0);
        cosgis.map.addOverlay(cosgis.polyline);

        GEvent.addListener(cosgis.polyline, "lineupdated", updateMeasure);
        cosgis.polyline.enableDrawing();

        toggleDiv("measureText", "on");
    } else {
        disableMeasuring();
    }
}

function updateMeasure() {
    var totalDist = roundNumber(cosgis.polyline.getLength() * 3.2808399, 2);
    var segDist = roundNumber(totalDist - cosgis.measure_dist, 2);
    var html = "Segment: " + segDist + "'&nbsp;&nbsp;&nbsp;&nbsp;Total: " + totalDist + "'";
    e("measureText").innerHTML = html;
    cosgis.measure_dist = totalDist;
}

function disableMeasuring() {
    cosgis.polyline && cosgis.polyline.disableEditing();
    cosgis.polyline && cosgis.map.removeOverlay(cosgis.polyline);
    toggleDiv("measureText", "off");
    e("measureText").innerHTML = "&nbsp;";
    cosgis.measure_dist = 0;
}


//------------------------------------------------------------//
//--IDENTIFY--//
//------------------------------------------------------------//
function doIdentify(overlay, point) {
    if (overlay) {
        return;
    }
    var layerid = cosgis.toc.GetLayerIDByName(cosgis.PARCEL_LAYER);
    cosgis.id_task = new esri.arcgis.gmaps.IdentifyTask(cosgis.dynamic_url);
    cosgis.id_point = point;
    var dim = cosgis.map.getSize();
    
    var idparams = new esri.arcgis.gmaps.IdentifyParameters();
    idparams.geometry = point;
    idparams.tolerance = 0;
    idparams.bounds = cosgis.map.getBounds();
    idparams.width = dim.width;
    idparams.height = dim.height;
    idparams.layerIds = [layerid];
    idparams.layerOption = "all";
    idparams.returnGeometry = true;
    
    cosgis.id_task.execute(idparams, idCallBack);
}

function idCallBack(idresults) {
    if (typeof (idresults.identifyResults[0]) != 'undefined') {
        var fieldName = idresults.identifyResults[0].displayFieldName;
        var fieldAttr = idresults.identifyResults[0].feature.attributes[fieldName];
        var attributes = idresults.identifyResults[0].feature.attributes;

        //Info window
        var html = "<div id=\"divResultsWindow\">";
        html += "<h3>Tax Parcel:</h3>";
        html += "<br>";
        html += "<table border=\"0\" cellspacing=\"2\">";
        var cnt = 0;

        //Save OID
        cosgis.id_oids.push(attributes["OBJECTID"]);

        //Jurisdiction
        var jur = attributes["Jurisdiction"];
       
        for (fld in cosgis.PARCEL_FIELD_LIST) {
            //alternate row color
            var cls = "tabCell1";
            if (cnt % 2) { cls = "tabCell2"; }
            
            //Write html
            switch (cosgis.PARCEL_FIELD_LIST[fld]) {
                case "Zoning":
                    if (jur == "City of Spokane")
                        html += "<tr class=\"" + cls + "\"><td>" + cosgis.PARCEL_FIELD_LIST[fld] + ":</td><td><a href=\"" + cosgis.ZONING_LINK + "\" target=\"_blank\" >" + attributes[cosgis.PARCEL_FIELD_LIST[fld]] + "</a></td>";
                    else
                        html += "<tr class=\"" + cls + "\"><td>" + cosgis.PARCEL_FIELD_LIST[fld] + ":</td><td>Unknown</td>";
                    break;
                case "Parcel Number":
                    var pidval = attributes[cosgis.PARCEL_FIELD_LIST[fld]];
                    html += "<tr class=\"" + cls + "\"><td>" + cosgis.PARCEL_FIELD_LIST[fld] + ":</td><td><a href=\"" + cosgis.ASSESSOR_LINK + pidval + "\" target=\"_blank\" >" + pidval + "</a></td>";
                    break;
                default:
                    html += "<tr class=\"" + cls + "\"><td>" + cosgis.PARCEL_FIELD_LIST[fld] + ":</td><td>" + attributes[cosgis.PARCEL_FIELD_LIST[fld]] + "</td>";
            }
                        
            cnt++;
        }
        html += "</table>";
        html += "</div>";

        //options
        var infoWindowOptions = {
            content: html,
            maxWidth: 250
        };

        //Add to map
        var ov = cosgis.map_extension.addToMap(idresults, null, infoWindowOptions);

        //Trigger click
        GEvent.trigger(ov[0][0], 'click', cosgis.id_point);
        //note - needs fix - also affects zoomIndentify
        cosgis.id_overlays.push(ov);

        //Track overlays
        var ovid;
        for (var x = 0; x < ov.length; x++) {
            ovid = cosgis.id_overlays.push(ov[x]);
        }

        //Write results to left content
        writeIdResults(idresults.identifyResults[0], ovid - 1);
    }
}

function zoomIdentify(lat, lng, id) {
    var pt = new GLatLng(lat, lng);
    cosgis.map.setCenter(pt);
    GEvent.trigger(cosgis.id_overlays[id][0], 'click', pt);
}

function clearIdentifyOverlays() {
    for (var x = 0; x < cosgis.id_overlays.length; x++) {
        cosgis.map_extension.removeFromMap(cosgis.id_overlays[x]);
    }
    cosgis.id_overlays = [];
    cosgis.map.closeInfoWindow();
    cosgis.result_tables = [];
}

function writeIdResults(results, id) {
    var attributes = results.feature.attributes;
    var displayFieldName = results.displayFieldName;
    var displayFieldAttribute = results.feature.attributes[displayFieldName];

    setNavTab('Results');

    var e_div = e("divSelect");
    var e_ul = e("ulSelect");

    if (e_div.style.display == 'none')
        e_div.style.display = '';

    collapseResultTables();

    var uid = GetID();
    var tblid = "tbl" + uid.toString();
    var imgid = "img" + uid.toString();
    cosgis.result_tables.push(uid);

    var html = "<li class='liResults'>";
    html += "<img id=\"" + imgid + "\" class=\"plus\" src=\"" + cosgis.TOC_IMAGE_PLUS + "\" onclick=\"toggleResults(this,'" + tblid + "');\" />";
    html += "<a href=\"javascript:zoomIdentify(" + cosgis.id_point.lat() + ", " + cosgis.id_point.lng() + ", " + id + "); \"><span>" + displayFieldAttribute + "</span></a>";
    html += "<table id=\"" + tblid + "\" border=\"0\" cellspacing=\"1\" width=\"100%\" style=\"display:none\">";
    var cnt = 0;

    //Jurisdiction
    var jur = attributes["Jurisdiction"];

    for (fldName in attributes) {
        if (fldName != "Shape" && fldName != "OBJECTID") {
            var cls = "tabCell1";
            if (cnt % 2) { cls = "tabCell2"; }
            html += "<tr class=\"" + cls + "\">";

            switch (fldName) {
                case "Zoning":
                    if (jur == "City of Spokane")
                        html += "<td>" + fldName + "</td><td><a href=\"" + cosgis.ZONING_LINK + "\" target=\"_blank\" >" + attributes[fldName] + "</a></td>";
                    else
                        html += "<td>" + fldName + "</td><td>Unknown</td>";
                    break;
                case "Parcel Number":
                    var pidval = attributes[fldName];
                    html += "<td>" + fldName + "</td><td><a href=\"" + cosgis.ASSESSOR_LINK + pidval + "\" target=\"_blank\" >" + pidval + "</a></td>";
                    break;
                default:
                    html += "<td>" + fldName + "</td><td>" + attributes[fldName] + "</td>";
            }

            html += "</tr>";
            cnt++;
        }
    }

    html += "</table>";
    html += "</li>";

    e_ul.innerHTML += html;
}

//------------------------------------------------------------//
//---AJAX---//
//------------------------------------------------------------//
function getXmlHttpRequestObject() {
    if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        return new ActiveXObject("Microsoft.XMLHTTP");
    } else {
        alert("This function is not supported by your browser");
    }
}

//------------------------------------------------------------//
//---TOC---//
//------------------------------------------------------------//
//Get json toc data
function getTOC() {
    cosgis.ajax_toc = getXmlHttpRequestObject();
    if (cosgis.ajax_toc.readyState == 4 || cosgis.ajax_toc.readyState == 0) {
        if (cosgis.include_layers.length > 0) {
            cosgis.ajax_toc.open("GET", 'toc.ashx?url=' + cosgis.dynamic_service_url + '&include=' + cosgis.include_layers.join(), true);
        } else {
            cosgis.ajax_toc.open("GET", 'toc.ashx?url=' + cosgis.dynamic_service_url, true);
        }
        cosgis.ajax_toc.onreadystatechange = parseTOCData;
        cosgis.ajax_toc.send(null);
    }
}

//Build the toc
function parseTOCData() {
    if (cosgis.ajax_toc.readyState == 4) {
        if (cosgis.ajax_toc.responseText.length > 0) {
            var layers = eval('(' + cosgis.ajax_toc.responseText + ')');
            cosgis.toc = new TOC(layers, "divLayers", "tocSpokane", cosgis.dynamic_map, cosgis.dynamic_service_url, cosgis.dynamic_opacity);
            cosgis.toc.BuildLayerList();
        }
        cosgis.ajax_toc = null;
    }
}

//------------------------------------------------------------//
//--SUGGEST SEARCH--//
//------------------------------------------------------------//
//Starts the search request.
function searchSuggest() {
    clearTimeout(cosgis.search_time);
    cosgis.search_time = setTimeout(function() {
        cosgis.ajax_search = getXmlHttpRequestObject();
        var typ = escape(e('sTab').value);
        if (cosgis.ajax_search.readyState == 4 || cosgis.ajax_search.readyState == 0) {
            var str = escape(e('txtSearch').value);
            if (str.length > 0) {
                cosgis.ajax_search.open("GET", 'search.ashx?val=' + str + '&typ=' + typ + '&mth=Suggest', true);
                cosgis.ajax_search.onreadystatechange = handleSearchSuggest;
                cosgis.ajax_search.send(null);
            } else {
                toggleDiv("search_suggest", "off");
            }
        }
    }, 250);
}

//Called when the AJAX response is returned.
function handleSearchSuggest() {
    if (cosgis.ajax_search.readyState == 4) {
        var ss = e('search_suggest')
        ss.innerHTML = '';
        if (cosgis.ajax_search.responseText.length > 0) {
            toggleDiv("search_suggest", "on");
            ss.innerHTML = cosgis.ajax_search.responseText;
        } else {
            toggleDiv("search_suggest", "off");
        }
        cosgis.ajax_search = null;
    }
}

//Mouse over function
function suggestOver(div_value) {
    div_value.className = 'suggest_link_over';
}

//Mouse out function
function suggestOut(div_value) {
    div_value.className = 'suggest_link';
}

//Close suggest div
document.onclick = check;
function check(e) {
    var target = (e && e.target) || (event && event.srcElement);
    var obj = document.getElementById('search_suggest');
    if (target != obj) { obj.style.display = 'none' }
}

//Find search value (click function)
function findSearchItem(value) {
    //document.getElementById('txtSearch').value = value.toString().replace("&amp;", "&");
    document.getElementById('search_suggest').innerHTML = '';
    toggleDiv("search_suggest", "off");
    var str = escape(document.getElementById('txtSearch').value);
    var typ = escape(document.getElementById('sTab').value);
    executeSearch(value, typ, true);
}

//Execute the search
function executeSearch(sterm, stype, isnew) {
    cosgis.search_new = isnew;

    switch (stype) {
        case "Parcel":
        case "Owner":
            setSearchTab(stype);
            e('txtSearch').value = sterm;
            var urlSearch = 'search.ashx?val=' + sterm + '&typ=' + stype + '&mth=Find';
            GDownloadUrl(urlSearch, function(data) {
                if (data.length > 1) {
                    var results = eval('(' + data + ')');
                    setNavTab("Results");
                    addMarker(new GLatLng(results[0].lat, results[0].lng), results[0].html);
                    if (isnew)
                        writeResults("divParcelSearch", "ulParcelSearch", stype);
                }
            });
            break;
        case "Address":
            setSearchTab(stype);
            e('txtSearch').value = sterm;
            var urlSearch = 'search.ashx?val=' + sterm + '&typ=' + stype + '&mth=Find';
            GDownloadUrl(urlSearch, function(data) {
                if (data.length > 1) {
                    var results = eval('(' + data + ')');
                    setNavTab("Results");
                    addMarker(new GLatLng(results[0].lat, results[0].lng), results[0].html);
                    if (cosgis.search_new)
                        writeResults("divAddressSearch", "ulAddressSearch", stype);
                } else {
                    geocodeAddress(sterm);
                }
            });
            break;
    }
}

//Querystring search
//ex. http://10.1.7.34/citymap2/default.htm?search=Address&val=808%20W%20Spokane%20Falls%20Blvd
//ex. http://10.1.7.34/citymap2/default.htm?search=Parcel&val=35183.1501
function loadWithSearch() {
    var search = getQuery("search");
    var val = getQuery("val");
    if (search == "Address") {
        executeSearch(unescape(val), 'Address', true);
    }
    if (search == "Parcel") {
        executeSearch(val, 'Parcel', true);
    }
}


//------------------------------------------------------------//
//--RESULTS--//
//------------------------------------------------------------//
function writeResults(divid, ulid, stype) {
    setNavTab('Results');

    var e_div = e(divid);
    var e_ul = e(ulid);

    if (e_div.style.display == 'none')
        e_div.style.display = '';

    var uid = GetID();
    var liid = "li" + uid.toString();

    var html = "<li id=\"" + liid + "\" class='liResults'>";
    html += "<a href=\"javascript:executeSearch('" + e("txtSearch").value + "','" + stype + "', false)\"><span>" + e("txtSearch").value + "</span></a>";
    html += "</li>";

    e_ul.innerHTML += html;
}

//------------------------------------------------------------//
//--DOM NODES--//
//------------------------------------------------------------//
function removeAllChildNodes(obj) {
    if (obj.hasChildNodes()) {
        while (obj.childNodes.length >= 1) {
            obj.removeChild(obj.firstChild);
        }
    }
}

function clearSearchNodes(objName) {
    var element = e(objName);
    if (element.hasChildNodes()) {
        for (node in element.childNodes) {
            if (element.childNodes[node].tagName == 'UL') {
                removeAllChildNodes(element.childNodes[node]);
            }
        }
    }
    element.style.display = "none";
}

function changeOpacity(element, op) {
    if (element.hasChildNodes()) {
        var child = element.childNodes;
        for (var i = 0; i < child.length; i++) {
            if (child[i].tagName == 'IMG' && child[i].id.toString().search(/legend/) != -1) {
                child[i].style.opacity = op;
                //child[i].filters.alpha.opacity = parseInt(op * 100);
            }
            //Recurse
            if (child[i].hasChildNodes()) {
                var child1 = child[i];
                changeOpacity(child1, op);
            }
        }
    }
}

//------------------------------------------------------------//
//---TABS---//
//------------------------------------------------------------//
//Set up search tabs
function setSearchTab(objName) {
    //Save Input Box Data
    var formTabVal = e("sTab").value;
    var formSearchData = e("txtSearch").value;
    saveFormData(formTabVal, formSearchData);

    //Get Stored Data 
    var tab = e(objName);
    if (tab.className != 'selected') {
        e("sTab").value = objName;
        e("txtSearch").value = getFormData(objName);
    }

    //Set Active Tab (Inactivate Others) 
    e("Address").className = '';
    e("Owner").className = '';
    e("Parcel").className = '';
    tab.className = 'selected';
}

//Set up nav tabs
function setNavTab(objName) {
    var obj = e(objName);
    var leftElem = e("leftColumn");
    if (leftElem.style.display != 'block' && leftElem.style.display != '') { hideShowLeft(); }
    e("Layers").className = '';
    e("Results").className = '';
    obj.className = 'selected';
    saveFormData("NavTab", obj.id);

    if (obj.id == "Results") {
        toggleDiv("leftLayers", "off");
        toggleDiv("leftResults", "on");
    }
    if (obj.id == "Layers") {
        toggleDiv("leftResults", "off");
        toggleDiv("leftLayers", "on");
    }
}

//------------------------------------------------------------//
//--GENERAL PAGE FUNCTIONS--//
//------------------------------------------------------------//
//Resizes map
function resizeApp() {
    var offsetTop = 0;
    var mapElem = e("map");
    var leftElem = e("leftColumn");

    for (var elem = mapElem; elem != null; elem = elem.offsetParent) {
        offsetTop += elem.offsetTop;
    }

    var height = getWindowHeight() - offsetTop - 10;
    if (height >= 0) {
        mapElem.style.height = height - 0 + "px";
        leftElem.style.height = height + "px";
    }

    if (cosgis.map) {
        cosgis.map.checkResize();
        cosgis.dynamic_map.refresh();
    }

}

//Get Height
function getWindowHeight() {
    if (window.self && self.innerHeight) {
        return self.innerHeight;
    }
    if (document.documentElement && document.documentElement.clientHeight) {
        return document.documentElement.clientHeight;
    }
    return 0;
}

//Get Element ID
function e(id) { return document.getElementById(id); }

//Hide/Show left column
function hideShowLeft() {
    var leftElem = e("leftColumn");
    var mapElem = e("map");
    var mapColElem = e("mapColumn");
    var hsElem = e("imghs");
    var li2Elem = e("Layers");
    var li3Elem = e("Results");

    if (leftElem.style.display == "none") {
        leftElem.style.display = "block";
        mapElem.style.marginLeft = "0px";
        mapColElem.style.width = "70%";
        hsElem.src = "_images/hs_hide2.gif";
        hsElem.title = "Hide Table of Contents";
        e(getFormData("NavTab")).className = 'selected';
    } else {
        leftElem.style.display = "none";
        mapElem.style.marginLeft = "0px";
        mapColElem.style.width = "100%";
        hsElem.src = "_images/hs_show2.gif";
        hsElem.title = "Show Table of Contents";
        li2Elem.className = "";
        li3Elem.className = "";
    }
    resizeApp();
}

//Parse Query String
function getQuery(variable) {
    //var query = qstr;
    var query = window.location.search.substring(1); 
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
            return pair[1];
        }
    }
}

//Get Unique ID
function GetID() {
    var dt = new Date();
    return dt.getTime();
}

//Save Key Value Pairs
function saveFormData(key, val) {
    cosgis.form_data[key] = val;
}
function getFormData(key) {
    var val = cosgis.form_data[key];
    if (typeof (val) == 'undefined') { val = ''; }
    return val;
}

//Toggle Div on/off
function toggleDiv(divID, display) {
    var divElem = e(divID);
    if (display == "off") {
        if (divElem.style.display != "none")
            divElem.style.display = "none";
    }
    if (display == "on") {
        if (divElem.style.display != "block")
            divElem.style.display = "block";
    }
}

//Toggle display
function toggleDisplay(id) {
    var element = e(id);
    if (element.style.display == 'none') {
        element.style.display = '';
    } else {
        element.style.display = 'none'
    }
}

//Toggle results
function toggleResults(imgElement, id) {
    if (imgElement.className == 'plus') {
        imgElement.src = cosgis.TOC_IMAGE_MINUS;
        imgElement.className = 'minus';
    } else {
        imgElement.src = cosgis.TOC_IMAGE_PLUS;
        imgElement.className = 'plus';
    }
    toggleDisplay(id);
}

function collapseResultTables() {
    for (var i = 0; i < cosgis.result_tables.length; i++) {
        var imgElement = e("img" + cosgis.result_tables[i]);
        var tblElement = e("tbl" + cosgis.result_tables[i]);
        if (imgElement != null) {
            imgElement.src = cosgis.TOC_IMAGE_PLUS;
            imgElement.className = 'plus';
        }
        if (tblElement != null) {
            tblElement.style.display = 'none'
        }
    }
}

function getRandomNumber() {
    return Math.floor(Math.random() * 11);
}

function roundNumber(num, dec) {
    var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
    return result;
}

//------------------------------------------------------------//
//---MAP TOOLS---//
//------------------------------------------------------------//
//Toggle tools on/off
function activateTool(tool) {    
    e('Identify').className = '';
    e('Measure').className = '';
    e('StreetView').className = '';
    if (getFormData("mapTool") == tool) {
        //turn off
        saveFormData("mapTool", "");
        e(tool).className = '';
    } else {
        //turn on
        e(tool).className = 'selected';
        saveFormData("mapTool", tool);
    }

    enableMeasuring();
    enableStreetView();
}

function clearMap() {
    //measure polylines
    disableMeasuring();
    //Results
    clearSearchNodes('divParcelSearch');
    clearSearchNodes('divAddressSearch');
    clearSearchNodes('divSelect');
    //ID overlays
    clearIdentifyOverlays();
    //Markers
    removeMarker();
}

//Street View
function enableStreetView() {
    if (getFormData("mapTool") == "StreetView") {
        if (cosgis.sv_overlay == null) {
            cosgis.sv_overlay = new GStreetviewOverlay();
            cosgis.map.addOverlay(cosgis.sv_overlay);
        }
    } else {
        disableStreetView();
    }
}

function disableStreetView() {
    if (cosgis.sv_overlay != null) {
        cosgis.map.removeOverlay(cosgis.sv_overlay);
        cosgis.map.closeInfoWindow();
        cosgis.sv_overlay = null;
    }
}

function showPanoData(panoData) {
    if (panoData.code != 200) {
        return;
    }
    var html = "<div id='panDiv' style='width:500px; height:350px; margin:10px;'></div>";
    var pov = { yaw: 370.64659986187695, pitch: -20 };
    
    cosgis.map.openInfoWindowHtml(panoData.location.latlng, html);

    setTimeout(function() {
        var panDiv = e("panDiv");
        cosgis.sv_pano = new GStreetviewPanorama(panDiv);
        cosgis.sv_pano.setLocationAndPOV(panoData.location.latlng, pov);
    }, 1000);
}

function handleNoFlash(errorCode) {
    if (errorCode == 603) {
        alert("Error: Flash not installed or not supported by your browser");
        return;
    }
}


//
//Get initial layers from query string
function getQueryLayers() {
    var layersQS = getQuery("layers");
    var vis = [];
    if (typeof (layersQS) != 'undefined') {
        var layers = layersQS.split(',');
        for (lyr in layers) {
            var layer = layers[lyr];
            vis.push(layer);
        }
    }
    return vis;
}

