Click here to Skip to main content
Click here to Skip to main content

Toob - London Underground travel app

, 4 Oct 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
Toob is a Windows 8 London Underground travel information app.

Introduction

Toob is an HTML5 entry in the AppInnovation contest, and, unfortunately, it is a closed source project so I will not be making the full source code available.  However, as well as introducing the application I will explain some elements of developing an HTML5 Windows Store application and provide relevant links relevant links to give anyone developing such an application a helpful starter. 

Application Overview 

Toob is a Windows Store application providing up-to-date London Underground travel information.  Travelling on the Tube is an integral part of most Londoners' lives and advance awareness of its status can make a genuine difference to the planning of their days.  Transport For London does publish this information, but Toob makes it ever-present at your fingertips, ready to use in conjunction with other applications, providing the beautiful and integrated user experience we all expect of modern devices.

In its current state the application consists of only a handful of screens.  The main screen is a hub showing the colour-coded lines of the London Underground and their current status.  The lines are sorted according to Transport For London guidelines, with the lines by decreasing issue status severity.  The combination of the ordering and bold, clear icons allows the user to very quickly see the state of the network and/or any particular line they are interested in.  Further information such as station issues and an interactive map are to be added in due course.

Toob Overview Screen

Individual lines can then be selected to see more detail.  Here the further information regarding the line's status is presented, as well as information about any individual stations on the line with issues and details of scheduled downtime for the coming weekend.  For those wanting to while away a little time, a brief history of the line is also presented.

Toob Piccadilly Line Screen

The application supports the various Windows 8 view states, such as the snapped view shown below, and includes various other Windows 8 features such as a live tile and search.  More details on some of these features are given in their respective sections below.

Toob Overview Screen in Snapped mode

Background Information

State

In Windows 8, the system manages which applications run rather than the user.  That is, the current foreground application runs but all other applications are suspended, or paused, by the system.  Eventually the system may terminate applications if machine resources become a little tight.  Applications aren't terminated in a first-in, first-out order, but rather the system determines the most suitable application(s) to terminate based on their resource usage.  When an application is being suspended it gets notified by the system and has a few seconds to save its state as appropriate.  However, on termination the application is not notified, so from a developers point of view suspension should be seen as termination.  The reason applications are suspended rather than left running in the background as happens in previous version of Windows is to ensure the system is less resource-intensive, thereby improving things like battery life on modern mobile devices.  The reason they are initially suspended rather than just terminated is to allow the user to instantly swap between applications because the applications do not need to initialise each time.

The following diagram represents the state model and transitions that occur in Windows 8.  For developers, it is important to consider the appropriate behaviour for your application in all the possible transitions, in particular the different kinds of activation.  ActivationKind enumerates the different types of ways an application can be launched.

Windows Store State Model

Development Tools

Unsurprisingly, Visual Studio 2012 for Windows 8 is currently the best/only choice of IDE when it comes to developing Windows Store applications.  It includes all the necessary libraries and a variety of useful features and templates specifically designed around the Windows Store UX and technical guidelines that make life a lot easier.  For HTML5 development, all the predefined code of interest lives under the WinJS namespace, from UI controls to animation and utility libraries.  When it comes to debugging and testing, Visual Studio 2012 includes support for running your application on the local machine, a remote machine, or a configurable simulator.  The simulator, in particular, is useful for testing touch interaction for those of us stuck with clunky old desktops.  And finally, for those who prefer to edit HTML/CSS visually, Visual Studio 2012 ships with Microsoft's Blend tool.

More general background information about developing applications for Windows Store can be found here.

Pages

When developing an HTML5 Windows Store application it is recommended to use a single-page navigation model rather than the multi-page navigation model more commonly used on the web.  That is, rather than navigating to a different page to present another screen, a single page dynamically loads and unloads screens as appropriate.  At a high level this is to provide a more application-like experience, where the screen does not go blank when loading the next page.  At a more technical level it is because the script context would be destroyed and initialised on each navigation step, introducing a performance hit and the potential for a window where the application would not receive system events.  It also ensures that management of the application lifecycle is naturally contained in a single place.

To achieve a single-page navigation model you could use iframes (for external web content), an existing third party framework (you already know and love) or even roll your own solution (madness!).  However, WinJS includes the PageControlNavigator control and Page class to create a single-page navigation model specifically suited to Windows Store applications.  Visual Studio includes a number of project templates that generate the necessary stub code to get you up and running quickly with this framework.

The basics of this approach are that you add a PageControlNavigator at the top level single page as follows:

<!DOCTYPE html>
<html>
    ...
    <body>
        <div data-win-control="Application.PageControlNavigator" 
             data-win-options="{ home: '/pages/overview/overview.html' }"
        >
        </div>
    </body>
</html>

An element with a data-win-control attribute is how WinJS controls are declared.  A call to WinJS.UI.processAll() in the application activation code ensures that the defined WinJS control is added to the specified element at start-up.  The data-win-options attribute specifies properties that are set on the injected WinJS control.  So in this case we are creating a PageControlNavigator instance where the URL of the home page has been set to /pages/overview/overview.html.  The PageControlNavigator also requires some additional JavaScript to add various interactivity behaviours.  Visual Studio automatically generates this code for you when one of its Windows Store templates is used, and this is the way I would recommend to add this feature.

Individual application screens comprise of an HTML file for the view mark-up, a JavaScript file for logic and a CSS file for styling, collectively known as a Page.  Once again, Visual Studio generates a stub template of the expected files whenever you add a Page Control item.  The HTML and CSS files are completely standard, but the JavaScript file is of more interest:

// declare the page as a JavaScript object mapped to the URL of its corresponding HTML file
WinJS.UI.Pages.define("/pages/page/page.html", {
    ready: function (element, options) {
        // called when the user navigates to the page
        // element is the root element of the page
        // options is the optional arguments object passed when navigating to the page
    },
    updateLayout: function (element, viewState, lastViewState) {
        // called when the view state changes, e.g. from full screen to snapped view, allowing 
        // you to update the layout appropriately

        // element is the root element of the page
        // viewState is the type of the new view state
        // lastViewState is the type of the previous view state
    },
    unload: function() {
        // called when navigating away from the page
    }
});

When it comes to the development of individual pages, many of the WinJS controls are very useful.  For example, the ListView control creates the hub behaviour and layout used in many Windows Store applications, including Toob, and Visual Studio 2012 includes templates specifically tailored towards its use.

More details about WinJS controls are available here.

Data Fetching

One of the first things Toob, and most other consumption applications, need to do on start-up is to fetch fresh content.  In HTML5 Windows 8 applications this can be done as in most HTML5 applications or websites: with an asynchronous HTTP request returning JSON.  WinJS provides the xhr function to do just this.  It takes an object containing the usual required and optional arguments for an HTTP request such as url, type and headers.  It also returns a Promise instance, which is the Windows 8 mechanism for asynchronous programming.  The two most commonly used functions on a Promise for asynchronous programming, then and done are very similar yet subtly different.  Both take three handler functions as parameters: the first to respond to successful completion of the promise, the second to respond when the promise is fulfilled with an error and the last to respond to progress reports.  The difference between then and done are that the former returns another Promise while the latter returns nothing.  This means then calls can be chained together to add behaviour as appropriate.  A consequence of this difference that is worth being aware of is that if an error occurs during execution of a handler then with done the error will be thrown, where as with then it results in the returned Promise being marked as in error.

More details about asynchronous programming in JavaScript for Windows Store applications is available here.

The following is an example of an xhr call with asynchronous result handling:

WinJS.xhr({ url: "http://www.example.com" }).then(
    function onSuccess(request) {
        // handle success response
        var data = JSON.parse(request.responseText);
    },
    function onError(request) {
        // handle error response
    },
    function onProgress(request) {
        // report on request progress
    }
);

One issue to consider when loading data at start-up is that Windows only allows applications a few seconds to launch while its splashscreen is showing.  This means that it is usually a bad idea to make HTTP request at this stage, since there is limited control of how quickly this will complete.  As such, the recommended practice is to defer data loading until after the splashscreen has been removed.  For the sake of the user experience, it is worth making the screen displayed when loading data identical to the preceeding splashscreen (so that no transition is seen by the user) and to add in a loading animation.  You can see exactly this behaviour in the standard Windows Store applications such as Weather when they are loaded from scratch.

Data Binding

Once data has been loaded, it needs to be displayed in the user interface.  This can be done through standard DOM manipulation with JavaScript or the more dynamic binding utilities available in WinJS.  Most of the WinJS controls, such as ListView, support binding out of the box, allowing you to declare HTML templates to render individual items in the ListView's data source.  For example:

<!-- the list view -->
<div class="list win-selectionstylefilled"
     data-win-control="WinJS.UI.ListView"
     data-win-options="{ itemTemplate: select('itemTemplate;) }"
>
</div>

<!-- the template for rendering each item -->
<div class="itemTemplate" data-win-control="WinJS.Binding.Template">
    <div class="item" data-win-bind="textContent: name"></div>
</div>

As we've already seen, a WinJS control is declared by creating an element with the data-win-control attribute identifying the control type and the data-win-options attribute declaring properties to be set on the control.  In this case we have two controls, a ListView and a Template, with the template being set as the itemTemplate on the list.  Note that templates do not show in your page, so you are free to place them anywhere in the page's HTML body.  The interesting part of the template is the data-win-bind attribute.  This can contain a semi-colon-separated list of name/value pairs, where name is the name of the property on the element and the value is the name of a property on the data item to which the template will be applied.  This creates a binding so that the specified value of any item rendered using that template will automagically be set on the specified property of the element.

All that is required from the JavaScript side is to populate the ListView with data.  This is done by setting the data source on the ListView to the dataSource property of a new WinJS.Binding.List instance (which in turn usually wraps an array of data objects).  For example, we could have the following code to go with the HTML above:

WinJS.UI.Pages.define("example.html", {
    // set up the list view any time someone navigates to this page
    ready: function (element, options) {
        // the data items
        var data = [ { name: "Bakerloo" },
                     { name: "Central" },
                     { name: "Circle" },
                     { name: "District" },
                     { name: "DLR" },
                     { name: "Hammersmith & City" },
                     { name: "Jubilee" },
                     { name: "Metropolitan" },
                     { name: "Northern" },
                     { name: "Overground" },
                     { name: "Piccadilly" },
                     { name: "Victoria" },
                     { name: "Waterloo & City" } ];
                     
        // the bindable list of data items
        var list = new WinJS.Binding.List(data);
        
        // get the list view control
        var listView = element.querySelector(".list").winControl;
        
        // set the bindable list on the list view
        listView.itemDataSource = list.dataSource;
    }
});

The result of would look something like this (depending on how you styled it in CSS):

This is only one of the basic building blocks that can be used for data binding, but it forms the basis of how the Toob overview screen is implemented, for example.  To go into more detail about binding is beyond the scope of this article.

More details about data binding are available here.

Searching

Windows 8's Search Charm is a search tool not dissimilar to OS X's Spotlight feature.  It is a selection-based search system that enables users to search not only for applications or files, but also application content.  This means that applications can hook into the search to supply up to 5 auto-completing prompts or outright result suggestions when triggered to do so by the system.  It is also a quick and easy way for users to launch applications or check information without necessarily executing the search.

Further reading about adding search to an application is available here.

In the case of Toob, users may want to go directly to a particular line's status page or simply get a quick glance at a particular line's status.  Alternatively, they may just be seeking to launch the application.  The Search Charm can easily serve all these different purposes with relatively little coding, although there are are potentially many different use cases and entry points to consider.

Toob Search Charm recommendations

First and foremost, to hook into the Search Charm, the Search declaration must be added to the application's manifest file, package.appxmanifest.  This is done on the Declarations tab in the GUI presented by Visual Studio upon opening the manifest file, and involves nothing more than selecting Search from the Available Declarations and adding it.

Adding search suggestions can then be done by responding to the onsuggestionsrequested event from SearchPane, as shown in the code below.  There are two kinds of suggestions an application can present: queries and results.  The former are plain text suggestions based on the search query entered so far, while the latter are outright results available in the application.  A total of 5 suggestions are permitted, made up of any combination of queries and results.  Suggestions are added by calling the appropriate functions on the SearchSuggestionCollection included in the event's request object: appendQuerySuggestion for queries and appendResultSuggestion for results.

The following code is an example from Toob shows lines being added as result suggestions:

Windows.ApplicationModel.Search.SearchPane.getForCurrentView().onsuggestionsrequested = 
  function (args) {
    var maxNumberOfSuggestions = 5;
    var query = args.queryText.toLowerCase();
    var request = args.request;
    for (var i = 0; i < lines.length; i++) {
        if (line.name.toLowerCase().indexOf(query) === 0) {
            // the name to show in the result suggestion on the search charm
            var name = line.name;
            // the details to show in the result suggestion on the search charm
            var detail = line.status;
            // a unique identifier for the suggested result, this will be passed back to
            // the app if the result is selected
            var tag = line.id;
            // an image to show in the result suggestion on the search charm, to ensure
            // users can easily differentiate between query suggestions and result suggestions
            var image = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(
                new Windows.Foundation.Uri("ms-appx:///images/" + name + ".png"));
            // alt text for the above image
            var imageAltText = line.name;
            
            request.searchSuggestionCollection.appendResultSuggestion(name,
                                                                      detail, 
                                                                      tag, 
                                                                      image, 
                                                                      imageAltText);
            
            // check if we have reached the maximum allowable number of suggestions
            if (request.searchSuggestionCollection.size === maxNumberOfSuggestions) {
                break;
            }
        }
    }
};

Depending on whether the user enters a query - either by typing and executing the search or by selecting a query suggestion - or selects a result suggestion different events are triggered for the application to respond to.  For a query it is onquerysubmitted, which in Toob is handled roughly as follows:

Windows.ApplicationModel.Search.SearchPane.getForCurrentView().onquerysubmitted = 
  function (args) {
    if (!args.queryText || args.queryText == "") {
        // if no query text then we assume the user is using the search to launch the app
        // so we navigate to the main screen
        WinJS.Navigation.navigate("/pages/overview/overview.html");
    }
    else {
        // otherwise we navigate to the search results page, passing along the search arguments
        WinJS.Navigation.navigate("/pages/searchResults/searchResults.html", args);
    }
};

When a result suggestion is selected, the onresultsuggestionchosen event is triggered.  In Toob this means the details of the selected line should be displayed, so the handler looks roughly as follows:

Windows.ApplicationModel.Search.SearchPane.getForCurrentView().onresultsuggestionchosen =
  function (args) {
    // navigate to the line details page, with the id of the selected line as the argument
    WinJS.Navigation.navigate("/pages/line/line.html", { line: args.tag });
};

Note that launching using the search is one of the ActivationKinds for applications, so you likely need to handle this as a special case in your application launch code.

Although there are many parts and considerations when adding search, Visual Studio provides some help in the form of the Search Contract item available when adding a New Item.  This sets automatically updates the manifest file appropriately and adds stub code to handle the appropriate events and application launch and a search results page template.  This is a useful starting point, but in my experience it often makes sense to refactor the generated code so that it integrates more closely with the rest.

Sharing

Another powerful feature of Windows 8 is the Share Charm.  As implied by its name, the Share Charm is a mechanism whereby the user can easily exchanged information between applications, rather like an advanced copy and paste feature.  Unlike the clipboard (which is still available!), it provides a single, consistent UI that is particularly suited to touch so that users don't end up confused by endless variations on how to copy and paste and developers have to do little more than hook in to a simple API.  Furthermore, by including this functionality the "Tap and send" feature becomes available through the Devices Charm, allowing content to be easily shared with nearby friends using Near Field Communication.  Content can be shared in a variety of pre-defined formats, such plain text, links, HTML, files or images, or as custom formats.  Any application can choose to share out content and/or mark itself consumer of particular formats of shared content from other applications.

Further reading about sharing and exchanging data is available here.

In the case of Toob, users are likely to want to quickly inform others of any potential travel issues, whether that be through social networks, e-mail or SMS.  Rather than support numerous different APIs and all the UI/UX difficulties that go along with them, we can let the users' other applications take care of that for us and simply make the travel information in Toob available through the Share Charm.  The status information is shared as plain text, since this is ample for its needs and will open up the sharing to the widest range of consumption options.

Toob with Share Charm

Sharing is done through the DataTransferManager by listening to its ondatarequested event.  This event is triggered whenever a user selects the Share Charm, and includes a DataRequest object containing the DataPackage instance on which you can set a title, a description and the actual content payload.

As an example, on an individual Line page we want to share the name and status of that line.  The code relevant to the sharing functionality for this page looks as follows:

// an alias to make accessing the DataTransferManager easier
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager;

WinJS.UI.Pages.define("/pages/line/line.html", {
    
    ...
    
    _line: null,
    
    ready: function (element, options) {
        this._line = options && options.line 
                        ? LineDataManager.resolveLineReference(options.line) 
                        : LineDataManager.lines.getAt(0);
        
        // ...
        // code setting up page ommitted
        // ...
        
        // hook up to Share Charm
        dataTransferManager.getForCurrentView().ondatarequested =
                                    this._onDataRequested.bind(this);
    },
    
    unload: function () {
        // tidy up after ourselves
        dataTransferManager.getForCurrentView().ondatarequested = null;
    },
    
    _onDataRequested: function (args) {
        var request = args.request;
        request.data.properties.title = this._line.name + " Status";
        request.data.setText(this._line.name + ": " + this._line.statusDescription
                            + "\n" + this._line.statusDetails);
    },
    
    ...
    
});

Further Work 

There are a number of different strands to the planned further work for Toob.  Firstly, there are still a number of general user experience features to be pursued, such as pinning of secondary tiles and settings.  There is also still a lot of relevant and useful content to be designed and built into the application, such as station information and live train times.  Finally, the application would greatly benefit from some form of live/interactive map, with route finder functionality.

History

       
  • 5th October, 2012 - Initial Version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Graham Odds
Software Developer (Senior) Scott Logic
United Kingdom United Kingdom
I am a developer, designer and opinionated nuisance who works at Scott Logic, a provider of bespoke financial software and consultancy for the investment banking, stockbroking, asset management and hedge fund communities.
 
When not geeking out I like all things sciencey, loud music and ice-cream.
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 5 PinmemberPaul Edwin24-Oct-12 6:06 
GeneralMy vote of 5 PinmemberYvan Rodrigues19-Oct-12 14:19 
GeneralMy vote of 5 PinmemberAndrewAylett19-Oct-12 0:28 
QuestionGreat article, but... PinadminChris Maunder12-Oct-12 15:58 
AnswerRe: Great article, but... PinmemberGraham Odds12-Oct-12 17:17 
GeneralMy vote of 5 PinmvpColin Eberhardt10-Oct-12 6:04 
GeneralRe: My vote of 5 PinmemberGraham Odds10-Oct-12 6:35 
GeneralRe: My vote of 5 PinmvpColin Eberhardt10-Oct-12 6:41 
GeneralMy vote of 5 Pinmember@AmitGajjar5-Oct-12 3:59 
GeneralRe: My vote of 5 PinmemberGraham Odds10-Oct-12 6:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141216.1 | Last Updated 4 Oct 2012
Article Copyright 2012 by Graham Odds
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid