﻿
// global variables
var map;
var geocoder;
var directions;
var infoHtmls;
var countResults = 0;


// jump to function load() when the document is ready to be manipulated.
$(document).ready(load);


// Cleanup to prevent memory leaks (IE specific)
$(window).unload(function() {
    GUnload();
});

var selectedState = false;
var selectedPosition = 0;

function load() {
    // begin load()
    $("#formSearchPorscheCenter").submit(function() {
        initMap();
        return false;
    });

    // move states overlay immediately into parent element "div#wrapper"
    $("#states_imagemap").remove().appendTo("#wrapper");

    // Change text color for default text when input gets focus, and return to
    // normal color on focus lost. ("Enter search term here..", bla)

    $("#searchInput").focus(function() {
        if (this.value == this.defaultValue) {
            this.value = "";
            this.style.color = '#000';
        }
    }).blur(function() {
        if (!this.value.length) {
            this.value = this.defaultValue;
            this.style.color = '#999999';
        }
    }).keyup(function() {
        $("select.stateDropdown").attr("selectedIndex", 0); // reset dropdowns.
    });

    // "OnChange" event handling for the states dropdown.
    $("select.stateDropdown").change(function() {
        selectedState = $('option[selected]', this).val();

        if (selectedState != 0) {
            // highlight the first option field (e.g. "Choose state")
            $(this).css("color", "#000");

            // reset any _other_ dropdowns (so that their selected value becomes invalid).
            // and paint them gray (-> disabled)
            $("select.stateDropdown[class!='" + this.className + "']").attr("selectedIndex", 0).css("color", "#999"); ;

            // set default input field text
            var searchInput = $("#searchInput")[0];
            if (searchInput.value != searchInput.defaultValue) {
                searchInput.value = searchInput.defaultValue;
                searchInput.style.color = '#999999';
            }

            initMap();
        }
        else {
            $(this).css("color", "#999");
        }
    }); // function load


    if (GBrowserIsCompatible()) {

        // Create a new map type incorporating the tile layer
        map = new GMap2($("#map_canvas")[0], { mapTypes: [G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP] });
        // see mapTypes: declaration in the GMap2 init routine above.
        map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());

        // set centerpoint
        //(parameters for each market: boundary, zoom level)

        var mapCenterPoint = new GLatLng(UI_MAP_DEFAULTCOORDS_LAT, UI_MAP_DEFAULTCOORDS_LNG); // TODO Use GLatLngBounds instead (requires two GLatLng points)

        // Mouse wheel zoom in/out
        map.enableScrollWheelZoom();

        // set map mode
        map.setMapType(UI_MAP_DEFAULTMAPTYPE);
        
        // set minimum zoom level
        var mt = map.getMapTypes();
        for (var i = 0; i < mt.length; i++) {
            mt[i].getMinimumResolution = function() { return UI_MAP_DEFAULTCOORDS_MINZOOMLEVEL; }
        }

        geocoder = new GClientGeocoder();
        geocoder.setBaseCountryCode(GLOBAL_CCTLD);

        // setup Directions ("calculate route")
        directions = new GDirections();
        GEvent.addListener(directions, "error", onDirectionsError);
        GEvent.addListener(directions, "load", function() {
            onDirectionsLoad();
        });

        /* Jump to direct search */
        // check if there is a direct search (e.g. location.aspx?locationId=123456)
        var hiddenLocationId = $("#searchPorscheCenter form input[name$='hiddenLocationId']").val();
        var hiddenLocationType = $("#searchPorscheCenter form input[name$='hiddenLocationType']").val();
        if (hiddenLocationId != undefined && hiddenLocationId != '') {
            //showSingleLocation(hiddenLocationId, hiddenLocationType);
            showSingleSite(hiddenLocationId, hiddenLocationType);
        }
        else {
            // external search (we came here from the market homepage)
            if (typeof(GLOBAL_SEARCHKEY) != 'undefined') {
                doExternalSearch(GLOBAL_SEARCHKEY);
            }
            else {
                // center map into default position
                map.setCenter(mapCenterPoint, UI_MAP_DEFAULTCOORDS_ZOOMLEVEL);
            }
        }
        

    }
}

function doExternalSearch(key) {
    log("doExternalSearch, key: " + key);
    $('#searchInput').focus().val(unescape(key));
    $('#searchButton').click();
}

function initMap() {
    // set mouse cursor to sandbox etc.
    // IMPORTANT: initMap() calls functions which have callbacks with delays,
    // so we call toggleSearch(false) not here, but at the appropriate position
    // in these callbacks, which is mostly, the end.    
    toggleSearch(true);
    

    // clear results
    showResultMessage('');

    // fade the states map overlay out.
    $("#states_imagemap").fadeOut(UI_STATESOVERLAY_FADEOUT_TIME);
    
    if (selectedState) {
        // State selected, skip keyword search.
        showStateDealers();
    }
    else {
        // reset states dropdown 
        $("select.stateDropdown").attr("selectedIndex", 0);
        
        // read input value (address).
        var address = $("#searchInput").val();

        // check if the entered value is a postcode.

        if (GLOBAL_POSTCODE_REGEX_ACTIVE) {
            if (isPostCode(address, GLOBAL_POSTCODE_REGEX_TESTSTRING, GLOBAL_POSTCODE_REGEX_OPTIONSSTRING))
                showDealerByPostCode(address);
            else {
                showResultMessage(UI_STRINGCONST_NORESULTSFOUND);
                $("#directions").hide(300);
                $("#results").show(300);
                toggleSearch(false);
            }
        }
        else {
            if (GLOBAL_PROXIMITY_SEARCH_ACTIVE)
                if (geocoder && address.length && address.length > 0) { geocoder.getLocations(address + ' ' + GLOBAL_CCTLD, addAddressesToMap); }
        }
    }
}

function isPostCode(str, regexString, regexOptions) {

    var testRegex = new RegExp(regexString, regexOptions);
    return testRegex.test(str);
}


// shows the porsche centres within the borders of a state/Bundesland.
// we are here because the user has chosen item from the dropdown.
// the variable selectedState is a global one.
function showStateDealers() {
    var searchurl = "";
    var searchmode = ""; //2define special errormessage in regionsearch 
    if ($("select[class='stateDropdown dealer']").attr("selectedIndex") != undefined && $("select[class='stateDropdown dealer']").attr("selectedIndex") != 0) {
    searchurl = APPPATH
                + "/search.aspx?siteid=" + GLOBAL_POOL
                + "&market=" + GLOBAL_MARKET
                + "&language=" + GLOBAL_LANGUAGE
                + "&mode=location"
                + "&locationtype=centre"
                + "&locationid=" + escape(selectedState);
    }
    else if ($("select[class='stateDropdown state']").attr("selectedIndex") != undefined && $("select[class='stateDropdown state']").attr("selectedIndex") != 0) {
    searchurl = APPPATH
                + "/search.aspx?siteid=" + GLOBAL_POOL
                + "&market=" + GLOBAL_MARKET
                + "&language=" + GLOBAL_LANGUAGE
                + "&mode=state"
                + "&locationtype=centre"
                + "&locationid=" + escape(selectedState);
    searchmode = 'state';
}
    else if ($("select[class='stateDropdown city']").attr("selectedIndex") != undefined && $("select[class='stateDropdown city']").attr("selectedIndex") != 0) {
    searchurl = APPPATH 
                + "/search.aspx?siteid=" + GLOBAL_POOL
                + "&market=" + GLOBAL_MARKET
                + "&language=" + GLOBAL_LANGUAGE
                + "&mode=city"
                + "&locationtype=centre"
                + "&locationid=" + escape(selectedState);
}

    //alert($("select[class='stateDropdown dealer']") + ' ' + $("select[class='stateDropdown dealer']").attr("selectedIndex"));
    $("#results").load(searchurl + " #resultData", "", function() {
        showDealersOnMap(searchmode);
    });
    
    selectedState = false; // reset selected state variable.

}

function showDealerByPostCode(postcode) {
    var searchurl = APPPATH 
                + "/search.aspx?siteid=" + GLOBAL_POOL
                + "&market=" + GLOBAL_MARKET
                + "&language=" + GLOBAL_LANGUAGE
                + "&mode=postcode"
                + "&locationtype=centre"
                + "&postcode=" + escape(postcode);
    $("#results").load(searchurl + " #resultData", "", function() {
        showDealersOnMap();
    });                        
}


function showSingleSite(locationId, locationType) {
    
    log("Entering showSingleSite()");
    log("locationId: " + locationId);
    log("locationType: " + locationType);
    var searchurl = APPPATH
                + "/search.aspx?siteid=" + GLOBAL_POOL
                + "&market=" + GLOBAL_MARKET
                + "&language=" + GLOBAL_LANGUAGE
                + "&mode=location"
                + "&locationtype=" + locationType
                + "&locationid=" + locationId;
    $("#results").load(searchurl + " #resultData", "", function() {
        showDealersOnMap();
    });                        
}


function addAddressesToMap(response) {
    if (!response || response.Status.code != 200) {
        showResultMessage(UI_STRINGCONST_NORESULTSFOUND);
        toggleSearch(false);
    } else {

    // take the first result
        place = response.Placemark[0];
        point = new GLatLng(place.Point.coordinates[1],
                            place.Point.coordinates[0]);

        //proximity search (centered around point.lat() and point.lng()
        // the reason why this is here, is because the google internal search function
        // redirects the result into a callback function, which is this one.
        
        // build query URL
        var searchurl = APPPATH
                + "/search.aspx?siteid=" + GLOBAL_POOL
                + "&market=" + GLOBAL_MARKET
                + "&language=" + GLOBAL_LANGUAGE
                + "&locationtype=centre"
                + "&mode=proximity"
                + "&lat=" + point.lat()
                + "&lng=" + point.lng();
        // fire ajax search
        $("#results").load(searchurl + " #resultData", "", function() {
            showDealersOnMap();
        });
    }
}


function showDealersOnMap(searchmode) {
    // reset selected position
    selectedPosition = 0; 
    
    // turn off search mode.
    toggleSearch(false);
    $("#directions").hide(300);
    $("#results").show(300);

    // handle mouse over icon on li's
    $('#results ul li').hover(
        function() {
            $(this).css('cursor', 'pointer');
            highlight($(this).prevAll().length + 1);
        },
        function() {
            $(this).css('cursor', 'default');
            highlight($(this).prevAll().length + 1, true);
        }
    );

    
    map.clearOverlays();
    // anonymous function to deal with the resulting data
    // from perimeter search in the database.
    var dealersNodeSet = $("dealer", "#dealerNonHTML");
    if (dealersNodeSet.length == 0) {
        if (searchmode == 'state') {
            showResultMessage(UI_STRINGCONST_NORESULTSFOUND_REGION);
        }
        else {
            showResultMessage(UI_STRINGCONST_NORESULTSFOUND);
        }
    }
    else {
        countResults = dealersNodeSet.length;
        var points = new Array();
        infoHtmls = $("#dealerInFoWindowData div.markerInfoWindow");

        for (var i = 0; i < countResults; i++) {
            points[i] = getDealerLatLng(i);
        }
        if (UI_MAP_DEFAULTCOORDS_MAXZOOMLEVEL && UI_MAP_DEFAULTCOORDS_MAXZOOMLEVEL > 0)
            fitMap(map, points, true, UI_MAP_DEFAULTCOORDS_MAXZOOMLEVEL);
        else
            fitMap(map, points, true);

        installMarkers(map, points, infoHtmls);

        // show the info window directly if there is an exact hit.
        if (countResults == 1) {
            gotoPorscheCenter(1, points[0].lat(), points[0].lng());
        }
    }
    toggleSearch(false);
}

function handleStateMapClick(stateCode, regiontype) {
    var idx = 0;
    var increment = true;
    $("select[class='stateDropdown " + regiontype + "'] option").each(function() {
        if (this.value == stateCode) {
            increment = false;
        }
        if (increment) idx += 1;
    });

    $("select[class='stateDropdown " + regiontype + "']").attr("selectedIndex", idx).change();
   
    
}


function installMarkers(map, points, infoHtmls) {

    var point;
    var marker;
    for (var i = 0; i < points.length; i++) {
        marker = createMarker(points[i], i, $(infoHtmls[i]).html());
        map.addOverlay(marker);
    }
}

function createMarker(point, number, html) {
    // Marker Setup
    var porscheIcon = new GIcon();
    porscheIcon.image = UI_MAPMARKERS_IMAGE;
    porscheIcon.shadow = false;
    porscheIcon.iconSize = new GSize(24, 30);
    porscheIcon.shadowSize = null;
    porscheIcon.iconAnchor = new GPoint(12, 30);
    porscheIcon.infoWindowAnchor = new GPoint(0, 20);

    markerOptions = { icon: porscheIcon };
    
    var marker = new GMarker(point, markerOptions);
    /* pixelOffset: Distance (x, y) of the info window from the current map point. 
       
       */
    var infoWindowoptions = UI_MAP_INFOWINDOWOPTIONS;
    marker.value = number;
    GEvent.addListener(marker, "click", function() {
        selectedPosition = number + 1;
        highlight(number+1);
        map.openInfoWindowHtml(point, html, infoWindowoptions);
    });
    return marker;
}


function fitMap(map, points, save, maxZoomLevel) {
    //log("UI_MAP_DEFAULTCOORDS_MAXZOOMLEVEL: " + UI_MAP_DEFAULTCOORDS_MAXZOOMLEVEL);
    // map bounds
    var bounds = new GLatLngBounds();
    var zoomLevel;
    for (var i = 0; i < points.length; i++) {
        bounds.extend(points[i]);
    }
    map.setCenter(bounds.getCenter());
    var calculatedZoomLevel = map.getBoundsZoomLevel(bounds);
    zoomLevel = (maxZoomLevel && maxZoomLevel < calculatedZoomLevel) ? maxZoomLevel : calculatedZoomLevel;
    //log("zoomLevel :" + zoomLevel);
    map.setZoom(zoomLevel);
    if (save) map.savePosition();
}


/*********************************************************************************************
    Neue Funktion zum intelligenten Zoomen und justieren des Viewports.
    Die Methode getMaxZoomAtLatLng ist in zwei Hinsichten noch ungeeignet:
    1. Es ist nur für die Satellit- und Hybridansichten verfügbar und nicht für die
    default eingesetzte normale Kartenansicht.
    2. Da es jedesmal eine Http-Anfrage an Google-Server geht verlangsamt sich das Ergebnis.
    Außerdem, weil diese eine zentrale Funktion ist muss es noch umfangreich getestet werden.
*********************************************************************************************/
function fitMapNew(map, points, save, maxZoomLevel) {
    var bounds = new GLatLngBounds();
    var zoomLevel;
    for (var i = 0; i < points.length; i++) {
        bounds.extend(points[i]);
    }
    var mapCenterPoint = bounds.getCenter();
    map.setCenter(mapCenterPoint);

    var googleMaxZoomLevel = false;
    map.getCurrentMapType().getMaxZoomAtLatLng(mapCenterPoint, function(response) {
        if (response && response.status == 200) {
            googleMaxZoomLevel = response.zoom;
        }
        var boundsZoomLevel = map.getBoundsZoomLevel(bounds);
        log("Google-MaxZoomLevel : " + googleMaxZoomLevel);

        // map's zoom vs. bounds' zoom
        if (googleMaxZoomLevel) {
            calculatedZoomLevel = Math.min(googleMaxZoomLevel, boundsZoomLevel);
        }
        else
            calculatedZoomLevel = boundsZoomLevel;

        // pool' global zoom vs. calculated zoom
        if (maxZoomLevel) {
            zoomLevel = Math.min(maxZoomLevel, calculatedZoomLevel);
        }
        else {
            zoomLevel = calculatedZoomLevel;
        }

        log("zoomLevel :" + zoomLevel);

        map.setZoom(zoomLevel);
        if (save) map.savePosition();
    });        
    
}


function getDealerLatLng(i) {
    var dealerNode = $("dealer", "#dealerNonHTML")[i];
    return new GLatLng(parseFloat($(dealerNode).attr("coords_lat")), parseFloat($(dealerNode).attr("coords_lng")));
}

function openDirections(toHere, pos) {
    var gLatLngDealer;

    $("#results").hide(300); // hide the results.
    // disable printing.
    $('#directionsPrintBtn, #directionsPrint')
        .css("cursor", "default")
        .fadeTo(1, 0.33)
        .unbind("click")
        .unbind("mouseover")
        .unbind("mouseout")
        .removeAttr('alt')
        .parent().parent().removeAttr("title")
        ;
    
       
    
    $("#directions_results").html("");
    $("#directions").show(300);

   
    var addressLine = $("#dealerInFoWindowData .markerInfoWindow:nth-child(" + pos + ") p.addresslineHidden:first").html();    
    gLatLngDealer = getDealerLatLng(pos - 1);

    if (toHere) {
        $("#directionsFrom").val("")[0].focus();
        $("#directionsTo").val(addressLine);
    }
    else {
        $("#directionsFrom").val(addressLine);
        $("#directionsTo").val("")[0].focus();
    }

    $("#formSearchDirections").submit(function() {
        toggleSearch(true);
        try {
            if (toHere) {
                directions.loadFromWaypoints(new Array($("#directionsFrom").val(), gLatLngDealer), UI_MAP_DIRECTIONOPTIONS);
            }
            else {
                directions.loadFromWaypoints(new Array(gLatLngDealer, $("#directionsTo").val()), UI_MAP_DIRECTIONOPTIONS);
            }
        }
        catch (ex) {
        }
        return false;
    });


    // Ende openDirections    
}



// Will run when GDirections loads succesfully and without errors,
// otherwise it will call to onDirectionsError()
function onDirectionsLoad() {
    // => statusCode = 200 (G_GEO_SUCCESS);

    /******************/
    /* setup map pane */
    /******************/
    map.clearOverlays();

    // setup polylines
    var poly = directions.getPolyline();
    map.addOverlay(poly);

    // fit and center map.
    var bounds = directions.getBounds();
    map.setCenter(bounds.getCenter());
    map.setZoom(map.getBoundsZoomLevel(bounds));

    // setup icons
    var baseIcon = new GIcon();
    baseIcon.shadow = UI_MAP_DIRECTIONS_SHADOWIMAGE;
    baseIcon.iconSize = new GSize(20, 20);
    baseIcon.shadowSize = new GSize(30,30);
    baseIcon.iconAnchor = new GPoint(10, 10);
    G_START_ICON = new GIcon(baseIcon);
    G_START_ICON.image = UI_MAP_DIRECTIONS_STARTIMAGE;
    G_END_ICON = new GIcon(baseIcon);
    G_END_ICON.image = UI_MAP_DIRECTIONS_ENDIMAGE;
    //G_PAUSE_ICON.image = UI_MAP_DIRECTIONS_PAUSEIMAGE;

    // plot start and end markers 
    map.addOverlay(new GMarker(poly.getVertex(0), G_START_ICON));
    map.addOverlay(new GMarker(poly.getVertex(poly.getVertexCount() - 1), G_END_ICON));

    // plot pause markers for any waypoints in between.
    // i < directions.getNumRoutes() - 1, because we do not add a pause for the last route.
    /*
    for (var i = 0; i < directions.getNumRoutes() - 1; i++) {
        var route = directions.getRoute(i);
        map.addOverlay(new GMarker(route.getEndLatLng(), G_PAUSE_ICON));
    }
    */

    /*********************/
    /* fill results pane */
    /*********************/

    //Summary

    var distMeters = directions.getDistance().meters; // distance in meters (integer);
    var distHtml = directions.getDistance().html; // string representation of distance / set by Google.

    var durSeconds = directions.getDuration().seconds; // duration in seconds (integer);
    var durHtml = directions.getDuration().html; // string representation of duration / set by Google.

    var results = $("#directions_results");
    var htmlResultSummary = UI_STRINGCONST_RESULTSUMMARY_1.replace(/\[ADDRESSLINE\]/, $("#directionsTo").val());
    htmlResultSummary += "<br/>\n";
    htmlResultSummary += UI_STRINGCONST_RESULTSUMMARY_2.replace(/\[DISTANCE\]/, distHtml).replace(/\[DURATION\]/, durHtml);

    $(results).html("<p class=\"summary\">" + htmlResultSummary + "</p>\n");

    $(results).append("<div class=\"resultWaypoint\">\n" +
                        "<img src=\"" + UI_DIRECTIONS_STARTIMAGE + "\" alt=\"\"/>\n" +
                        "<span>" + $("#directionsFrom").val() + "</span>" +
                        "<div class=\"clearfix\"></div>" + 
                        "</div>\n");

    //for (var i = 0; i < directions.getNumRoutes()-1; i++) {
    //var route = directions.getRoute(i);
    var route = directions.getRoute(0);


    var tableHtml = "<table>\n";
    for (var step = 0; step < route.getNumSteps(); step++) {
        currStep = route.getStep(step);
        var rowClass = (step == 0) ? " class=\"firstRow\"" : "";
        tableHtml += "<tr" + rowClass + ">\n" +
                        "<td>" + (step + 1) + ".</td>\n" +
                        "<td>" + currStep.getDescriptionHtml().replace(/\<b\>|\<\/b\>|/g, '') + "</td>\n" +
                        "<td class=\"distance\">" + currStep.getDistance().html + "</td>" + 
                      "</tr>\n";
    }
    tableHtml += "</table>\n";
    $(results).append(tableHtml);
    //}


    $(results).append("<div class=\"resultWaypoint\">\n" +
                    "  <img src=\"" + UI_DIRECTIONS_ENDIMAGE + "\" alt=\"\"/>\n" +
                    "  <span>" + $("#directionsTo").val() + "</span>" +
                    "  <div class=\"clearfix\"></div>" +
                    "</div>\n");

    var fromLatLng = route.getStep(0).getLatLng();
    var toLatLng = route.getEndLatLng();

    
    // enable printing.
    $('#directionsPrintBtn, #directionsPrint')
        .bind("mouseover", function() { $(this).css("cursor", "pointer") })
        .bind("mouseout", function() { $(this).css("cursor", "default") })
        .fadeTo("fast", 1.0)
        .bind("click", function() {
            try {
                console.log(fromLatLng.lng());
                console.log(toLatLng.lng());
                console.log($("#directionsFrom").val());
                console.log($("#directionsTo").val());
            }
            catch (e) {
            }
            var win = window.open(APPPATH
                        + "/direct.aspx?siteid=" + GLOBAL_POOL
                        + "&market=" + GLOBAL_MARKET
                        + "&language=" + GLOBAL_LANGUAGE
                        + "&fromText=" + $("#directionsFrom").val()
                        + "&toText=" + $("#directionsTo").val()
                        + "&fromLatLng=" + serializeLatLng(fromLatLng)
                        + "&toLatLng=" + serializeLatLng(toLatLng)
                        + "&actiontype=directions"
                        + "&print=1"
                        , "printPreview"
                        , "width=594,height=750,left=200,top=20,scrollbars=yes,resizable=yes");
        })
        .attr('alt', $("#lblPrint").text())
        .parent().parent().attr('title', $("#lblPrint").text() /*$('#directionsPrintBtn').attr('alt')*/)
        ;
       
        
    
    toggleSearch(false);

}

function onDirectionsError() {
    // Directions could not load because of some error (address wrong or ambigious)
    var errCode = directions.getStatus().code;
    $('#directions_results').html("<p class=\"error\">" + UI_STRINGCONST_NORESULTSFOUND + "</p>");
    toggleSearch(false);
}

function serializeLatLng(gLatLng) {
    var arrGLatLng = new Array();
    arrGLatLng[0] = gLatLng.lat();
    arrGLatLng[1] = gLatLng.lng();
    try {
        console.log(arrGLatLng.join(';'));
    }
    catch (e) {
    }
    return arrGLatLng.join(';');
        
}

function gotoPorscheCenter(position, lat, lng) {
    toggleCursor(true);    
    selectedPosition = position;
    highlight(position);
    var point = new GLatLng(lat, lng);
    var html = $(infoHtmls[position - 1]).html();
    map.openInfoWindowHtml(point, html, UI_MAP_INFOWINDOWOPTIONS);
    toggleCursor(false);
}

function highlight(position, bOff) {
    var i;
    for (i=1; i<=countResults; i++) {
        var elm = $("#resultData ul li:nth-child(" + i + ")")[0];
        if (position == i) {
            if (bOff && i != selectedPosition)
                $(elm).removeClass("hover");
            else
                $(elm).addClass("hover");
        }
        else {
            if (i != selectedPosition) {
                $(elm).removeClass("hover");
            }
        }
    }

}

function showResultMessage(msg) {
    $("#results").html("<p class=\"error\">" + msg + "</p>")
}

function hiliteAreaToggle(areaId, show) {
    if (show) {
        //showResultMessage(areaId + ": show");
        $("#state_over_" + areaId).show();
    }
    else {
        //showResultMessage(areaId + ": hide");
        $("#state_over_" + areaId).hide();
    }
}

// toggle Elements to indicate search or similar activity, 
// so that the user knows something's going on in the background.
function toggleSearch(searching) {
    toggleCursor(searching);
    if (searching) {
    }
    else {
        //alert($("#searchInput")[0] + " " + $("#directionsFrom")[0]);
        //alert(($("#searchInput").length > 0).toString() + ", " + ($("#searchInput").css("display") == 'block').toString());
        if ($("#searchInput").length > 0 && $("#searchInput").css("display") == 'block') {
            $("#searchInput")[0].focus();
        }
        else {
            //alert($("#directionsFrom").css("display") == 'block');
            if ($("#directions").css("display") == 'block'
                && $("#directionsFrom").length > 0
                && $("#directionsFrom").css("display") == 'block') {
                    $("#directionsFrom")[0].focus();
            }
        }
        
    }
}

// toggles mouse cursor icon between "progress" (sand clock) 
// and "pointer" (default)
function toggleCursor(on) {
    if (on) 
        document.body.style.cursor = 'progress';
    else 
        document.body.style.cursor = 'auto';
}

function openSite(refForm, sWidth, sHeight, sName, sUrl) {
    if (!sUrl) sUrl = "";
    var topOffset = 40;


    if (sHeight > (self.screen.availHeight + topOffset - 40)) {
        sHeight = self.screen.availHeight - 40;
        topOffset = 0;
    }
    newWin = window.open(sUrl, sName, "width=" + sWidth + ",height=" + sHeight + ",left=40,top=" + topOffset + ",scrollbars=yes,dependent=yes,location=no,resizable=yes,status=no");

    if (refForm) {
        refForm.target = sName;

    }

}

function log(str) {
    try { console.log(str); } catch (e) {}
}