This article describes the development of a cross-platform HTML5 mobile app for searching UK property listings. The application uses JavaScript, Knockout, some elements from jQuery-Mobile and Apache Cordova (PhoneGap) for wrapping the application in order to deploy it to App-stores / marketplaces. I’ll also demonstrate how to use PhoneGap Build to create the iOS version of the application without the need for a Mac computer. The application makes use of the publically available Nestoria APIs which provide various methods for querying their database of properties for sale and rent.

This article will look at the technical details of how this application was written and the overall user-experience that this it delivers. The conclusions show that through the use of HTML5 it was possible to share quite a lot of common code between the two mobile platforms, however, the use of HTML5 did result in a few user experience compromises.

There has been a growing trend in the use of HTML5 for development of cross-platform mobile applications. This technology allows a developer to write an application using platform-neutral web technologies that can be delivered to a broad range of smartphone devices. This capitalises on modern smartphones generally having highly capable browsers, with good support for HTML5 / CSS3 features.

This article uses Apache Cordova (previously called PhoneGap), an open source framework, that provides a mechanism for packaging HTML5 content (HTML, JavaScript, CSS, images) as a native executable for Windows Phone, iOS, BlackBerry and Android. Cordova also provides a JavaScript interface for native phone functionality that is not accessible using HTML5 technologies (e.g. camera, accelerometer, compass).

I recently wrote an article for the Microsoft MSDN magazine which walked through the basic steps involved in creating a Cordova application for Windows Phone. The application described within the magazine article was rather simple. In this article I want to describe a more complex application “Property Finder”, which I released to the Windows Phone marketplace last year. Since then, I have used this codebase to create an iOS version of the same application, which I also describe in this article.

If you are totally new to Apache Cordova you might want to read my MSDN article first. Likewise, if you are new to Knockout, which is a rather funky JavaScript MVVM framework, you might want to read my previous codeproject article which contrasts Knockout and Silverlight. I have written on a number of topics relating to Windows Phone and Cordova in the past, so much of this article is light on details, with references to blog posts and other sources of information throughout.

In this article I’ll assume knowledge of JavaScript, Cordova and Knockout and concentrate on the application itself!

I’ll give a very brief summary of the tools and frameworks I have used to develop this application:

JavaScript – OK, this is a pretty obvious one, it’s an HTML5 app so it is written using JavaScript, duh! However, JavaScript is very rarely used on its own; there are a plethora of frameworks and tools for you to choose from. What follows are the frameworks I selected for this particular application.

Knockout – this is an MVVM framework for JavaScript. It allows you to create view-models that bind to your UI, with the binding framework marshalling changes of state between the two.

jQuery – the de facto framework for JavaScript development! Within this project I use jQuery quite sparingly with Knockout removing most of the need for accessing the DOM directly. I use jQuery for the occasional selector to locate an element in the DOM and for the each() convenience function which I use extensively.

jQuery-JSONP – The standard jQuery-JSONP functionality lacks a mechanism for specifying a timeout. The jQuery-JSONP plugin is a compact and feature rich alternative that provides this much needed functionality.

Apache Cordova – this is a framework for packaging HTML5-based applications within a native shell. This allows you to distribute HTML5 applications as though they were native. Cordova also provides a common set of APIs for using the phones hardware functions such as location, persistence etc …

JSLint – JavaScript is a very forgiving language … too forgiving! Language features such as globals and semi-colon insertion make it very easy to write sloppy JavaScript code. JSLint imposes a set of rules that ensure your JavaScript is more consistent, readable and error free. If you are writing anything more than the most trivial piece of JavaScript code, I would recommend linting it! There is a Visual Studio 2010 extension that provides JSLint support which I would recommend using.

JavaScript Intellisense – To be honest Visual Studio is not the best tool for authoring JavaScript, personally I think Eclipse has the edge. However, developing in Visual Studio does allow you to quickly build and deploy the Windows Phone version of the code. Visual Studio provides JavaScript Intellisense via pseudo-execution of your code, this is needed because JavaScript is dynamic, so the IDE cannot comprehend your code by static analysis alone. In order to use this effectively you need to ensure that the IDE can discover all of your files. For this reason I have the following file in my project which informs Visual Studio of all the JavaScript files in my project which I would like to include in Intellisense:

/// Ensure that all the files listed below are included, so that VS provides
/// Intellisense
//////<referencepath="namespaces.js"/>///<referencepath="model//JSONDataSource.js"/>///<referencepath="model//Location.js"/>///<referencepath="model//Property.js"/>///<referencepath="model//PropertyDataSource.js"/>///<referencepath="viewModel//AboutViewModel.js"/>///<referencepath="viewModel//ApplicationViewModel.js"/>///<referencepath="viewModel//FavouritesViewModel.js"/>///<referencepath="viewModel//GeolocationViewModel.js"/>///<referencepath="viewModel//LocationViewModel.js"/>///<referencepath="viewModel//PropertySearchViewModel.js"/>///<referencepath="viewModel//PropertyViewModel.js"/>///<referencepath="viewModel//SearchResultsViewModel.js"/>///<referencepath="lib//knockout-2.1.0.js"/>

All JavaScript files reference the above ‘contents’ file as follows:

///<referencepath="..//intellisense.js"/>

Firefox and Firebug – You can develop Cordova apps using the Windows Phone emulator, however the startup times and poor JavaScript instrumentation make this a very painful process! Because the core of your application will be plain-old JavaScript it is possible to run it within a desktop browser. My preference has been Firefox with the Firebug plugin for a long time, however more recently I have started using the Chrome development tools. One thing’s for sure, they both beat the IE tools hands-down!

NOTE: This application and the article were written against Cordova 1.9. The current release is 2.0, however, there are a few Windows Phone bugs in the most recent release that cannot be worked around.

When developing a Cordova app, you can add your HTML, JavaScript and CSS files to the www folder, and as long as you mark them with a Build Action of Content they will be included into your project and accessible via the browser control when your application executes.

The Cordova APIs are documented on the PhoneGap website, I will not describe them in detail here. One important thing to note is that you must wait for the deviceready event before making use of any of the other API methods. If you inspect the index.html file generated from the Visual Studio Cordova Application Template you can see that it waits until the device is ready before updating the UI:

You can develop your applications by making changes to your HTML / JavaScript, compiling and deploying to the emulator or device, however there is a quicker way. As your Cordova application is simply a HTML / JavaScript application you can run it in a desktop browser directly. However, you have to provide mock implementations of any Cordova APIs you use. For example, to run the application created by the Visual Studio template, you can mock the ‘device’ object that Cordova adds to ‘window’ then invoke onDeviceReady:

You will often find yourself using a small subset of the Cordova APIs, so desktop browser-based testing becomes a viable and rapid-turnaround option. For the Property Finder application I describe later, the vast majority of the development was done against FireFox and FireBug.

If you download the Property Finder source code and view the index.html file in your browser you will find that the application starts immediately. This is thanks to the following little piece of JavaScript:

If the Cordova created window.device is not present, then the code is being run from a desktop browser, so we immediately create the view models and start the application. Otherwise, we wait for the deviceready event, then start the app.

My preference is the second, because it allows you to create multiple instances of the same ‘type’ of view models.

Namespacing

JavaScript does not have a built-in mechanism for namespacing or packaging. As an alternative, objects can be used to organise code into namespaces. Within the Property Finder application I define three objects which act as namespaces: var View = View || {};

var Model = Model || {};
var ViewModel = ViewModel || {};

The logical OR operator used above is equivalent to the C# null coalesce operator (??).

The view model constructor functions are then defined as properties of these objects:

Object Oriented JavaScript

With C# object-oriented constructs such as ‘class’ and ‘interface’ are first-class features of the language. JavaScript is a simpler, more flexible language that lacks these constructs. This does not mean that JavaScript cannot be used to write object-oriented applications.

You can certainly write object-oriented application with JavaScript, however, you have choices to make. There are a number of different patterns that you can employ to define your classes, their methods and variables. It is worth noting that there isn’t really a good pattern for JavaScript interfaces, however, objects that define the same functions (i.e. methods) can be interchanged, so interfaces become un-necessary.

There are a couple of popular patterns for defining classes. The first uses protoypes:

In the above example we define the constructor function and the title variable. We then add a method (a method is a function which is associated with an object), via the prototype. A prototype is an object from which an object inherits properties. In the above example, adding the function to the Book prototype will ensure that it is accessible to any instance of the Book object.

The use of protoypes for defining the methods of an object is a popular JavaScript pattern for object oriented programming. However, it does not allow information hiding, i.e. private methods and variables.

An alternative approach to defining the same Book class is as follows:

Here the getTitle method is added to the Book object within the constructor function rather than via the prototype.

One advantage of this approach is that it allows information via closures because the getTitle function will have access to all of the variables defined within the constructor function even after it has returned.

The following is a trivial example of how closures can be used to create private variables and methods (although strictly speaking in this context they are actually functions!):

Whilst it adds information-hiding, this pattern is a little more heavyweight. The prototype pattern has been shown to be faster and require less memory, which is why the prototype pattern is quite widely used.

With Property Finder I used the ‘closures’ approach due to personal preference more than anything else. I find it easier to read and memory usage and performance were not a great concern for this application.

The Property Finder application is divided into two distinct layers; the ‘Model’ layer which is responsible for querying Nestoria APIs, analysing the response and returning data in the form of ‘model’ objects, and the ‘View Model’ layer which is responsible for the overall application logic, including navigation, state persistence and responding to the user input.

The following diagram provides an overview of the general application structure. There has been a certain amount of interpretation involved in creating this diagram – interfaces are used where two different classes are interchangeable and used for the same purpose:

From the model layer, PropertyDataSource provides the rest of the application with an interface for querying the Nestoria APIs. This is exposed via a couple of simple methods, one which queries via a plain-text search string (e.g. “London”), and one via geolocation (latitude and longitude). Internally, this class makes use of JSONDataSource, which encapsulates the logic to perform the actual web requests, the source of which is shown below:

The above code makes use of the jQuery-JSONP plugin in order to be able to specify a timeout for the query. As an aside, if you are not sure what the difference is between JSON and JSONP, and why we need to use JSONP in this instance, take a look at this StackOverflow answer for a good overview.

Separating the code that makes the request to the Nestoria APIs from the code which parses the response allows us to easily inject test data. The class above can be substituted for the following, which waits 1 second before returning a ‘canned’ response:

This is very useful for testing against web services, where you do not have any direct control over the returned response. As you can see, the above code returns a couple of different types of response in order to allow for more thorough testing.

The ProperyDataSource class takes the JSON response provided by JSONDataSource, and parses into a format which is more suitable for the Property Finder application. It also handles the various response codes and returning a suitable response:

The code above highlights an interesting design decision that I made; the various model objects returned, Location, Property, PropertyDataSourceResponse, are all created using a constructor function. Take for example the code which creates a Location:

As these are model objects, they do not have any methods or any kind of functionality beyond being carriers of data. The above code could be modified to create an equivalent object using literal notation:

Using the above, the application would still work just fine. So why have I gone to the effort of creating these model objects? The Location object shown below illustrates why:

/// <reference path="..//intellisense.js" />
/*global $, Model */
Model.Location = function (config) {
/// <summary>
/// A model that represents a location. This is composed of a human readable display string and a
/// placename, which is the string sent to Nestoria in order to perform a search.
///
/// e.g. longTitle='Albury, Guildford', placename = 'albury_guildford'
/// </summary>
// this display name
this.longTitle = config.longTitle;
// the query name
this.placeName = config.placeName;
};

The model objects to do not add anything to the functionality of the application, however, they make the code much more readable, providing a place for documentation and a way to specify the ‘shape’ of objects which are being passed around.

Note that the config object allows for a more concise and readable construction of the model objects.

The Property Finder application uses the same pattern I outlined in my recent MSDN Magazine Article, so I’ll go light on the details here. The MSDN article uses a much simpler example of a twitter-search application, making it easier

ApplicationViewModel

The application has a single instance of an ApplicationViewModel, which manages the application back-stack. This view model contains an array of view model instances, with the UI being rendered (and data-bound using Knockout) for the top-most view model.

When the back-stack has more than one view model, the Cordova hardware back button event is handled, in order to capture the back button press (which would otherwise exit the application, it is a single Silverlight page after all!) and remove the top-most view model from the stack.

app.js

The Property Finder is structured in a similar manner to the classic Silverlight / WPF MVVM pattern, with folders for view-models, model objects etc …

The app.js file is the entry-point for the application, creating an instance of the ApplicationViewModel and a PropertySearchViewModel (the first page of the app), then pushing this view model onto the application back-stack.

You can see that the above code makes use of the ApplicationViewModel.backButtonRequired property, which is a computed observable, which changes state between true / false, depending on whether the application needs to handle the back button.

I like to think of app.js as roughly equivalent to the Silverlight Application instance; it handles application and page lifecycle.

PropertySearchViewModel

The PropertySearchViewModel presents the front-page of the application, which gives the user a text field to input their search term. A snippet of this view model is shown below:

As you can see from the above, this is pretty straightforward Knockout stuff. There are a few points worth noting …

The content div also has the class noScroll, with the page lifecycle code in app.js detecting the presence of this class. If it is found, a message is sent to the native Silverlight code to inform it that it should disable scrolling of the native WebBrowser control. This relates to a blog post I wrote a while back on how to supress pinch zoom and scroll in a Windows Phone WebBrowser in order to give a better user experience for HTML5 apps.

At the bottom of this template there is a div which creates an app-bar. The project CSS creates a Metro-style UI as shown below:

There is a small amount of code in app.js which adds various event handlers to the app-bar to give it the show / hide behaviour:

The Property Finder uses a simple CSS file to achieve the Metro styling seen above. You might be wondering why I didn’t use the recently released jQuery-Mobile Metro to achieve this same result, with less effort. Unfortunately jQuery-Mobile is much more than just CSS, it adds a lot of extra structure to the DOM and has its own page lifecycle. Making jQuery Mobile play nicely with Knockout is not much fun and after my own efforts, I’d avoid attempting this!

LocationViewModel and GeoLocationViewModel

The Nestoria APIs allow you to search via a plain-text search string or a geolocation. The Property Finder has view models that represent each of these types of search.

Each of these view models has its own executeSearch method, which uses the PropertyDataSource described earlier to perform the required search. Giving the responsibility of executing the search to the objects which represent each type of search removes the need for a nasty ‘type-based’ switch to invoke the required search method.

An example of how these are used is when the user hits the ‘My location’ button, which is handled by the PropertySearchViewModel. Here the navigation.geolocation object, which is part of the HTML5 Geolocation specification, is used to find the current location, an instance of GeolocationViewModel created and a search executed.

If there are more pages of data, a ‘Load more …’ button is displayed at the end of the list:

State Persistence

Hopefully the previous sections are enough to give you a flavour of how the Property Finder application is structured and functions. I have not given an exhaustive descriptions of all the application features, such as recent searches, favourites etc … however, these all follow a similar pattern.

The one area I wanted to detail a bit further is state persistence. Within app.js property changed handlers are added to all the view model properties that we would like to persist between application sessions:

Cordova does its magic here, replacing the localStorage object with its own equivalent that provides a platform specific mechanism for saving state, i.e. for Windows Phone it uses isolated storage via the Silverlight APIs.

When the application restarts, we check for any previously saved state and re-load it:

The saved application state is in JSON format, for we can easily re-create our view model objects, using the ko.fromJSON utility function for example. However, this will provide objects that look like our view models, but they will lack the methods we have added to these objects within their constructor function.

For this reason I have created a utility function, hydrateObject, that recursively re-constructs view models, where each has its constructor function identified by a factoryName property:

Because Property Finder has been written using platform-agnostics HTML5, it could be run directly on an iPhone. However, because I decided to use the Windows Phone Metro style, it would look very odd on an Apple device! Instead, I wanted to give users of both OS an experience that is suited to their device; Metro for Windows Phone and the classic ‘Apple’ theme for iOS.

All of the application logic is written using Knockout view models, so is entirely separate from the UI layer. This means it should be possible to replace the Metro UI with an iOS equivalent simply by changing the templates and style sheets.

Well … almost.

Borrowing from jQuery Mobile

Creating an iOS style UI using HTML / CSS is a much harder task than creating a Metro UI with HTML. Fortunately the jQuery Mobile team have come up with a highly comprehensive framework that produces HTML UIs that look almost exactly the same as their native equivalents, with minimal effort.

Unfortunately, as I mentioned previously, Knockout and jQuery Mobile do not play nice! So I used the jQuery Mobile CSS without their JavaScript code. This has the side-effect that my HTML templates are much more complex.

The extra HTML elements are required in order to support the jQuery Mobile CSS (If only HTML / CSS had the equivalent of Silverlight templates!).

Using this slightly verbose approach, I was able to create HTML templates that make use of the jQuery Mobile CSS resulting in iOS screens which look very much like a native application:

Scrolling with iScroll

The ‘standard’ layout for an iPhone application has a fixed header bar at the top and scrolling content beneath. Unfortunately iOS browser (prior to iOS5) lack so of the CSS constructs required to achieve this type of page layout. For an overview of the issues, refer to the jQuery Mobile page on touchOverflow.

In order to create a page with a fixed header and scrolling content, people resort to some quite complex JavaScript and CSS, manually handling touch events, offsetting the content, calculating inertia etc … A popular script for that wraps up all of the complex code required is iScroll. You can see a live demo of it in action here. In order to render a scrolling list of properties, I integrated iScroll into the iOS version of Property Finder.

There is a little extra code required in app.js in order to handle changes to the list of properties and update the iScroll instance so that it is aware that its contents have changed. Other than that, the integration was quite straightforward:

The iPhone lacks a hardware back button, hence the inclusion of a back button within the header bar in the above screenshot.

iScroll also has some very nice extra features, such as pull-to-refresh. I was able to integrate this feature into PropertyFinder as an alternative to the ‘Load more …’ button in the Windows Phone version:

The code which handles this is a bit messy, as it is outside of the elegant Knockout view model-driven code:

The Project Structure and Build

Other than the cosmetic changes detailed above, all of the core application functionality, including geolocation and state persistence, work s unchanged on iOS. In order to facilitate the development of the iOS version, I created a simple batch file which copies the shared code from the Windows Phone project into my iOS folders:

The static images in this article look almost indistinguishable from their native contemporaries. However, when you actually put them in the hands of an end user, they will start to spot a few of the tell-tale signs that identify these as non-native applications!

Windows Phone

Windows Phone HTML5-based applications have a few issues that affect the user-experience of the finished product. Here is a brief summary of some of those issues:

Text selection – because the PhoneGap view is HTML, the user can select any text on the page. With WebKit browsers (iOS, Android), you can disable this with the CSS user-select:none property. This is not supported in IE, which is a shame because it improves the user experience of HTML-based applications.

Suppression of pinch zoom – the solution I described above for disabling pinch and tap zoom works well, however, as it is dependent on the internal visual tree of the WebBrowser control. For this reason, when I discussed it with Jesse Macfeyden of the Cordova team, I advised against including it being included in the Windows Phone Cordova framework. A future version of the WebBrowser control might have a different visual tree that breaks this functionality. What is really needed is better support for the user-scalable:no meta property. Both Android and iOS do a better job of this!

Gray link highlighting – probably the single biggest issue with the IE9 mobile browser, from a HTML5 application developer perspective, is the way it highlights links, or any element with a JavaScript click event handler, in gray. If you are trying to create an application with a native look and feel it totally ruins the experience. Try looking at the jQuery Mobile demo on your Windows Phone browser. It is an almost pixel perfect iOS UI, however as soon as you click on a link, it is immediately obvious that this is a web page.

In the screenshot below you can see this issue, where a gray rectangle appears over the property tile when the user clicks on it:

This occurs throughout the application, when they search buttons, app-bar buttons, tiles, everywhere! Regarding the last issue, I have posted on StackOverflow but haven’t found a satisfactory solution yet.

iPhone

The Property Finder iPhone interface holds up a little better than the Windows Phone equivalent. There are no immediately obvious UI flaws that identify it as a HTML5 application. However, there are a few signs. Probably the most noticeable difference is the page transitions. With native iOS applications, the transition from one screen to the next is subtle and complex, involving at least five different elements.

HTML5-based applications typically transition from one screen to the next as a single sliding block.

The main reason for choosing to implement mobile applications with HTML5 is in order to share code across multiple platforms, removing the need to create multiple native equivalents. So just how much code was shared between the iOS and Windows Phone Property Finder?

Using lines of code as a metric, 43% of the code was shared across platforms:

This doesn’t sound that impressive! However, it is worth noting that this is over the entire codebase, which includes JavaScript, CSS and HTML. In terms of development effort, it typically takes much less time to write CSS and HTML than JavaScript.

If we focus on JavaScript alone, the re-use story is much better:

Another reason why the amount of code shared was not as high as it could have been is that I decided to create an application that mimicked the native look and feel of each of the two platforms. Nearly all of the platforms specific code was as a result of this decision.

The following is a brief summary of my findings, in an easily digestible bullet-point format:

HTML5 is a viable technology for cross-platform mobile application development. Both the Windows Phone and iOS version delivered the required end user functionality.

HTML5 does allow you to share code across platforms. All of the core business logic was shared across both platforms. This is a key benefit of the cross-platform approach, where you can write and test your logic just once.

HTML5 is a route of compromise. While both applications look ‘at home’ within their respective platforms, it is quite easy to spot the fact that they are not native. The Windows Phone version has a few glaring UI quirks that do spoil the user experience. Personally, I would not choose HTML5 for Windows Phone development at the moment, perhaps Windows Phone 8 will solve these issues? For iOS the differences are more subtle, but are still noticeable.

Matching the native look and feel is costly. It did take quite a bit of time to match the native iOS UI. There are frameworks that assist with this, such as jQuery Mobile, however, these are often not suitable for more complex applications and you find yourself fighting the framework.

If you want a premium experience, go native! I don’t think it is possible to create a HTML5 application that matches the ‘premium’ experience of a native equivalent. If you do not want to compromise … native is your only option.

My advice to anyone who is considering creating a HTML5-based cross platform mobile application is to ignore the iOS style, ignore the Windows Phone Metro and Android Roboto and create your own application style that can be shared across all platforms. Creating a single consistent UI style will significantly reduce your development costs. And finally, understand the compromises you will have to make.

I hope you have enjoyed this article … my next one is already underway, where I will look at using Xamarin / MonoTouch as an alternative to HTML5.

I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.