Virtual Earth Basics Part 1 – Loading the Map

Welcome to the first part in series that takes you through the core functionality of the Microsoft’s Virtual Earth JavaScript control. Through example code I hope to either introduce you to the Virtual Earth control or show you how to do things better and highlight some things you may not have known. I will be making use of the jQuery JavaScript library to provide valuable helper functions and simplify our code. If you feel there is something that could done better please share your ideas in the comments below.

Lets start by loading the Virtual Earth map on a page. Sounds trivial? Well it is, but lets do it as if you were building a real world application and include:

  1. Browser detection to only load the map for supported browsers
  2. Binding to the body onload method programmatically as you may not have access to the actual HTML tag
  3. Dispose the map when you are done
  4. Load the Virtual Earth JavaScript after the page has loaded to make things load fast
  5. Have a onLoadedMap method where you can add your data once the map has loaded
  6. Put your code and styles in external files from the HTML page itself

 vebasicspart1loadingthemapfiles_jiwr%20q Developer

 

LoadingTheMap.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Loading the Virtual Earth Map</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link href="css/Styles.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
    <script type="text/javascript" src="js/LoadingTheMap.htm.js"></script>
</head>
<body>
    <div id="mymap" style="position:relative; width:800px; height:600px; overflow:hidden;"></div>
</body>
</html>

The Virtual Earth controls requires some specific features in your HTML page:

  1. A DocType of XHTML
  2. A meta tag for UTF-8
  3. A <div></div> for the map itself with unique explicit ID
  4. Inline styles set on the map div setting:
    1. The position to either relative or absolute
    2. Width
    3. Height
    4. Recommended to hide any overflow, the ERO (popup) is rendered outside of this div.

 

In this example note that we do not reference the Virtual Earth JavaScript nor put any JavaScript in the HTML page itself. We reference our stylesheet, our “code-behind” external JavaScript file and the jQuery library.

 

Styles.css

body
{
    margin:0;
    padding:0;
}

.maploading
{
    background: url(ajax-loader.gif) center center no-repeat;
}

As we had to set the height and width of the map inline there is little to do here, I create a class for our loading animation.

 

LoadingTheMap.htm.js

//jquery 1.2.6 doesn't provide support to getScript from the local cache
//we need to add this ourselves currently
$.getScript = function(url, callback, cache) {
    $.ajax({
        type: "GET",
        url: url,
        success: callback,
        dataType: "script",
        cache: cache
    });
};

//our global map object
var map;

$(document).ready(function() {
    // This event is fired when the DOM is fully loaded
    // Is this browser supported by VE? If not why bother loading a broken control?
    if (!($.browser.msie) && !($.browser.mozilla) && !($.browser.safari)) {
        $("#mymap").html("Virtual Earth is not supported by your browser.")
    } else {
        // set a nice animated gif to show the map is loading
        $("#mymap").addClass("maploading");
        if (!($.browser.msie)) {
            //work around for non ie
            $.getScript("http://dev.virtualearth.net/mapcontrol/v6.2/js/atlascompat.js", "", true);
        }
        $.getScript("http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&onScriptLoad=onscriptload", "", true);
    }
});

function onscriptload() {
    // get rid of our load animation
    $("#mymap").removeClass("maploading");
    //load the map
    map = new VEMap('mymap');
    map.onLoadMap = onMapLoaded;
    map.LoadMap(new VELatLong(-27.47, 153.03), 16, VEMapStyle.Hybrid);
    //do nothing more to the map here, use the onMapLoaded event.
}

function onMapLoaded() {
    //here we can do what we want with the map object, add data etc.
}

$(window).unload(function() {
    // This event is fired when the web page is closing
    // Time to dispose our map
    if (map) map.Dispose();
});

First up jQuery has a nice helper to dynamically load our Virtual Earth JavaScript file but by default it appends a timestamp to prevent caching. At the time of writing we apply this override to provide this option.

We have four events:

  1. “$(document).ready” is when the DOM has loaded and is when we can make dynamic changes, like load the map, without breaking the page and getting the dreaded “operation aborted” error in IE.
  2. “onscriptload” is fired when the Virtual Earth JavaScript has fully loaded, this is when we can load the map.
  3. “onMapLoaded” is fired when the Virtual Earth Map has loaded, this is when we can load data onto the map and attach map events.
  4. “$(window).unload” is fired as the HTML page is unloaded, for example when navigating to another URL, we dispose our map object here.

Let’s walk through the actual steps involved, the comments in the code explain the code.

  1. First up lets check if the browser is actually supported by Virtual Earth (IE, FireFox and Safari), if not lets just show a message.
  2. While the map is loading lets put a nice animated gif on the map’s div to show it is loading. We do this using CSS.
  3. If the browser is not IE then we have to load the compatibility script prior to the VE script. This is a workaround that may become redundant in time.
  4. Load the Virtual Earth JavaScript
  5. Remove the loading animation
  6. Create the map
  7. Do something with the map
  8. Dispose the map

The creation of the Virtual Earth map is two lines of code:

map = new VEMap('mymap');
map.LoadMap(new VELatLong(-27.47, 153.03), 16, VEMapStyle.Hybrid);

First we create our map object passing the ID of the Div from our page in the constructor, the we load the map with our initial properties. The API defines this as:

VEMap.LoadMap(VELatLong, zoom, style, fixed, mode, showSwitch, tileBuffer, mapOptions);

Parameter Description

VELatLong

A VELatLong Class object that represents the center of the map. Optional.

zoom

The zoom level to display. Valid values range from 1 through 19. Optional. Default is 4.

style

A VEMapStyle Enumeration value specifying the map style. Optional. Default is VEMapStyle.Road.

fixed

A Boolean value that specifies whether the map view is displayed as a fixed map that the user cannot change. Optional. Default is false.

mode

A VEMapMode Enumeration value that specifies whether to load the map in 2D or 3D mode. Optional. Default is VEMapMode.Mode2D.

showSwitch

A Boolean value that specifies whether to show the map mode switch on the dashboard control. Optional. Default is true (the switch is displayed).

tileBuffer

How much tile buffer to use when loading map. Default is 0 (do not load an extra boundary of tiles). This parameter is ignored in 3D mode.

mapOptions

A VEMapOptions Class that specifies other map options to set.

Importantly all of these parameters are options, for example I only supplied the center, zoom and style.

The actual URL for the Virtual Earth JavaScript is:

http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2

Where the parameter “v” is the version. We supplied an additional optional parameter “onScriptLoad” that is the function executed when the script has fully loaded. The script itself is currently 217.7K compressed (943.6K uncompressed), it may take a few seconds to load on the clients browser, hence we only load it if it will be supported by the browser and after the initial page has loaded to provide a good user experience. The script has a complex cache expiry date to ensure that all users can receive monthly updates as required.

Additionally you can supply a “mkt” parameter to provide localized tiles, find and direction results. The following table provides the options currently available:

Language – Country/Region Culture Feature Support

Czech – Czech Republic

cs-CZ

VEMap.Find, VEMap.GetDirections

Danish – Denmark

da-DK

VEMap.Find, VEMap.GetDirections

Dutch – Netherlands

nl-NL

VEMap.Find, VEMap.GetDirections

English – Australia

en-AU

VEMap.GetDirections using MWS

English – Canada

en-CA

Map control dashboard, VEMap.Find, VEMap.GetDirections using MWS

English – India

en-IN

VEMap.GetDirections using MWS

English – United Kingdom

en-GB

VEMap.GetDirections using MWS

English – United States

en-US

All features. This is the default culture.

Finnish -Finland

fi-FI

VEMap.Find, VEMap.GetDirections

French – Canada

fr-CA

Map control dashboard, 3D dialogs, VEMap.Find, VEMap.GetDirections, map labels

French – France

fr-FR

Map control dashboard, 3D dialogs, VEMap.Find, VEMap.GetDirections, map labels

German – Germany

de-DE

Map control dashboard, VEMap.Find, VEMap.GetDirections, map labels

Italian – Italy

it-IT

Map control dashboard, 3D dialogs, VEMap.Find, VEMap.GetDirections, map labels

Japanese – Japan

ja-JP

Map control dashboard, 3D dialogs, VEMap.Find, map labels

Norwegian (Bokmal) – Norway

nb-NO

VEMap.Find, VEMap.GetDirections

Portuguese – Brazil

Pt-BR

VEMap.Find, VEMap.GetDirections

Portuguese – Portugal

pt-PT

VEMap.Find, VEMap.GetDirections

Spanish – Mexico

es-MX

VEMap.GetDirections using MWS, map labels

Spanish – Spain

es-ES

Map control dashboard, VEMap.Find, VEMap.GetDirections, map labels

Spanish – United States

es-US

Map control dashboard, VEMap.Find, VEMap.GetDirections using MWS, map labels

Swedish – Sweden

sv-SE

VEMap.Find, VEMap.GetDirections

 

Get the code

View a live demo HERE

Download the full source code HERE

Summary

In this article you have seen that, although the Virtual Earth is loaded in only two lines of JavaScript, to provide the best experience to your users and to ease your development some extra thought and logic is required. Feel free to download the code or view the live example. I would love to hear your feedback, suggestions and improvements. Stay tuned for the next article.