﻿var m_Map = null;
var m_Bounds;
var m_SWLatLng;
var m_NELatLng;
var m_SWLat;
var m_SWLng;
var m_NELat;
var m_NELng;
var m_Zoom;
var m_CenterPt;
//"BB" or "CT"; we're combining Canada & USA 
//JEB 7-25-08: To make this application BB only or CT only,
//comment out the <tr> with the dropdownlist in it on Default.aspx,
//and change "BB" to "CT" or vice versa, EVERYWHERE IN THIS FILE!!!!!!!!!
//That should be all you need to do, and you don't need to alter
//HFCMapProvider.aspx.cs or Searches.aspx.cs at all,
//and you'll still send BB or CT in the query string for the image and the terrnum search.
//Default is BB in the application where the dropdownlist is included.
var m_TerrType = "BB";
var m_TerrOverlay;
var m_ResponseText;
var m_Marker;
var m_Opacity = 50; //used in DisplayTerritories(); set in SetGlobalOpacity()
var m_bIsMetroArea = new Boolean(false); //this determines whether too zoom way in or not on a zip find
var m_OverviewCtrl;
var m_LgMapCtrl;
var m_MapTypeCtrl;
var m_TerrNum = "";

function LoadMap() 
{
	if (GBrowserIsCompatible()) 
	{
	    ParseQueryString();
	    SetMapDivSize();
		m_Map = new GMap2(document.getElementById("map_canvas"));
		m_Map.addMapType(G_PHYSICAL_MAP);
		m_Map.setCenter(m_CenterPt, m_Zoom);
		//our office:
		//m_Map.setCenter(new GLatLng(33.823367540358035, -117.85154342651367), 9);
		
        m_OverviewCtrl = new GOverviewMapControl();
        m_Map.addControl(m_OverviewCtrl);
        m_LgMapCtrl = new GLargeMapControl();
        m_Map.addControl(m_LgMapCtrl);
        m_MapTypeCtrl = new GMapTypeControl();
        m_Map.addControl(m_MapTypeCtrl);
        m_Map.enableGoogleBar();

		GEvent.addListener(m_Map, "moveend", DisplayTerritories);
		DisplayTerritories();
	}
}//end LoadMap()

/********************************************************************
PURPOSE: Per Jason Engberg, we want the ability to send someone a link
to a particular center point and zoom, ostensibly to show them a territory
that they are contemplating purchasing. This function will parse the 
query string so the map can light up at that location & zoom.
*********************************************************************/
function ParseQueryString()
{
    m_SWLat, m_SWLng, m_NELat, m_NELng, m_Zoom, m_TerrType = "";
    var sURL = window.location.toString();
    //alert(sURL);
    var arURL = sURL.split('?');
    if (arURL.length == 2)
    {
        var arQS = arURL[1].split('&');
        for (var i = 0; i < arQS.length; i++)
        {
            var arNameValue = arQS[i].split('=');
            if (arNameValue.length == 2)
            {
                if (arNameValue[0].length > 0 && arNameValue[1].length > 0)
                {
                    var sName = arNameValue[0];
                    var sValue = arNameValue[1];
                    switch(sName)
                    {
                        case"SWLat":                     
                            m_SWLat = (sValue.length > 0) ? parseFloat(sValue) : "";
                            break;
                        case "SWLng":
                            m_SWLng = (sValue.length > 0) ? parseFloat(sValue) : "";
                            break;
                        case "NELat":
                            m_NELat = (sValue.length > 0) ? parseFloat(sValue) : "";
                            break;
                        case "NELng":
                            m_NELng = (sValue.length > 0) ? parseFloat(sValue) : "";
                            break;
                        case "Zoom":
                            m_Zoom = (sValue.length > 0) ? parseInt(sValue) : 4;
                            break;
                        case "TerrType":
                            m_TerrType = (sValue.length == 2) ? sValue : "BB";
                            break;
                    }//switch                
                }//if
            }//if            
        }//for
    
        //check for valid values from query string...
        if (isNaN(m_SWLat) || isNaN(m_NELat) || isNaN(m_SWLng) || isNaN(m_NELng))
        {   
            //default values if something went wrong
            m_CenterPt = new GLatLng(39.30, -95.45);
            m_Zoom = 4;
            m_TerrType = "BB";
        }
        else
        {
            //everything's a go
            m_CenterPt = new GLatLng(((m_NELat + m_SWLat)/2), ((m_NELng + m_SWLng)/2));
        }
    }
    else //no query string
    {
        m_Zoom = 4;
        m_CenterPt = new GLatLng(39.30, -95.45);
        m_TerrType = "BB";
    }   
        
//    alert("m_SWLat: " + m_SWLat + 
//        "\nm_SWLng: " + m_SWLng	+ 
//        "\nm_NELat: " + m_NELat + 
//        "\nm_NELng: " + m_NELng + 
//        "\nm_Zoom: " + m_Zoom + 
//        "\nm_TerrType: " + m_TerrType +
//        "\nm_CenterPt: " + m_CenterPt);        
	    
}//end ParseQueryString()

/********************************************************************
From: http://code.google.com/apis/maps/documentation/services.html
PURPOSE: does an ajax call on the imageUrl. DisplayTerritories()
calls DisableControls() to throw a div over the page and 
disable the map controls. After m_TerrOverlay is constructed, this 
function takes the imageUrl as a parameter and does an ajax call.
readyState won't = 4 until the imageUrl comes into existence. This 
prevents the user from moving the map or making any other moves until
AFTER the previous event has been fully processed.
*********************************************************************/
function CheckImageLoadStatus(imageUrl)
{
    var request = GXmlHttp.create();
    request.open("GET", imageUrl, true);
    request.onreadystatechange = function() 
    {
        if (request.readyState == 4)
        {
            EnableControls();
        }
    }
    request.send(null);
}

/********************************************************************
PURPOSE: makes covering div visible, and disables all map controls,
until image fully loads. Called in DisplayTerritories().
*********************************************************************/
function DisableControls()
{
    //document.getElementById("lblBBorCT").innerHTML = "<h1>Loading.... Please Wait.</h1>";
    document.getElementById("loading").className = "loading-visible";
    m_Map.disableDragging();
    //m_Map.disableInfoWindow();
    m_Map.disableDoubleClickZoom();
    m_Map.disableContinuousZoom();
    //m_Map.disableGoogleBar();
    m_Map.disableScrollWheelZoom();
    //m_Map.removeControl(m_OverviewCtrl);
    m_OverviewCtrl.hide();
    m_Map.removeControl(m_LgMapCtrl);
    m_Map.removeControl(m_MapTypeCtrl);

}

/********************************************************************
PURPOSE: makes covering div invisible, and enables all map controls,
after having been disabled by DisableControls(). Called in CheckImageLoadStatus(),
which is called in DisplayTerritories().
*********************************************************************/
function EnableControls()
{
    //document.getElementById("lblBBorCT").innerHTML = "<h3>Budget Blinds Territories</h3>";
    document.getElementById("loading").className = "loading-invisible";

	m_Map.enableDragging();
    //m_Map.enableInfoWindow();
    m_Map.enableDoubleClickZoom();
    m_Map.enableContinuousZoom();
    //m_Map.enableGoogleBar();
    m_Map.enableScrollWheelZoom();
    //m_Map.addControl(m_OverviewCtrl);
    m_OverviewCtrl.show();
    m_Map.addControl(m_LgMapCtrl);
    m_Map.addControl(m_MapTypeCtrl);
}

/********************************************************************
PURPOSE: This is the main function. It is responsible for calculating
the center, the bounds, the zoom, and territory (BB or CT), putting
this all into a query string, and then using the ImageOverlay constructor
to call the aspx file that generates the image that gets overlaid onto
the map.
*********************************************************************/
function DisplayTerritories()
{
    //m_Map.clearOverlays();
    if (m_TerrOverlay) m_Map.removeOverlay(m_TerrOverlay);
	var mapZoom = m_Map.getZoom();
	var mapBounds = m_Map.getBounds();
	var SWLatLng = mapBounds.getSouthWest();
	var NELatLng = mapBounds.getNorthEast();
	
	var lngDelta = 0;
	var latDelta = 0;
	
	//this switch determines how much MORE than the actual viewport
	//gets sent to the provider. This is done so that some of the larger shapes
	//don't get "lopped off".
	switch (mapZoom)
	{
	    case 18:
	    case 17:
	    case 16:
	    case 15:
	    case 14:
	    case 13:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 1;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 1;
            break;
	    case 12:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 2;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 2;
            break;
	    case 11:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 3;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 3;
            break;
	    case 10:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 4;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 4;
            break;
	    case 9:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 5;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 5;
            break;
	    case 8:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 6;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 6;
            break;
	    case 7:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 7;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 7;
            break;
	    case 6:
            lngDelta = (NELatLng.lng() - SWLatLng.lng()) / 8;
            latDelta = (NELatLng.lat() - SWLatLng.lat()) / 8;
            break;
        default:
            lngDelta = 0;
            latDelta = 0;
            break;	        
	}//end switch
	//disable the map & controls until image finishes loading
	if (mapZoom < 11) DisableControls();
    
	var SWLat = SWLatLng.lat() - latDelta;
	var SWLng = SWLatLng.lng() - lngDelta;
	var NELat = NELatLng.lat() + latDelta;
	var NELng = NELatLng.lng() + lngDelta;
	
	var imageUrl = "HFCMapProvider.aspx?SWLat=" + SWLat + "&SWLng=" + SWLng + 
	    "&NELat=" + NELat + "&NELng=" + NELng + "&Zoom=" + mapZoom + "&TerrType=" + m_TerrType;	
	//alert("imageUrl: " + imageUrl);
	var rectBounds =  new GLatLngBounds(new GLatLng(SWLat, SWLng), new GLatLng(NELat, NELng));
	
	m_TerrOverlay = new ImageOverlay(imageUrl, rectBounds);	
	m_Map.addOverlay(m_TerrOverlay);
	m_TerrOverlay.setOpacity(m_Opacity);
	//GEvent.addListener(m_TerrOverlay, "visibilitychanged", WhenDoesThisFire(true));
	GetCenterCoords();	
	//re-enable the page & map if image has finished loading
	if (mapZoom < 11) CheckImageLoadStatus(imageUrl);					
}//end DisplayTerritories()

function WhenDoesThisFire(bIsVisible)
{
    alert("In WhenDoesThisFire()");
}

/********************************************************************
PURPOSE: given a file name, in this case ZipSearch.aspx?Zip=92807,
performs its ajax magic to retrieve the zoom, center coordinates,
and attribute description from the CShape object with that zipcode.
*********************************************************************/
function AjaxZipSearch(fName)
{
	var xmlHttp;
	try//#1
	{
		// Firefox, Opera 8.0+, Safari
		xmlHttp=new XMLHttpRequest();
	}//end try #1
	catch (e)//#1
	{
		// Internet Explorer
		try//#2
		{
			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}//end try #2
		catch (e)//#2
		{
			try//#3
			{
				xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
			}//end try #3
			catch (e)//#3
			{
				alert("Your browser does not support AJAX!");
				return false;
			}//end catch #3
		}//end catch #2
	}//end catch #1		

	xmlHttp.onreadystatechange=function()
	{
		if(xmlHttp.readyState==4)
		{
			//document.myForm.time.value=xmlHttp.responseText;
			m_ResponseText = xmlHttp.responseText;
			//alert("In ajaxFunction: " + m_ResponseText);
			LoadTheDiv(m_ResponseText, true);
		}
	}
	xmlHttp.open("GET", fName, true);
	xmlHttp.send(null);		
}//end AjaxZipSearch()

/********************************************************************
PURPOSE:
    01) to display information about the zip code or territory sought
    02) to center and zoom the map over that zip code or territory
This function parses the xmlHttp.responseText from the ajaxFunction,
to find zoom, center coordinates, and zip code or territory attributes.  
CALLED BY: AjaxZipSearch()   
*********************************************************************/
function LoadTheDiv(sResponse, bZoomTo)
{
    var arResponse = sResponse.split("|");
    //alert(arResponse);
    var centerLat = parseFloat(arResponse[0]);
    var centerLng = parseFloat(arResponse[1]);
    var nZoom =  parseInt(arResponse[2]);
    //alert("centerLat: " + centerLat + " centerLng: " + centerLng);
    if ((!isNaN(centerLat)) && (!isNaN(centerLng)))
    {
        if (bZoomTo)//it's a zip code search; zoom to it and add a GMarker with City, State, Zip info window
        {
            if (m_Marker) m_Map.removeOverlay(m_Marker);
            nZoom = (isNaN(nZoom)) ? 13 : nZoom;
            nZoom = (m_bIsMetroArea) ? 10 : nZoom; //if it's a metro area, zoom out
            m_Map.setCenter(new GLatLng(centerLat, centerLng), nZoom);
            m_Marker = new GMarker(new GLatLng(centerLat, centerLng));
            GEvent.addListener(m_Marker, "click", function() {m_Marker.openInfoWindowHtml(arResponse[4])});
            m_Map.addOverlay(m_Marker);
        }
        else //it's a territory search, just show the territory information
        {
            document.getElementById("divShapeInfo").innerHTML = arResponse[3];    
        }
    }
    else
    {
        if (bZoomTo)
        {
            var sZipCode = document.getElementById("txtZipCode").value;
            alert(sZipCode + " is not a valid zip code." + 
                "\nPlease enter a valid zip code, or choose from list.");            
        }
        else
        {
            var sTerrNum = document.getElementById("txtTerrNum").value;
            alert(sTerrNum + " is not a valid territory number." +
                "\nPlease double-check your entry.");            
        }
    }
    document.getElementById("txtZipCode").value = "";
    document.getElementById("txtTerrNum").value = "";
}//end LoadTheDiv()

/********************************************************************
PURPOSE: gets a zip code value from either txtZipCode or ddlZipCode, 
creates a file name with query string from that, and calls 
AjaxZipSearch with that file name.
CALLED BY: btnFindZip in Default.aspx
*********************************************************************/
function btnFindZip_Click()
{
	var zip = 92807;
	if (document.getElementById("txtZipCode").value != "")
	{
	    m_bIsMetroArea = false;
	    zip = document.getElementById("txtZipCode").value;
	    document.getElementById("ddlZipCode").selectedIndex = 0;
	    //document.getElementById("txtZipCode").value = "";
	}
	else if (document.getElementById("ddlZipCode").value != "0")
	{
	    m_bIsMetroArea = true; //if metro area, zoom out
	    zip = document.getElementById("ddlZipCode").value;
	}
	//alert(zip);
	AjaxZipSearch("Searches.aspx?Zip=" + zip);
	//return false;
}//end btnFindZip_Click()

/********************************************************************
PURPOSE: User changes the dropdownlist for metropolitan areas.
This function clears txtZipCode, then calls btnFindZip_Click().
This way there will be no confusion as to which zip we're sending in the query.
*********************************************************************/
function ddlZipCode_Changed(nIndex)
{
    if (nIndex != 0)
    {
        document.getElementById("txtZipCode").value = "";
    }
    btnFindZip_Click();
    
}//end ClearZipTextBox()

/********************************************************************
PURPOSE: Given a valid territory number and BB or CT, changes
the status of a the corresponding CShape.BBStatus or CShape.CTStatus
*********************************************************************/
function ChangeStatus()
{
    var ddlStatus = document.getElementById("ddlChangeStatus");
    var sNewStatus = ddlStatus[ddlStatus.selectedIndex].value;
    var nNewStatus = parseInt(sNewStatus);
    var sTerrNum = document.getElementById("txtChangeTerrNum").value;
    //alert("sNewStatus: " + sNewStatus + "\nTerrNum: " + sTerrNum);
    if (nNewStatus > -1 && nNewStatus < 5 && sTerrNum.length > 0)
    {
        var TheUrl = "StatusChange.aspx?Status=" + sNewStatus + "&TerrType=" + m_TerrType + "&TerrNum=" + sTerrNum;
        var bContinue = confirm("ChangeStatus(): " + TheUrl);
        if (bContinue)
        {
            AjaxChangeStatus(TheUrl);
        }
        else
        {
            alert("Status Change has been canceled");
        }
    }
}//end ChangeStatus()

/********************************************************************
PURPOSE: the ajax call to Status.aspx, called by ChangeStatus
*********************************************************************/
function AjaxChangeStatus(fName)
{
	var xmlHttp;
	try//#1
	{
		// Firefox, Opera 8.0+, Safari
		xmlHttp=new XMLHttpRequest();
	}//end try #1
	catch (e)//#1
	{
		// Internet Explorer
		try//#2
		{
			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}//end try #2
		catch (e)//#2
		{
			try//#3
			{
				xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
			}//end try #3
			catch (e)//#3
			{
				alert("Your browser does not support AJAX!");
				return false;
			}//end catch #3
		}//end catch #2
	}//end catch #1		

	xmlHttp.onreadystatechange=function()
	{
		if(xmlHttp.readyState==4)
		{
            //JEB 10/8/08: I am using a pipe '|' in my message on Searches.aspx.cs
            //This allows me to split the string and only grab the first section.
            //I was getting all this extraneous html bullshit in the alert.
            var msg = "AjaxChangeStatus(): \n" + xmlHttp.responseText.split('|')[0];
            alert(msg);
            //alert("AjaxChangeStatus(): " + xmlHttp.responseText);
		}
	}
	xmlHttp.open("GET", fName, true);
	xmlHttp.send(null);		
    
}//end AjaxChangeStatus()

/********************************************************************
PURPOSE: to set a global opacity value, so that the opacity 
stays the same until the user changes it manually,
and then to call setOpacity() with the new value.
REQUIRES: a global variable called m_Opacity
ASSUMES: the image overlay is called m_TerrOverlay
*********************************************************************/
function SetGlobalOpacity(nOpacity)
{
    m_Opacity = nOpacity;
    m_TerrOverlay.setOpacity(nOpacity)
}//end SetGlobalOpacity()

/********************************************************************
PURPOSE: outputs to a div id="message" various items, including
a query string Jason wants someone to be able to use to include in an
email for opening the application and zooming right to that territory.

var imageUrl = "HFCMapProvider.aspx?SWLat=" + SWLat + "&SWLng=" + SWLng + 
	    "&NELat=" + NELat + "&NELng=" + NELng + "&Zoom=" + mapZoom + "&TerrType=" + m_TerrType;	
*********************************************************************/
function GetCenterCoords()
{
    //sURL contains just the URL up to but not including the ?, if there is one
    var sURL = window.location.toString().split('?')[0];
    
	m_Center = m_Map.getCenter(); //returns GLatLng of center of map
	m_Bounds = m_Map.getBounds(); //returns SW GLatLng and NE GLatLng;
	var nIndex = -1;
	var SWLat = m_Bounds.getSouthWest().lat();
	nIndex = SWLat.toString().indexOf('.');
	SWLat = parseFloat(SWLat.toString().substring(0, nIndex) + SWLat.toString().substring(nIndex, nIndex + 4));

	var SWLng = m_Bounds.getSouthWest().lng();
	nIndex = SWLng.toString().indexOf('.');
	SWLng = parseFloat(SWLng.toString().substring(0, nIndex) + SWLng.toString().substring(nIndex, nIndex + 4));

	var NELat = m_Bounds.getNorthEast().lat();
	nIndex = NELat.toString().indexOf('.');
	NELat = parseFloat(NELat.toString().substring(0, nIndex) + NELat.toString().substring(nIndex, nIndex + 4));

	var NELng = m_Bounds.getNorthEast().lng();
	nIndex = NELng.toString().indexOf('.');
	NELng = parseFloat(NELng.toString().substring(0, nIndex) + NELng.toString().substring(nIndex, nIndex + 4));
	
	m_Zoom = m_Map.getZoom(); //returns zoom integer: smaller is less zoom, greater zooms in
	m_Size = m_Map.getSize();
	var sInfo = "Center: " +  m_Center.toString() + 
	"&nbsp;&nbsp;&nbsp;Zoom: " + m_Zoom.toString() + "&nbsp;&nbsp;&nbsp;Size: " + m_Size +
	"<br />Bounds: " + m_Bounds.toString() +
	//"<br />QueryString: http://maps.homefranchiseconcepts.com/BBMaps/Default.aspx?SWLat=" + SWLat + 
	"<br />QueryString: " + sURL + "?SWLat=" + SWLat + 
	//"<br />QueryString: http://localhost:1202/HFCTerrMap/Default.aspx?SWLat=" + SWLat + 
	"&SWLng=" + SWLng + "&NELat=" + NELat + "&NELng=" + NELng + "&Zoom=" + m_Zoom + "&TerrType=" + m_TerrType;
	
	document.getElementById("message").innerHTML = sInfo;
}//end GetCenterCoords()

/********************************************************************
PURPOSE: event handler for user entering a BBTERRNUM into txtTerrNum
Calls the Ajax function, and passes it the proper filename and query string.
*********************************************************************/
function btnFindTerr_Click()
{
    var sTerrNum = "803CA018";
    if (document.getElementById("txtTerrNum").value != "")
    {
        sTerrNum = document.getElementById("txtTerrNum").value;
       //document.getElementById("txtTerrNum").value = "";
    }
    AjaxBBTerrNumSearch("Searches.aspx?TerrNum=" + sTerrNum + "&TerrType=" + m_TerrType);    
}//end btnFindTerr_Click()

/********************************************************************
PURPOSE: given a file name, in this case ZipSearch.aspx?BBTerrNum=800CA018,
performs its ajax magic to retrieve the zoom, center coordinates,
and attribute description from the CShape object with that BBTERRNUM.
*********************************************************************/
function AjaxBBTerrNumSearch(fName)
{
	var xmlHttp;
	try//#1
	{
		// Firefox, Opera 8.0+, Safari
		xmlHttp=new XMLHttpRequest();
	}//end try #1
	catch (e)//#1
	{
		// Internet Explorer
		try//#2
		{
			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}//end try #2
		catch (e)//#2
		{
			try//#3
			{
				xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
			}//end try #3
			catch (e)//#3
			{
				alert("Your browser does not support AJAX!");
				return false;
			}//end catch #3
		}//end catch #2
	}//end catch #1		

	xmlHttp.onreadystatechange=function()
	{
		if(xmlHttp.readyState==4)
		{
			//document.myForm.time.value=xmlHttp.responseText;
			m_ResponseText = xmlHttp.responseText;
			//alert("In AjaxBBTerrNumSearch(): " + m_ResponseText);
			LoadTheDiv(m_ResponseText, false);
		}
	}
	xmlHttp.open("GET", fName, true);
	xmlHttp.send(null);		
}//end AjaxBBTerrNumSearch()

/********************************************************************
PURPOSE: This is the event handler for the ddl that changes the 
territory from Budget Binds to Closet Tailors and vice versa.
All it does is re-set a global variable and call DisplayTerritories().
DisplayTerritories() checks the value of the global variable, and passes
its value on to HFCMapProvider.aspx.cs, in the query string.
*********************************************************************/
function ddlBBorCT_Changed(sValue)
{
    //alert(sValue);
    m_TerrType = sValue;
    //m_Map.setCenter(new GLatLng(39.30029918615029, -95.44921875), 4);
    DisplayTerritories();
}//end ddlBBorCT_Changed()

/********************************************************************
http://developer.mozilla.org/en/docs/window.innerWidth
http://developer.mozilla.org/en/docs/window.innerHeight
http://developer.mozilla.org/en/docs/DOM:document.documentElement
http://developer.mozilla.org/en/docs/DOM:element.clientHeight

http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
window.innerHeight/Width: Provided by most browsers, but importantly, not Internet Explorer.
document.body.clientHeight/Width: Provided by many browsers, including Internet Explorer.
document.documentElement.clientHeight/Width: Provided by most DOM browsers, including Internet Explorer. 
*********************************************************************/
function SetMapDivSize() 
{
    var nWidth = 0;
    var nHeight = 0;
    if (typeof(window.innerWidth) == 'number') 
    {
        //Non-IE
        nWidth = window.innerWidth;
        nHeight = window.innerHeight;
    } 
    else if (document.documentElement && 
            (document.documentElement.clientWidth || document.documentElement.clientHeight)) 
    {
        //IE 6+ in 'standards compliant mode'
        nWidth = document.documentElement.clientWidth;
        nHeight = document.documentElement.clientHeight;
    } 
    else if (document.body && (document.body.clientWidth || document.body.clientHeight)) 
    {
        //IE 4 compatible
        nWidth = document.body.clientWidth;
        nHeight = document.body.clientHeight;
    }
    //alert("nWidth before: " + nWidth + "\nnHeight before: " + nHeight);
    var mp = document.getElementById("map_canvas");
    //var mp = document.getElementById("container");
    //nWidth *= .75; //this varies, for some reason
    nWidth -= 250; //unfortunately, trial & error to compensate for leftCol
    //nHeight *= .85;
    //900 is trial & error max window heights; 130 is calculated header height
    nHeight = (nHeight < 900) ? nHeight - 130 : 770;
    mp.style.height = nHeight.toString() + "px";
    mp.style.width = nWidth.toString() + "px"; 
}
