Metro: Understanding the default.js File

The goal of this blog entry is to describe — in painful detail — the contents of the default.js file in a Metro style application written with JavaScript. When you use Visual Studio to create a new Metro application then you get a default.js file automatically. The file is located in a folder named jsdefault.js.

image

The default.js file kicks off all of your custom JavaScript code. It is the main entry point to a Metro application. The default contents of the default.js file are included below:

// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
    "use strict";

    var app = WinJS.Application;

    app.onactivated = function (eventObject) {
        if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
            if (eventObject.detail.previousExecutionState !== Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            WinJS.UI.processAll();
        }
    };

    app.oncheckpoint = function (eventObject) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // eventObject.setPromise().
    };

    app.start();
})();

There are several mysterious things happening in this file. The purpose of this blog entry is to dispel this mystery.

Understanding the Module Pattern

The first thing that you should notice about the default.js file is that the entire contents of this file are enclosed within a self-executing JavaScript function:

(function () {

   ...

})();


Metro applications written with JavaScript use something called the module pattern. The module pattern is a common pattern used in JavaScript applications to create private variables, objects, and methods. Anything that you create within the module is encapsulated within the module.

Enclosing all of your custom code within a module prevents you from stomping on code from other libraries accidently. Your application might reference several JavaScript libraries and the JavaScript libraries might have variables, objects, or methods with the same names. By encapsulating your code in a module, you avoid overwriting variables, objects, or methods in the other libraries accidently.

Enabling Strict Mode with “use strict”

The first statement within the default.js module enables JavaScript strict mode:

'use strict';

Strict mode is a new feature of ECMAScript 5 (the latest standard for JavaScript) which enables you to make JavaScript more strict. For example, when strict mode is enabled, you cannot declare variables without using the var keyword. The following statement would result in an exception:

hello = "world!";

When strict mode is enabled, this statement throws a ReferenceError. When strict mode is not enabled, a global variable is created which, most likely, is not what you want to happen. I’d rather get the exception instead of the unwanted global variable.

The full specification for strict mode is contained in the ECMAScript 5 specification (look at Annex C):

http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf

Aliasing the WinJS.Application Object

The next line of code in the default.js file is used to alias the WinJS.Application object:

var app = WinJS.Application;

This line of code enables you to use a short-hand syntax when referring to the WinJS.Application object: for example,  app.onactivated instead of WinJS.Application.onactivated. The WinJS.Application object  represents your running Metro application.

Handling Application Events

The default.js file contains an event handler for the WinJS.Application activated event:

app.onactivated = function (eventObject) {
    if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
        if (eventObject.detail.previousExecutionState !== Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
            // TODO: This application has been newly launched. Initialize
            // your application here.
        } else {
            // TODO: This application has been reactivated from suspension.
            // Restore application state here.
        }
        WinJS.UI.processAll();
    }
};

This WinJS.Application class supports the following events:

· loaded – Happens after browser DOMContentLoaded event. After this event, the DOM is ready and you can access elements in a page. This event is raised before external images have been loaded.

· activated – Triggered by the Windows.UI.WebUI.WebUIApplication activated event. After this event, the WinRT is ready.

· ready – Happens after both loaded and activated events.

· unloaded – Happens before application is unloaded.

The following default.js file has been modified to capture each of these events and write a message to the Visual Studio JavaScript Console window:

(function () {
    "use strict";

    var app = WinJS.Application;

    WinJS.Application.onloaded = function (e) {
        console.log("Loaded");
    };

    WinJS.Application.onactivated = function (e) {
        console.log("Activated");
    };

    WinJS.Application.onready = function (e) {
        console.log("Ready");
    }

    WinJS.Application.onunload = function (e) {
        console.log("Unload");
    }

    app.start();
})();

When you execute the code above, a message is written to the Visual Studio JavaScript Console window when each event occurs with the exception of the Unload event (presumably because the console is not attached when that event is raised).

image

 

Handling Different Activation Contexts

The code for the activated handler in the default.js file looks like this:

app.onactivated = function (eventObject) {
    if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
        if (eventObject.detail.previousExecutionState !== Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
            // TODO: This application has been newly launched. Initialize
            // your application here.
        } else {
            // TODO: This application has been reactivated from suspension.
            // Restore application state here.
        }
        WinJS.UI.processAll();
    }
};

Notice that the code contains a conditional which checks the Kind of the event (the value of e.detail.kind). The startup code is executed only when the activated event is triggered by a Launch event,

The ActivationKind enumeration has the following values:

· launch

· search

· shareTarget

· file

· protocol

· fileOpenPicker

· fileSavePicker

· cacheFileUpdater

· contactPicker

· device

· printTaskSettings

· cameraSettings

Metro style applications can be activated in different contexts. For example, a camera application can be activated when modifying camera settings. In that case, the ActivationKind would be CameraSettings. Because we want to execute our JavaScript code when our application first launches, we verify that the kind of the activation event is an ActivationKind.Launch event.

There is a second conditional within the activated event handler which checks whether an application is being newly launched or whether the application is being resumed from a suspended state. When running a Metro application with Visual Studio, you can use Visual Studio to simulate different application execution states by taking advantage of the Debug toolbar and the new Debug Location toolbar. 

image

image

Handling the checkpoint Event

The default.js file also includes an event handler for the WinJS.Application checkpoint event:

app.oncheckpoint = function (eventObject) {
    // TODO: This application is about to be suspended. Save any state
    // that needs to persist across suspensions here. You might use the
    // WinJS.Application.sessionState object, which is automatically
    // saved and restored across suspension. If you need to complete an
    // asynchronous operation before your application is suspended, call
    // eventObject.setPromise().
};

The checkpoint event is raised when your Metro application goes into a suspended state. The idea is that you can save your application data when your application is suspended and reload your application data when your application resumes.

Starting the Application

The final statement in the default.js file is the statement that gets everything going:

app.start();

Events are queued up in a JavaScript array named eventQueue . Until you call the start() method, the events in the queue are not processed. If you don’t call the start() method then the Loaded, Activated, Ready, and Unloaded events are never raised.

Summary

The goal of this blog entry was to describe the contents of the default.js file which is the JavaScript file which you use to kick off your custom code in a Windows Metro style application written with JavaScript. In this blog entry, I discussed the module pattern, JavaScript strict mode, handling first chance exceptions, WinJS Application events, and activation contexts.

Discussion

  1. Andrey says:

    WinJS.Application.onloaded = function() { … } – not a very good practice, imho. What if several event handlers needs to be attached?