Quantcast
Channel: The Microsoft MVP Award Program Blog
Viewing all articles
Browse latest Browse all 788

Building a Windows 8 Touch application with WinRT JavaScript and Html5

$
0
0

Editor’s note:  The following post was written by ASP.NET MVP Peter Kellner

Introduction

With the introduction of WinRT (which replaces the Win32 API we are all use to), Microsoft has provided JavaScript programmers first class access to system libraries previously unavailable. That is, because WinRT is available directly to JavaScript, device access (GPS, motion sensors, etc.) are all available directly to the application with no special security layer. That said, WinRT also brings with it restrictions which a typical browser does not have. Because it is possible with such tight access to the OS for applications to do harm, WinRT has a sophisticated security model in place to keep bad things from happening. In addition, a WinRT app forces you application to behave nicely or it may not work. For example, if you application takes too long to start, the WinRT library will automatically stop the application from proceeding.

Microsoft has done a good job of balancing the needs of many with the needs of a few with WinRT. That is, your application is really the needs of a few (well, you alone), while the needs of many (all the other applications and services running on your device) are all looked out for.

Our Goal Today

We will be using Visual Studio 2012’s support for building a WinRT application using JavaScript and HTML5. The application will be a simple conference track viewer that lets its users navigate tracks and the associated speakers. This data will be downloaded asynchronously from a remote server in JSON.

Windows 8 application development has lots of special capabilities for which we will only scratch the surface. Our example will implement the basic search contract and provide a simple about box for the application on the charms bar. The application will be fully touch enabled and it will support all the requirements necessary to be submitted to the Windows 8 store.

Built In Visual Studio 2012 Templates

As you would expect, Visual Studio has new project wizard that let’s you get started building your windows 8 store application. Having now been through the process of getting a token that let’s me submit applications to the store, I’ve learned that it is best when you are starting out to use the built in templates as much as possible. Microsoft has strict guidelines around building WinRT touch applications and if you don’t follow these, your application will be rejected. You of course can build the application from and empty template and follow the guidelines yourself, but you will spend a lot of time learning these specifications which are very detailed and picky. You’ll find in the UX Guidelines words like:

If you find yourself cramming things to fit, it’s okay to use 5x5 mm targets as long as touching the wrong target can be corrected with one gesture. Using 2 mm of padding between targets is extremely important in this case.

Because your app will likely be running in different resolutions and on different size devices, implementing the above requires a high level of CSS3 and HTML skills. If you use the templates that are built in to Visual Studio 2012, these kind of requirements are already taken care of for you with the included CSS3 style sheets.

Building the Conference Track Viewer

A Quick Look Ahead

Here is what our completed app will look like. Basically, it has two pages. The first page shows all the tracks and it includes an image background that represents each track.

image

Then, when the user touches any of the tracks listed, they will be presented with the details of that particular track as follows.

image

In addition, there will of course be the charms bar on the right for both search and about and on the bottom will be the app bar that let’s you refresh in case one or more tracks have changed. As mentioned earlier, there are a lot more areas we could improve upon to make this app take much better advantage of the windows 8 platform. Just to mention a couple, we could add push notifications so that refresh is not necessary and we could add a communication charms so the user could email or tweet a session or track.

Create a New Project for the JavaScript Windows 8 App

First thing to do is to create a new Visual Studio 2012 JavaScript Windows 8 project. We of course want to select from a template that most closely matches our scenario for the reasons mentioned in the previous section “Built In Visual Studio 2012 Templates”. So, File/New/Project/JavaScript (from the opening screen of Visual Studio). Knowing that we want to display a top level view of all the tracks, with a drill down detail view of each track showing the individual sessions, it seems like the “Split App” is going to be our best choice so let’s choose that.

image

If we run this application, out of the box you can see the similarities to the conference track viewer we plan on building. Below are some small screen shots of how that looks.

image image

Changing Where The Data Comes From (static to JSON)

One fundamental difference between the Split Item template and the actual Conference Track Viewer we are building is that the data in the template is static data that is simply created by defining JavaScript arrays. In my opinion, the sample would have more value if those arrays were loaded as if they were coming from an asynchronous source rather than just static memory.

So, if you look closely at the project created in Visual Studio 2012 from using the Split Template, you’ll see a that in the default.html, there is a reference to a JavaScript file called data.js. Basically, that data.js file executes an anonymous JavaScript function which assigns the the namespace “Data” several properties that include both data and functions. Because “Data” is a global, this means that after this anonymous JavaScript function executes (which happens when the application first loads), all that was initialized, stays initialized (thank you JavaScript Closure). I know that’s a bunch of charged words I just said, but at the end of the day what exists is a bunch of functions and data that were declared dynamically. Lines 16 to 23, as shown below of data.js really are the full definition that get used by the rest of the application to retrieve the data.

 WinJS.Namespace.define("Data", {
        items: groupedItems,
        groups: groupedItems.groups,
        getItemReference: getItemReference,
        getItemsFromGroup: getItemsFromGroup,
        resolveGroupReference: resolveGroupReference,
        resolveItemReference: resolveItemReference
    });

If you look, for example in items.js, you will find at line 12, code that sets the datasource of the list to be Data.groups.dataSource which is basically pulling data from the global declaration of data above.

ready: function (element, options) {
  var listView = element.querySelector(".itemslist").winControl;
   listView.itemDataSource = Data.groups.dataSource;
   ...

So, the challenge here is we need to load the data into the “Data” global namespace from a JSON web service and not from static data. To do this, we need to take into consideration that we can not simply include a static JavaScript file in our application and expect the data will be loaded. It is not that that static JavaScript file can not load the data, the problem is that we need to synchronize that loading such that the actual list (grid of tracks in our case) loads after the JSON service returns it’s data.

So, in order to do this, we change things up a little. In our Tracked Session Viewer, instead of loading the data in a static JSON file, we simply define the functions for loading the data in a static JSON file (we call it loadData now), then, in default.js, which is the code that executes when the program first launches, we add some code that calls loadData() function in the initial “activated” event of the full application. We pass in the navigator object to this function so that after the data is fully loaded (using asynchronous JavaScript) we then, and only then let the applicaiton navigate to our session tracks page which now can display data because it is fully loaded. The code in our program activation event (default.js) looks something like this:

app.addEventListener("activated", function (args) {

    if (args.detail.kind ===
        activation.ActivationKind.launch) {
        if (args.detail.previousExecutionState !==
            activation.ApplicationExecutionState.terminated) {
        } else {
        }

        if (app.sessionState.history) {
            nav.history = app.sessionState.history;
        }
        args.setPromise(WinJS.UI.processAll().then(function () {
            var searchString = "";
            svcc.Functions.loadData(nav, searchString);
        }));
    }
});

And then, in our loadData method, which is included as a separate file, we have code that does the Async JavaScript call and when that data load completes, does the navigation to our first page (looking like the following):

WinJS.Namespace.define("svcc.Functions", {
    loadData: function (nav, searchString) {
        var searchStringLower = "";
        if (searchString && searchString.length > 0) {
            searchStringLower = searchString.toLowerCase();
        }

        var sampleGroups = [];
        var sampleItems = [];

        var imageParams =
            "?width=160&height=160&mode=pad&scale=both&anchor=middlecenter&format=png";
        var urlString = svcc.Constants.baseUrl +
            "GeneralHandlers/Tracks.ashx?codecampyear=6";
        var xhrOptions = { url: urlString };
        var that = this;
        WinJS.xhr(xhrOptions).done(function(myXhr) {
            var result = JSON.parse(myXhr.response);
            for (var i = 0; i < result.rows.length; i++) {
                var trackId = result.rows[i].TrackId;
                var trackName = result.rows[i].TrackName;

All the source for this application is included in a link at the top of this article so feel free to download it and take a look at all the details.

Adding Search Functionality

We’ve talked about how to retrieve data the first time, but now let’s talk about what happens when the user wants to look for a specific speaker or session by some search string. Because we knew we wanted to add this later, we added to our loadData() function a search string parameter. When passed in as null, all tracked sessions are downloaded. However, when a value is passed in, we’ve added simple JavaScript code to the loadData() function to filter those results.

So, let’s follow the guidelines posted at http://msdn.microsoft.com/en-us/library/windows/apps/hh465238.aspx for how to create a minimal search in a Windows 8 JavaScript app. In our application, there are only a few things that are required.

First, in the split.js JavaScript file, add the following line of code in your page/ready label. This causes the search charm to automatically come up as soon as the user starts to type anything on the keyboard. That is, the user see something like the following and as soon as the press the search button or press enter, they event defined a little further below here will get executed.

image

And the code looks as follows:

// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
    Windows.ApplicationModel.Search.SearchPane.getForCurrentView().
        showOnKeyboardInput = true;

Then, at the top of that same file (split.js) add an event listener that responds when ever a search is performed. That code is actually executed when the user types

// Register event handler for QuerySubmitted
Windows.ApplicationModel.Search.SearchPane.getForCurrentView().onquerysubmitted =
    function (eventObject) {
        var searchString = eventObject.queryText;
        svcc.Functions.loadData(nav, searchString);
};

Adding an About Button

It is required that every program have an “About”. That is, on the charms bar, there needs to be button the user can touch that gives some information about the maker of the program (you). To do that, all that is necessary is to create a new about.html, about.js and about.css just like creating any other page (put them in the /page folder). Then, from the default.js file you need to register this new about page as follows:

// Populate settings pane and tie commands to settings flyouts.
WinJS.Application.onsettings = function (e) {
    e.detail.applicationcommands = {
        "aboutDiv": { href: "/pages/about/about.html", title: "About" }
    };
    WinJS.UI.SettingsFlyout.populateSettings(e);
};

Then, when the user brings up the charms bar, there will be a new “about” button and when that is tapped, the html page you just created (/page/about/about.html) comes flying out of the side and looks as follows:

image image

Summary

In this article, we’ve built a very simple Conference Session Tracker. It uses the Visual Studio 2012 Split template, adds to the charm bar a working search button as well as an About button. We’ve done it using JavaScript, HTML5 and CSS3. There are a huge number of things we did not talk about. This was just a short sampler of building something straight forward that has real world use. For further reading, I strongly suggest taking a dive over to http://dev.windows.com and you’ll find a wealth of resource and more information.

Good Luck with your Windows 8 App Building! See you in the Windows 8 store.

About the author

peterpict

Peter Kellner, a Microsoft ASP.NET MVP since 2007, is founder and president of ConnectionRoad, and a seasoned software professional specializing in high quality, scalable and extensible .Net web applications. His experience includes building and leading engineering teams both on and off shore. When not working, Peter spends most his free time biking. He has ridden his bike across the globe. Most recently he and his wife, Tammy, rode across the U.S., from California to Georgia, in just 27 days. You can find his blog at peterkellner.net, and follow him on Twitter @pkellner


Viewing all articles
Browse latest Browse all 788

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>