Geocoding and Routing in Bing Maps Windows Store Apps (JavaScript)

In this blog post we are going to look at how implement Geocoding and Routing using the Bing Maps Windows Store App JavaScript SDK. If you are new to JavaScript development with the Bing Maps Windows Store App SDK I recommend reading the Getting started with Bing Maps Windows Store Apps blog post first. We will also be making use of Bing Maps Modules. If you are unfamiliar with modules, I recommend reading the blog post: Modules in Bing Maps Windows Store Apps.

Geocoding is one of the most common tasks done by users of online maps. Geocoding is the process of taking an address or query and returning its equivalent coordinate on the map. Routing is the task of calculating the directions between two or more locations. In Bing Maps there are a lot of different options around routing such as routing by different modes of transportation; driving, walking, or transit. In Bing Maps there are several ways to carry out these tasks. The most common method is to use the Bing Maps REST services which are very easy to use from just about any programming language. In the JavaScript version of Bing Maps there a modules which wraps the REST services and exposes it as an easy to use JavaScript library. We will be making use of the Search module for geocoding and the Directions module for routing.

Setting up the project

To set up the project open Visual Studios 2012 and create a new project. In the window that opens select JavaScript -> Windows Store. Select the Blank App template, call the application BingMapsSearch_WinRTJS and press OK.

To keep things clean, we are going to create a separate CSS Style Sheet and JavaScript file for our application. To do this, right click on the js folder and select Add -> New Item. Create a new JavaScript file called BingMapsSearch.js. Then, right click on the css folder and select Add -> New Item and create a new Style Sheet called BingMapsSearch.css.

At this point your Solution should look something like this:

win8_project_geo_thumb-1.jpg

Next, you’ll want to add a reference to the Bing Maps JavaScript library. Right click on the References folder and press Add Reference. Then select Windows -> Extensions and select Bing Maps for JavaScript. If you do not see this option, you may want to verify that you have installed the Bing Maps for Windows Store App SDK .

We can now open up the default.html file and add references to the Bing Maps SDK along with references to our CSS Style Sheet and JavaScript file. To do this, simply add the following in the head of the page:

<!– Bing Maps references –>

<script type=”text/javascript” src=”ms-appx:///Bing.Maps.JavaScript//js/veapicore.js”></script>

<script type=”text/javascript” src=”ms-appx:///Bing.Maps.JavaScript//js/veapimodules.js”></script>

 

<!– Our Bing Maps CSS & JavaScript Code –>

<link href=”/css/BingMapsSearch.css” rel=”stylesheet” />

<script src=”/js/BingMapsSearch.js”></script>


Creating the UI Layout

Before we worry about how to do all the programming of the logic required for this application, let’s first focus on creating the UI. For this app we are going to have a panel on the left side where all our input controls will reside and the map will fill up the rest of the space to the right. In the left frame we will have Clear Map button, an area for inputting geocode and route requests, and a div for rendering routing itineraries. The geocode input area will consist of a single textbox and a button. The routing input area will have two textboxes and a button. The HTML for the default.html file should look like this:

<!DOCTYPE html>

<html>

<head>

    <meta charset=”utf-8″ />

    <title>BingMapsSearch_WinRTJS</title>

 

    <!– WinJS references –>

    <link href=”//Microsoft.WinJS.1.0/css/ui-dark.css” rel=”stylesheet” />

    <script src=”//Microsoft.WinJS.1.0/js/base.js”></script>

    <script src=”//Microsoft.WinJS.1.0/js/ui.js”></script>

 

    <!– BingMapsSearch_WinRTJS references –>

    <link href=”/css/default.css” rel=”stylesheet” />

    <script src=”/js/default.js”></script>

 

    <!– Bing Maps references –>

    <script type=”text/javascript”

            src=”ms-appx:///Bing.Maps.JavaScript//js/veapicore.js”></script>

    <script type=”text/javascript”

            src=”ms-appx:///Bing.Maps.JavaScript//js/veapimodules.js”></script>

 

    <!– Our Bing Maps CSS & JavaScript Code –>

    <link href=”/css/BingMapsSearch.css” rel=”stylesheet” />

    <script src=”/js/BingMapsSearch.js”></script>

</head>

<body>

    <div class=”leftFrame”>

        <!– Clear Map Button–>

        <div style=”height:30px;“>

            <button onclick=”ClearMap();” class=”greenBtn”>Clear Map</button>

        </div>

 

        <!– Geocoding Input –>

        <div style=”height:100px;“>

            <h2>Geocode</h2>

            <input id=”searchTbx” type=”text” style=”width:240px;“/>

            <button onclick=”Geocode();” class=”greenBtn”>Go</button>

        </div>

 

        <!– Routing Input –>

        <div style=”height:150px;“>

            <h2>Route</h2>

            From: <input id=”fromTbx” type=”text” style=”width:200px;“/>

            To: <input id=”toTbx” type=”text” style=”margin-left:17px;width:200px;“/>

            <button onclick=”GetRoute();” class=”greenBtn”>Get Directions</button>

        </div>    

 

        <!– Route Itinerary Area –>

        <div id=”itineraryDiv”></div>

    </div>

 

    <!– Map Area–>

    <div id=”myMap”></div>

</body>

</html>

To keep things clean we will add some of the styling information into the BingMapsSearch.css file. Add the following to this file:

.leftFrame {

    position:absolute;

    height:100%;

    width:260px;

    padding:10px;

    background-color:#808080;

    overflow-y:auto;

}

 

.greenBtn {

    background-color:green;

    float:right;

    margin-right:15px;

}

 

#myMap {

    position:absolute;

    width:100%;

    height:100%;

    margin-left:280px;

}

 

#itineraryDiv {

    position:absolute;

    width:240px;

}

At this point we can run the application and see what it looks like. You should end up with something like this:

win8_geo_layout_thumb-1.jpg

Note that the map does not appear as we have not yet added the logic to load it. Also, since we haven’t wired up any of the functionality for the buttons, clicking on them now would throw an error.

Loading the Bing Maps Control

We will add the functionality to load the Bing Maps control to the BingMapsSearch.js file. We are now going to create three global variables called: map, searchManager and directionsManager. Next, we will create a function called GetMap which will load the Bing Maps control for us. The GetMap function will be loaded after the Microsoft.Maps.Map module has completed loading. Your code should look like this:

var map, searchManager, directionsManager;

 

function GetMap() {

    var mapOptions =

    {

        credentials: “YOUR_BING_MAPS_KEY”,

        zoom: 2

    };

 

    map = new Microsoft.Maps.Map(document.getElementById(“myMap”), mapOptions);

}

 

//Initialization logic for loading the map control

(function () {

    function initialize() {

        Microsoft.Maps.loadModule(‘Microsoft.Maps.Map’, { callback: GetMap });

    }

 

    document.addEventListener(“DOMContentLoaded”, initialize, false);

})();


Adding the Geocoding Logic

When a user adds content to the searchTbx textbox and presses the Go button a request will be fired to a Geocode function. For this functionality we will be making use of the Search module. The first thing we will do in this function is check to see if the searchManager variable has been initialized. If it hasn’t, we will load the Search module and initialize this variable and then process the search request. If this variable has been initialized, we will then create a geocode request passing in the users input value and requests a maximum of 1 result. We will also pass in the names of callback functions that get called if the request is successful or not.

If the request is successful we will display the result on the map with a pushpin and zoom into the location. If it is not successful, we will alert the user. The request will then be geocoded against the search manager. I would like to take a moment to point out that the alert JavaScript function that is commonly used in web development is not supported in Windows Store Apps. Instead, we need to make use of the Windows.UI.Popups.MessageDialog class. And since this is likely something we will want to use regularly, we will create a simple function for displaying messages to the user called ShowMessage. Add the following code to the BingMapsSearch.js file.

function GeocodeModule() {

    ClearMap();

 

    if (searchManager) {

        var request = {

            where: document.getElementById(‘searchTbx’).value,

            count:1,

            callback: geocodeCallback,

            errorCallback: geocodeError

        };

 

        searchManager.geocode(request);

    } else {

        //Load the Search module and create a search manager.

        Microsoft.Maps.loadModule(‘Microsoft.Maps.Search’, {

            callback: function () {

                //Create the search manager

                searchManager = new Microsoft.Maps.Search.SearchManager(map);

 

                //Perfrom search logic

                Geocode();

            }

        });

    }

}

 

function geocodeCallback(response, userData) {

    if (response &&

        response.results &&

        response.results.length > 0) {

        var r = response.results[0];

        var l = new Microsoft.Maps.Location(r.location.latitude, r.location.longitude);

 

        //Display result on map       

        var p = new Microsoft.Maps.Pushpin(l);

        map.entities.push(p);

 

        //Zoom to result

        map.setView({ center: l, zoom : 15 });

    } else {

        ShowMessage(“Geocode Response”, “Not results found.”);

    }

}

 

function geocodeError(request) {

    ShowMessage(“Geocode Error”, “Unable to Geocode request.”);

}

 

function ShowMessage(title, msg) {

    var m = new Windows.UI.Popups.MessageDialog(title, msg);

    m.showAsync();

}

 

Adding the Routing Logic

When a user adds content to the fromTbx and toTbx textboxes and presses the Get Directions button a request will be fired to a GetRoute function. For this functionality we will be making use of the Directions module. The first thing we want to do in this function is to verify that the directionsManager variable has been initialized. If it hasn’t, we will load the Directions module and initialize this variable and then process the route request. If this variable has been initialized, we will then pass the start and end points to the directions manager and pass in the itinerary div id as the location to display the directions. We will then have the directions manager calculate the directions. Add the following code to the BingMapsSearch.js file.

function GetRoute() {

    ClearMap();

 

    if (directionsManager) {

        // Set Route Mode to driving

        directionsManager.setRequestOptions({ routeMode: Microsoft.Maps.Directions.RouteMode.driving });

 

        // Create start and end waypoints

        var startWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById(‘fromTbx’).value });

        var endWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById(‘toTbx’).value });

 

        directionsManager.addWaypoint(startWaypoint);

        directionsManager.addWaypoint(endWaypoint);

 

        // Set the id of the div to use to display the directions

        directionsManager.setRenderOptions({ itineraryContainer: document.getElementById(‘itineraryDiv’) });

 

        // Calculate directions, which displays a route on the map

        directionsManager.calculateDirections();

    } else {

        //Load the Directions module and create a directions manager.

        Microsoft.Maps.loadModule(‘Microsoft.Maps.Directions’, {

            callback: function () {

                //Create the directions manager

                directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);

 

                //Perfrom route logic

                GetRoute();

            }

        });

    }

}

The directions manager takes care of notifying the user if there is an issue calculating the route such as one of the route points having ambiguous results. This saves use a lot of time as we won’t have to worry about handling and developing this functionality. Additionally, this gives us the ability to easily drag the route if we want to customize it or avoid an area.

Clearing the Map

Whenever we process a new geocode or route request we will want to clear the map. We will also need to create a function named ClearMap as this is needed for the Clear Map button. When this function is called we will want to remove any entities from the map and reset the directions manager. This is rather simple to do, just add the following code to the BingMapsSearch.js file.

function ClearMap() {

    map.entities.clear();

 

    if (directionsManager) {

        directionsManager.resetDirections();

    }

}

Running the App

At this point we have created all the functionality needed for the UI we created originally. If you run the app now you can make geocode and routing requests. Here is a screen shot of the app with a route from New York to Toronto.

win8_geo_complete_thumb-1.jpg

– Ricky Brundritt, EMEA Bing Maps Technology Solution Professional