﻿
//
//This file contains script that must accompany Default.aspx and most other map implementations. 
//Some of these methods are referenced by script emitted from RichmondMapDotNetVEBase.cs. Other methods handle 
//VE Template events and are required for normal map behaviors. 
//
//Most of the commented code remaining here is related to capabilities that are not included in the
//default map. These include: (1) 3D and Birdseye display, (2) inclusion of custom controls set 
//inside the map div, or (3) a collapsible sidebar that expands the map area. This code remains here 
//in case these capabilities are required by future applications.
//
//History:
//2008.09.30  Released version 1.0.
//2008.10.08  Added ChangeMapFile(). Renamed ChangeMap() to ChangeMapApp().
//



//
//VE TEMPLATE HANDLERS AND OVERRIDES
//

//flag to indicate whether there is a highlight shape after a page parameter query;
//highlight functionality is used exclusively of drilldown on page parameter
var hasPageParameterHighlightShape = false; 

//a timer and interval used by the MDNBrowserResizeWrapper and MDNBrowserResizeEvent methods
var mdnResizeTimer = null;
var mdnResizeTimerInterval = 250;

//magic map size values used by MDNBrowserResizeWrapper on load, browser resize, and sidebar toggle 
//var sidebarWidth = '260px'; 
var mapWidthOffsetWithSidebar = 278;//288; 
//var mapWidthOffsetWithoutSidebar = 27;// 25; 
var mapHeightOffset = 44;
var minMapHeight = 100;
var minMapWidth = 100;

//a flag to indicate whether the sidebar is visible
//var sidebarIsVisible = true;

//custom control sizes
//var customControlLeft = '7px';
//var customControlTop2D = 145;
//var customControlTop2DBird = 210;
//var customControlTop3D = 273;
//var customControlVerticalSpace = 24;

//Overrides the VE Template method so that MDNBrowserResizeWrapper() fires every time the page  
//resizes instead of just once during the initial load. This is wired in the markup for the body 
//element in the onresize attribute. A timer is used to delay the MDNBrowserResizeWrapper() call 
//by a fraction of a second. Applications with a fixed map size do not need this override. 
function MDNBrowserResizeEvent()
{
    if (mdnResizeTimer != null)
    {
        window.clearTimeout(mdnResizeTimer);
        mdnResizeTimer = null;
    }
    if(typeof(MDNBrowserResizeWrapper)!= 'undefined')
    {
        mdnResizeTimer = window.setTimeout('MDNBrowserResizeWrapper()', mdnResizeTimerInterval);
    }
}

//Sizes the map based appropriately for the browser window. Called by MDNBrowserResizeEvent() 
//when the browser has been resized. Commented code is included for applications that allow
//3D or Birdseye view, a collapsing sidebar, and/or custom controls in the map div.
function MDNBrowserResizeWrapper()
{
//    var uxMapTOC = document.getElementById('uxMapTOC');
//    var toolPanel = document.getElementById('uxToolPanel');
//    var logoImage = document.getElementById('logo');
//
//    //delete custom controls
//    DeleteCustomControls();
//
//    sidebarDiv = document.getElementById('sidebar');
//    if (sidebarIsVisible)
//    {
//        sidebarDiv.style.width = sidebarWidth; 
//        uxMapTOC.style.visibility = 'visible';
//        toolPanel.style.visibility = 'visible';
//        logoImage.style.visibility = 'visible';
//        w = MDNGetClientWidth() - mapWidthOffsetWithSidebar;
//    }
//    else
//    {
//        sidebarDiv.style.width = '0px';
//        uxMapTOC.style.visibility = 'hidden';
//        toolPanel.style.visibility = 'hidden';
//        logoImage.style.visibility = 'hidden';
//        w = MDNGetClientWidth() - mapWidthOffsetWithoutSidebar;
//    }
    
    w = MDNGetClientWidth() - mapWidthOffsetWithSidebar;
    h = MDNGetClientHeight() - mapHeightOffset; 
    if (w < minMapWidth) {w = minMapWidth;}
    if (h < minMapHeight) {h = minMapHeight;}
    
    var mapDiv = document.getElementById(MDNGetVEMapContainerID());
    if (mapDiv)
    {
        mapDiv.style.width = w + 'px';
        mapDiv.style.height = h + 'px';
        
        MDNGetVEMap().Resize(w, h);
        
        var footerDiv = document.getElementById('footerDiv');
        if (footerDiv)
        {
            //get style values used to calculate footer position;
            //these come from the css rules for the map and footer elements 
            var footerDivWidth;
            var mapDivLeft; 
            var mapDivTop;
            if (window.getComputedStyle) 
            {
                footerDivWidth = (window.getComputedStyle(footerDiv,null).width).replace(/px/,'');
                mapDivLeft = (window.getComputedStyle(mapDiv,null).left).replace(/px/,'');
                mapDivTop = (window.getComputedStyle(mapDiv,null).top).replace(/px/,'');       
            } 
            else if (footerDiv.currentStyle && mapDiv.currentStyle)
            {
                //IE
                footerDivWidth = (footerDiv.currentStyle.width).replace(/px/,'');
                mapDivLeft = (mapDiv.currentStyle.left).replace(/px/,'');
                mapDivTop = (mapDiv.currentStyle.top).replace(/px/,'');
            }
            else
            {
                //hide footer
                footerDiv.style.display = 'none';
                return;
            }
                        
            //extra 4px provides space between the bottom of the map and the top of the footer
            footerDiv.style.top = (h + parseInt(mapDivTop) + 4) + 'px';
            
            //extra 2px aligns footer right edge with map right edge
            footerDiv.style.left = (w + parseInt(mapDivLeft) - parseInt(footerDivWidth) + 2) + 'px'; 
        }
    }
//    var controlTop
//    if (MDNGetVEMap().GetMapMode() == VEMapMode.Mode2D)
//    {
//        if (MDNGetVEMap().GetMapStyle() == VEMapStyle.Birdseye)
//        {
//            controlTop = customControlTop2DBird;
//        }
//        else
//        {
//            controlTop = customControlTop2D;
//        }
//    }
//    else 
//    {
//        controlTop = customControlTop3D;
//    }
//
//    //create custom controls inside the VEMap:
//    //
//    //create full extent control for all modes and browsers
//    AddControlDiv("fullExtent", controlTop + "px", customControlLeft, "<a href='javascript:ZoomToFullExtent();'><img src='Images/FullExtent.gif' alt='Full Extent' style='width:16px; height:16px;'/></a>");
//    
//    //create toggle overview control for 2D mode in all browsers
//    toggleOverviewSpace = 1;
//    if (MDNGetVEMap().GetMapMode() == VEMapMode.Mode2D)
//    {
//        AddControlDiv("toggleOverview", controlTop + customControlVerticalSpace + "px", customControlLeft, "<a href='javascript:ToggleOverview();'><img src='Images/ToggleOverview.gif' alt='Toggle Overview' style='width:16px; height:16px;'/></a>");
//        toggleOverviewSpace = 2;
//    }
//    
//    //create toggle toolpanel control for all modes and non-IE browsers
//    if (!document.all) 
//    {
//        if (sidebarIsVisible == true)
//        {
//            AddControlDiv("toggleToolPanel", controlTop + toggleOverviewSpace*customControlVerticalSpace + "px", customControlLeft, "<a href='javascript:ToggleToolPanel();'><img src='Images/ArrowLeft.gif' alt='Hide Tool Panel' style='width:16px; height:16px;'/></a>");
//        }
//        else
//        {
//            AddControlDiv("toggleToolPanel", controlTop + toggleOverviewSpace*customControlVerticalSpace + "px", customControlLeft, "<a href='javascript:ToggleToolPanel();'><img src='Images/ArrowRight.gif' alt='Show Tool Panel' style='width:16px; height:16px;'/></a>");
//        }
//    }
}

//Called by MDNPostLoadVEMapInternal after the VE map control has been instantiated and loaded 
//into the parent element. Used here to add MDN tiles, update the mouse coordinate feedback,
//and wire various VE events.
function MDNPostLoadVEMap(veMap)
{   
    //adds tile layer to map
    MDNAddTileLayer();
     
    //override onmousemove event handler for XY coordinate display
    document.onmousemove = function(event)
    {
        //call base MDNS handler
        MDNMouseMoveHandlerOverride(event);

        //grab the event in a cross-browser way
        event = event || window.event;

        //get the map div
        var mapDiv = document.getElementById(MDNGetVEMapContainerID());

        //internal helper method to get absolute position of html element
        MDNGetElementAbsolutePos(mapDiv);

        //calculate the relative coordinates within the map div
        event.mx = event.clientX - mapDiv.x;
        event.my = event.clientY - mapDiv.y;

        //if the mouse is over the map, get map coordinate
        if (event.mx>=0 && event.my>=0 && event.mx<mapDiv.w && event.my<mapDiv.h)
        {
            try
            {
                //convert pixels to lat/long and display
                var latLong = MDNGetVEMap().PixelToLatLong(new VEPixel(event.mx, event.my));
                document.getElementById('coordLatSpan').innerHTML=latLong.Latitude;
                document.getElementById('coordLonSpan').innerHTML=latLong.Longitude;
            }
            catch(e){}
        }
    }

    //wire VEMap mouse and keyboard events
    MDNGetVEMap().AttachEvent('onmousedown', OnVEMouseDown);
    MDNGetVEMap().AttachEvent('onmouseup', OnVEMouseUp);
    MDNGetVEMap().AttachEvent('ondoubleclick', OnVEDoubleClick);
    MDNGetVEMap().AttachEvent('oninitmode', OnVEInitMode);
//    MDNGetVEMap().AttachEvent('onkeydown', OnVEKeyDown); 
//    MDNGetVEMap().AttachEvent('onchangemapstyle', OnVEChangeMapStyle);

    if (pageParameterPointLat != null && pageParameterPointLon != null)
    {
        //reset flag and set drilldowns into motion
        //doDrillDown = false;  
        DoDrillDown();
    }
    else if (hasPageParameterHighlightShape)
    {
        //call registered script
        HighlightPageParameterShape(); 
    }
}



//
//VEMAP MOUSE AND KEYBOARD EVENT HANDLERS
//

//a timer and interval used to skip double-click events; interval must be longer than the VE doubleclick interval
var doubleClickTimer = null;
var doubleClickInterval = 500;

//XY values of mouse location
var mousedownClientX = 0;
var mousedownClientY = 0;

//Removes mouseout behavior from pushpins. Call after placing the pushpin.
//
//TODO: verify that this function is still needed now that VE seems to support mouseout event capture...
//
function BlockInfoBoxHideOnPushpinMouseout()
{
    var elem = document.getElementById('VELayerListDiv');
    if (elem)
    {
        var arr = elem.getElementsByTagName('A');
        for (var n = 0; n < arr.length; n++)
        {
            var arr2 = arr[n].getElementsByTagName('DIV');
            if (arr2.length)
            {
                //
                //TEST remove Russell's method here... 
                //
                arr2[0].onmouseout = null;
            }
        }
    }
}

//Return VELatLong at mouse location. Should work for 2D or 3D.
function GetVEMouseEventLatLon(e)
{
    var latLong = e.latLong;
    if (!latLong)
    {
        //map is 2D
        latLong = MDNGetVEMap().PixelToLatLong(new VEPixel(e.mapX,e.mapY));
    }
    return latLong;
}   

//Clear the timeout and do drilldown. 
function HandleVEMouseClick(lon, lat, zoom)
{
    //call registered script method
    HandleDrillDownIdentify(lon,lat,zoom);
    doubleClickTimer = null;
}

////Call MDNBrowserResizeWrapper in order to redraw custom controls in case the style 
////shifted between Bird's eye and one of the other three styles. 
//function OnVEChangeMapStyle(e)
//{
//    MDNBrowserResizeWrapper();
//}

//Abort onclick drilldown.
function OnVEDoubleClick(e)
{
    if (doubleClickTimer != null)
    {
        window.clearTimeout(doubleClickTimer);
        doubleClickTimer = null;
    }
}

////Disable shortcut keys for 3D and Birdseye--not needed since VE 6.1 release, 
////though this handler could be used for other things. 
//function OnVEKeyDown(e)
//{
//    if(e.keyCode == 66 || e.keyCode == 79 || e.keyCode == 51)
//    {
//        //key is either B/b, O/o, or 3/#
//        return true;
//    }
//}

//Evaluate the map mode and show the footer if in 2D. If in 3D, then hide info 
//box and delete shape layer which may contain pushpins.
function OnVEInitMode(e)
{
    var footer = document.getElementById("footer");
    
    //delete custom controls; this must be done before MDNBrowserResizeWrapper when switching modes
    //DeleteCustomControls();
    
    if (MDNGetVEMap().GetMapMode() == VEMapMode.Mode3D)
    {
        if (footer) footer.style.display = 'none';
        window.MDNGetVEMap().HideInfoBox();
        if (window.MyHighlightLayer) window.MDNGetVEMap().DeleteShapeLayer(window.MyHighlightLayer);
    }
    else if (MDNGetVEMap().GetMapMode() == VEMapMode.Mode2D)
    {
        //
        //TODO: figure out why InfoBox does not display correctly after returning from 3D mode;
        //      the following does not solve this problem: MDNGetVEMap().SetDefaultInfoBoxStyles(); 
        if (footer) footer.style.display = 'inline';
    }
}

//Capture location on single click.
function OnVEMouseDown(e)
{
    mousedownClientX = e.clientX;
    mousedownClientY = e.clientY;
}

//Execute drilldown if not dragged.
function OnVEMouseUp(e)
{
    //verify that mouse wasn't dragged and we haven't started a timeout
    if (mousedownClientX == e.clientX && mousedownClientY == e.clientY && doubleClickTimer == null)
    {
        //verify that map is in 2D mode here;
        if (MDNGetVEMap().GetMapMode() == VEMapMode.Mode2D)
        {
            var latLong = GetVEMouseEventLatLon(e);

            //use a timeout so if they double-click we can abort
            doubleClickTimer = window.setTimeout('HandleVEMouseClick(' + latLong.Longitude + ',' +
                               latLong.Latitude + ',' + MDNGetVEMap().GetZoomLevel() + ')', doubleClickInterval);
        }
    }
}



//
//SUPPORT FOR DRILLDOWN FROM PAGE PARAMETER QUERIES
//

//location from which to do a drilldown after a page parameter query
var pageParameterPointLat;
var pageParameterPointLon;

//flag to indicate when the drilldown web method has completed the operation
var drillDownCompleted = false;

//a timer and interval used to continue calling HandleDrillDownIdentify() until it completes 
var repeatDrillDownTimer = null;
var repeatDrillDownTimerInterval = 1500;

//keeps attempting to do a drilldown until successful
function DoDrillDown()
{
    //clear timer if previously set
    if (repeatDrillDownTimer != null)
    {
        window.clearTimeout(repeatDrillDownTimer);
        repeatDrillDownTimer = null;
    }

    //get latLong and set timer to call registered drilldown script
        
    if (!drillDownCompleted)
    {
        //web method on page has not yet reset drillDownCompleted;
        //issue the request using the center of the screen
        HandleDrillDownIdentify(pageParameterPointLon, pageParameterPointLat, MDNGetVEMap().GetZoomLevel());

        //create recursive call in case the operation did not execute
        repeatDrillDownTimer = window.setTimeout('DoDrillDown()', repeatDrillDownTimerInterval);
    }
}



//
//TOGGLE OVERVIEW MAP
//

//a flag to indicate whether the overview VE Mini Map is visible
var overviewIsVisible = false;

//called by control at toggleOverviewDiv to hide or show the VE Mini Map.
function ToggleOverview()
{
    overviewIsVisible = !overviewIsVisible;
    if (overviewIsVisible)
    {
        MDNGetVEMap().ShowMiniMap();
    }
    else
    {
        MDNGetVEMap().HideMiniMap();
    }
}



//
//CHANGE MAP
//

//the index of the current map file; this is zero for apps that have only a single map
var currentMapFileIndex = 0;

//Redirect the page to a new map if one is supplied in the url, otherwise display the available maps 
//on the main page.
function ChangeMapApp(url)
{
    if (url)
    {
        window.location.href = url + GetPageParamString() + '&dd=false';
    }
    else
    {
        var elem = document.getElementById('mapChoiceDiv');
        if (elem)
        {
            elem.style.display='block';
        }
    }
}

//Redirect the page to a new map file.
//Note that unlike ChangeMapApp() above, this method redirects to the same page while inserting a 
//page parameter to indicate which map file RichmondMapDotNetVEBase.Initialize() will use.
function ChangeMapFile(url, mapFileIndex)
{
    if (url)
    {
        window.location.href = url + GetPageParamString() + '&mapFileIndex=' + mapFileIndex;
    }
}

//Returns coordinates, zoom level, and VEMapStyle of the current map. 
function GetPageParamString()
{
    var center = MDNGetVEMap().GetCenter();
    var zl = MDNGetVEMap().GetZoomLevel();
    var veMapStyle = MDNGetVEMap().GetMapStyle();
    return '?lon=' + center.Longitude + '&lat=' + center.Latitude + '&zl=' + zl + '&vemapstyle=' + veMapStyle;
}



//
//OTHER WINDOWS AND DIALOGS
//

//bookmark variables
var bookmarkBaseUrl;
var bookmarkName='My Location';
var bookmarkWindow;
var bookmarkWindowWidth=450;
var bookmarkWindowHeight=150;

//help window
var helpWindow;

//Attempts to create an Internet Explorer bookmark to the current map. If this fails then a 
//popup is provided containing a url that can be copied for manual bookmark creation.  
function AddBookmark()
{
    //create the query string that can be appended to the application url to open the current map
    var queryString = GetPageParamString();
    try
    {
        //create IE bookmark
        window.external.AddFavorite(bookmarkBaseUrl + queryString, bookmarkName);
    }
    catch(e)
    {
        //not IE; open a popup to simply display the url
        OpenBookmarkWindow(queryString);
	}
} 

//Creates a popup displaying the url of the current map.
function OpenBookmarkWindow(queryString) 
{
    try
    {
        //calculate screen center
        leftPosition = (screen.width) ? (screen.width  - bookmarkWindowWidth)/2 : 100;
	    topPosition  = (screen.height) ? (screen.height - bookmarkWindowHeight)/2 : 100;
    	        
    	//open new window
	    bookmarkWindow=window.open(bookmarkBaseUrl,'bookmarkWindow','width=' + bookmarkWindowWidth + ',height=' + bookmarkWindowHeight + 
	                               ',top=' + topPosition + ',left=' + leftPosition + 
            	                   ',location=no,directories=no,menubar=yes,toolbar=no,status=no,scrollbars=no,resizable=yes,dependent=yes');
        
        //create markup
	    var doc = bookmarkWindow.document;
	    doc.write('<html><head><title>Bookmark Location</title>');
	    doc.write('<link rel="stylesheet" href="Bookmark.css">');	    
	    doc.write('</head><body>');
	    doc.write('<p>The following link identifies the location currently displayed by the map. You may save this link using your browser&#39;s bookmark functionality.</p>');
	    doc.write('<p><a href="' + bookmarkBaseUrl + queryString + '">' + bookmarkBaseUrl + '<br/>' + queryString + '</a></p>');
	    //doc.write('<p><textarea class="popup" rows="4" cols="38" readonly="true">' + bookmarkBaseUrl + queryString + '</textarea></p><br />');
	    doc.write('<br/><br/><p><a href="javascript:self.close()">Close</a></p>');
	    doc.write('</body></html>');
	    doc.close();
	    	    
	    //focus
	    if (bookmarkWindow.focus) 
	    {
	        bookmarkWindow.focus();
        }
    }
    catch(e)
    {
        alert('Unable to open bookmark window. Error message: ' + e.message);
    }
}

//Displays help content window.
function OpenHelpWindow()
{
    try
    {
        helpWindow=window.open('Help.htm', 'HelpWindow'); //,'','scrollbars=no,resizable=yes,dependent=yes');
        if (helpWindow.focus) helpWindow.focus; 
    }
    catch(e)
    {
        alert('Unable to open bookmark window. Error message: ' + e.message);
    }    
}

//Open PrintableMap.aspx if layout is supplied, otherwise display the layout options on the main page.
function PrintMap(layout)
{
    if (layout)
    {
        var w, h;
        if (layout == 'Landscape')
        {
            w = 866; //912;
            h = 624; //624; -- 592
        } 
        else
        {
            w = 624;
            h = 866;
        }
        window.open('PrintableMap.aspx', 'MapPrintWin' + layout, 'height=' + h + ',width=' + w + ',status,menubar,toolbar,resizable');
    }
    else
    {
        var elem = document.getElementById('printChoiceDiv');
        if (elem)
        {
            elem.style.display='block';
        }
    }
}



///
///CUSTOM CONTROL CREATION AND COLLAPSIBLE SIDEBAR SUPPORT
///

//function AddControlDiv(name, top, left, innerhtml)
//{
//    div = document.createElement("div"); 
//    div.id = name + "Div";
//    div.style.top = top; 
//    div.style.left = left; 
//    div.innerHTML = innerhtml;  

//    MDNGetVEMap().AddControl(div);
//    AddShim(div, name + "Shim");
//}

//function AddShim(el, shimId)
//{
//    var shim = document.createElement("iframe");
//    shim.id = shimId;
//    shim.frameBorder = "0";
//    shim.style.position = "absolute";
//    shim.style.zIndex = "1";
//    shim.style.top  = el.offsetTop;
//    shim.style.left = el.offsetLeft;
//    shim.width  = el.offsetWidth;
//    shim.height = el.offsetHeight;
//    el.shimElement = shim;
//    el.parentNode.insertBefore(shim, el);
//}

//function DeleteCustomControls()
//{
//    fullExtentDiv = document.getElementById('fullExtentDiv');
//    if (fullExtentDiv) RemoveControlDiv(fullExtentDiv);
//    fullExtentDiv = null;
//    toggleOverviewDiv = document.getElementById('toggleOverviewDiv');
//    if (toggleOverviewDiv) RemoveControlDiv(toggleOverviewDiv);    
//    toggleOverviewDiv = null;
//    togglePanelDiv = document.getElementById('toggleToolPanelDiv');
//    if (togglePanelDiv) RemoveControlDiv(togglePanelDiv);
//    togglePanelDiv = null;
//}

//function RemoveControlDiv(div)
//{
//    if (div != null)
//    {
//       MDNGetVEMap().DeleteControl(div);
//       div = null;
//    }
//}

////Toggles Toolpanel and legend.
//function ToggleToolPanel()
//{
//    sidebarIsVisible=!sidebarIsVisible;
//    toggleToolPanelDiv=null;
//    MDNBrowserResizeWrapper();
//}
