Wednesday 3 July 2013

WiseMove HTML5 Mobile App Part 2 - KnockoutJS and JQuery Mobile

In this post I describe 2 of the main libraries used in the WiseMove HTML5 mobile app introduced in my last post.

The full source for the app is available on github here: http://github.com/phillp/wisemove

An instance of the app tailored for desktop browsers is here: http://wisemove.ppettit.net

One key decision when choosing libraries for mobile or web HTML5 development is whether to follow a declarative DOM-based approach for defining UI and model bindings, or whether to use one of the many libraries that allow you to code against a more abstracted UI model.  For the development of the WiseMove application I preferred the former approach. 

In line with this decision, I found KnockoutJS and JQuery Mobile to be an effective combination.  There are several posts that describe how these libraries can work together including this one by David Forster: http://blog.dee4star.com/integrating-knockoutjs-with-jquery-mobile-1

KnockoutJS allows you to decorate HTML elements with binding information that describes how values in a JavaScript model should be presented in the DOM, and how changes to DOM elements should cause updates to the JavaScript model.  This reduces the amount of event handling and DOM manipulation code that must be written.
KnockoutJS defines binding types for the standard HTML element types and events.  

When using JQuery Mobile widgets it is sometimes necessary to call methods on the elements when values change or when the DOM representation for the widget should be initialised or updated.  A widget of this type used in WiseMove is the JQuery Mobile Slider widget.



In order for the visual representation of the slider to be updated whenever the associated model value changes a KnockoutJS binding handler was needed as shown below.  The only really slider specific pieces of the code below are the call to the slider() methods.

ko.bindingHandlers.slidervalue = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
        $(element).slider();
       
        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function () {
            var observable = valueAccessor();
            observable($(element).val());
        });
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever the associated observable changes value.
        // Update the DOM element based on the supplied values here.
        var value = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);
       
        if (valueUnwrapped){
            $(element).val(valueUnwrapped);
         }
       
        $(element).slider('refresh');
    }
};
 The binding is used in HTML as shown below.
<input type="number" min="-1" max="10" data-bind="slidervalue: scoreValue" />

I found KnockoutJS very easy to use and definitely a time-saver.  There are many other approaches and libraries available.  One framework that I am interested in investigating further is AngularJS, a much larger framework that  contains elements that perform some of the same functions as KnockoutJS.

I have read a number of comments concerning performance issues associated with JQuery Mobile, such as flickering and non-smooth scrolling.  I did experience some problems of this type when running the app on mobile devices however I was able to get to an acceptable level of performance after applying some of the tips and approaches found on-line.  The JQuery Mobile library is more ambitious than many others in terms of the breadth of supported platforms and browser versions.  It seems this comes with a number of challenges and a few quirks but ultimately I think the framework is an impressive one.  If you have a more controlled set of target platforms you may see advantages in a more targeted UI framework.

Thanks for reading.