Using JavaScript in the Bing Maps Trip Optimizer sample

 

The HTML and JavaScript portion of Bing Maps Trip Optimizer defines the user interface. The UI collects locations from the user and displays the shortest route among all locations on a Bing Maps AJAX control. This document describes how the JavaScript portion of the app is organized, and how the local context and the web context communicate with each other. It also describes some of the key migration points to keep in mind.

The JavaScript portion uses standard CSS, HTML, and JavaScript to define the UI. This document doesn't explain these elements in detail. But it does explain the elements that make a JavaScript web app different from a JavaScript Windows 8.x Store app.

Note

The sample code that corresponds to this document is found in the Bing Maps trip optimizer sample.

In this article

The local context and the web context

A Windows 8.x Store app using JavaScript contains at least one HTML page. That page, and any other pages you include in the app itself, generally run in the app's local context. When you use an iframe to navigate to a remote page, that page runs in the web context and has limited access to your system. For more info about the different restrictions and features available to pages in the local and web contexts, see .0902FD81-A27D-4098-A0D6-0CEFACE2278C

Bing Maps Trip Optimizer separates the UI into two pairs of HTML, CSS, and JavaScript files. We felt that separating code that references the Windows Runtime from code that references the web made the app easier to maintain. The files default.html, default.css, and default.js reference the Windows Runtime—this includes the custom C++ Windows Runtime component—but do not access the web. default.html, default.css, and default.js represent the main page of the app. The files web.html, web.css, and web.js access the web, but do not access the Windows Runtime. The content of web.html is an inline frame of the local context.

The following illustration shows the relationship between the local context and the web context. How these contexts communicate is discussed later in this document.

Security Note

Maintaining web code in a separate module also helps increase the security of an app. When possible, validate data that you receive in the local context from the web context so that you can minimize the chance of security vulnerabilities such as buffer overrun.

Referencing the web context from the local context

The body tag of the local context (default.html) defines an inline frame (iframe) tag that holds the web context (web.html).

<iframe id="mapFrame" src="ms-appx-web:///html/web.html" style="position: absolute; left: 0px; width: 100%; top: 0px; height: 100%; overflow: hidden"></iframe>

When you reference a code file in your JavaScript Windows 8.x Store app, it's important to use this syntax:

src="ms-appx-web://<package-name>/<file-name>"

You can omit the <package-name> part if the target file is part of the same package as the calling file. You can find the package name in the application manifest. To do so, in Visual Studio, open the package.appxmanifest file and choose the Packaging tab. For more information about the navigation features that are new to Windows 8.x Store apps written in JavaScript, see .7657CFA0-C71F-44F2-AAA2-AF571CC3E31B

Communication between contexts

The local context and the web context use cross-document messaging to communicate. Before the contexts can communicate, they must first register for messaging events. Both default.html and web.html specify an onLoad function for the onload property of the body tag. Both onLoad functions call the addEventListener method to listen to events of the type message and route those messages to the receiveMessage function. The following example shows the onLoad function for the local context.

function onLoad() {
    "use strict";
    window.addEventListener("message", receiveMessage, false);
}

Important

Bing Maps Trip Optimizer uses cross-document messaging because one context can't directly access the DOM of another context.

After the contexts register for messaging events, they can use the postMessage method to communicate. This method sends a cross-document message that's routed to the message event handler, the receiveMessage function, of the other context. Because cross-document messages are text-based, the app and web contexts use the JSON.stringify function to serialize messages into JSON text. When a context receives a message, it calls the JSON.parse function to deserialize the fields back from the JSON text.

To illustrate how the contexts communicate, consider how the web context communicates to the local context to initialize the custom C++ Windows Runtime component. (Recall that the web context can't interact with the Windows Runtime component directly). The onLoad function that's defined in the web context, web.js, is called during initialization.

web.js

// Called when the page loads.
function onLoad() {
    "use strict";
    // Hook to main frame for incoming messages.
    window.addEventListener("message", receiveMessage, false);

    // Disable input.
    disableElement(inputArea, true);

    // Load the C++ component.
    optimizerLoad();

    // Load a default map.
    Microsoft.Maps.loadModule('Microsoft.Maps.Overlays.Style', {
        callback: function () {

            map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), {
                mapTypeId: "r",
                center: new Microsoft.Maps.Location(45.5, -80.5),
                zoom: 4,
                enableClickableLogo: false,
                enableSearchLogo: false,
                customizeOverlays: true,
                showBreadcrumb: true
            });
        }
    });

    // Reset waypoints.
    resetWaypoints();
}

The onLoad function calls the optimizerLoad function. The optimizerLoad function communicates to the local context to initialize the C++ Windows Runtime component.

web.js

function optimizerLoad() {
    "use strict";
    var message = { "invoke": "load" };
    window.parent.postMessage(JSON.stringify(message), "*");
}

We initiate the loading of the Windows Runtime component from the web context instead of directly from the local context to ensure that both contexts are loaded before the Windows Runtime component is created.

The receiveMessage function in the local context parses the message and routes the call to the appropriate message handler. In this case, the invoke field of the deserialized JavaScript object is "load"; therefore, the local context calls the optimizerLoad function.

default.js

function receiveMessage(message) {
    "use strict";
    // Verify event origin.
    if (message.origin !== "ms-appx-web://microsoft.sdksamples.tripoptimizer.js") {
        return;
    }

    var data = JSON.parse(message.data);
    if (data.invoke === "load") {
        optimizerLoad();
    } else if (data.invoke === "optimizeTrip") {
        optimizerOptimizeTrip(
            data.locations,
            data.travelMode,
            data.optimize,
            data.bingMapsKey,
            data.alpha,
            data.beta,
            data.rho,
            data.iterations,
            data.parallel);
    } else if (data.invoke === "cancel") {
        optimizerCancel();
    } else if (data.invoke === "alert") {
            // Show message dialog.            
            new Windows.UI.Popups.MessageDialog(data.message).showAsync().then();
    }
}

The details of the optimizerLoad function in the local context are explained in Interoperating between JavaScript and C++ in the Bing Maps Trip Optimizer sample.

Migration from ActiveX

For information about how we migrated from the ActiveX version of Bing Maps Trip Optimizer to a Windows 8.x Store app, see Migrating existing code in the Bing Maps Trip Optimizer sample.

Next steps

Read Using C++ in the Bing Maps Trip Optimizer sample to learn how Bing Maps Trip Optimizer uses C++ to perform computationally intensive operations and thereby improve overall performance.

See Also

72CE58AA-D870-47B6-A25B-4EE5850D460A