ProgramiCo
JavaScript Web Application Development
  • Home
  • SmartJs
    • Setting up the Environment
    • Running SmartJs
  • SmartJs Blog
  • About

Building a jQuery Mobile SPA in Phonegap

10/19/2012

0 Comments

 
This post continues to answer "what is SmartJs".  In this article we look at the J and the S.  How is the SmartJs framework Single Page Application UI implemented with jQuery Mobile? Read on to find out...  

UI Frameworks; pick one

I have tried a few frameworks for developing a mobile application UI.  The the number one reason to love jQuery Mobile over things like Sencha Touch or Titanium Appcelerator, is that it allows the UI to be written in pure Html and Css.  For me, other UI frameworks violate separation of concerns, when they make me compose my UI inside JavasScript files.  That is why we have Html and Css, to build the UI.  The especially strange feeling is when they make me use proprietary JavaScript objects to build UI's.  It reminds me of a Telerik or Infragistics library kind of control I've encountered several times in the .Net world. Almost always, these would end up being trickier to integrate with when you wanted something special.

Other things I like about jQuery Mobile are:
  • It looks good
  • It has a great code generator in Codiqa
  • It has a great theme generator in Themeroller
  • It has a rich set of widgets
  • It is compatible with jQuery
  • It is easy to bind to Knockout Js
  • It is being actively developed and improved
  • Just like everything else in SmartJs it is free, free, free

Codiqa UI; WYSIWYG Generator for jQuery Mobile

It can be daunting when you look at jQuery Mobile Html markup.  There seem to be a lot of attributes that one needs to know to get the proper effects.  Enter Codiqa UI to get you quickly started without having to write a single tag of that Html.  If you hit the jQueryMobile homepage, there is a free demo of Codiqa where you can actually do quite a bit without ever even needing to open an account.  Just drag and drop your UI elements and then customize them for your app.  Then hit "Inspect Code" and copy and paste the generated source code into your app's html view file.  From there it's easy to add some Knockout bindings to the Html to connect it to your ViewModels.

Bootstrapping jQuery Mobile and Phonegap

A good deal of work and research has gone into properly bootstrapping the SmartJs SPA and getting all of the libraries to work together cleanly.  The startup sequence looks something like this:

  1. index.html includes Cordova directly.  Cordova has its own built-in AMD implementation that registers itself as a module named "cordova".
  2. index.html then uses the regular RequireJs method to get to the app/main.js module
  3. Inside main.js we require jQuery and jQuery Mobile first
  4. We use jQuery to attach an event handler to document to handle the ready event.  This seems to be good enough to begin using jQuery Mobile
  5. In the case of a mobile-targeted build configuration, we attach an event handler to the deviceready event that will be fired when Cordova has initialized.  According to Phonegap documentation, a Phonegap app "shouldn't do anything" until this is received.

In different situations the events can be received in different orders.  So we need a flexible solution that works independently of timing.  The SmartJs main.js file shows how this can be done.

Click here to view the SmartJs main.js bootstrap file on github.

Keeping the Knockout-bound jQm Listview updated

When binding a jQuery Mobile Listview to a Knockout ViewModel, Knockout is going to come along and regenerate the Html whenever the underlying ViewModel changes.  When that happens, jQueryMobile needs to be notified that the listview should be refreshed.  That's because jQueryMobile does some post-processing to the normal <ul> and <li> markup of a list to turn it into a super special jQueryMobile list.

But how do we cleanly separate that concern from the ViewModel?  We surely don't want to have to call a function that manually updates the View each time we update the ViewModel.  Fortunately, we have the Knockout binding handler concept which is perfectly suited for the task.

Below is SmartJs's binding handler for the purpose of refreshing the jQuery Mobile Listview.  To re-render other jQuery Mobile widgets after dynamically adding content, a binding handler should be created for each kind of widget, because currently jQuery Mobile's widgets each have their own "unique" way of refreshing themselves that you will need to research.
0 Comments

Real Time Communications in a JavaScript Mobile App

10/1/2012

0 Comments

 
This post continues to answer "what is SmartJs".  In this article we look at the R and the T.  How does SmartJs implement Real Time communications? Read on to find out...

Network Events are Events too

In SmartJs a number of network communication channels are available:

  • Client->Server
  • Client->Client
  • Server->Client
  • Client->Group
  • Server->Group

All of them use the same Publish/Subscribe model to loosely couple the interactions.  In fact in SmartJs I go so far as to call it a Virtual Pubsub because an event could be Published on one device and consumed by other devices.

Underneath, there are two modules that are handling the communication infrastructure.  One is the proxy for Server on the client-side and the other is the proxy for Client on the server-side.  SmartJs was designed to allow these two modules to be able to swap out with other real time library implementations, or even plain Ajax.

Implementing Open-Closed Principle in the SmartJs client-server Interface

In the SmartJs client's proxy module for the Server we have the implementation of the function:
  • nowjs.eventServerToClient

This is where information is received from the server, and it is wired directly up to a Publish.

In this same module we find that the client calls the server using this function:
  • nowjs.eventClientToServer

It provides a callback which runs when the event is processed.  It is never the responsibility of the callback to handle any resultant data.  It is only there to provide success or failure feedback in the case where that is possible.  For example,  when attempting to create a new Topic, it will return a failure in case that Topic name is taken.  But if the Topic name is not taken, a separate message will come back Published containing the new Topic's data.  This is an example of SRP applied to a functional interface.

Similarly the server implements:
  • nowjs.eventClientToServer

This is where the information sent by the client arrives to the server.  There it is separated into data or group handling and further separated within the data or group handlers.

The server makes calls to connected clients using the function:
  • nowjs.eventServerToClient

It is the data structures passed through these functions that determines the routing and handling.  The functions themselves are open to extension while remaining closed to modification.

The dataContext and groupContext modules provide segregated interfaces to the server functionality.  These populate the traffic "kind" attribute with "data" and "group", respectively. Conceivably, other new modules could be developed that make use of the server proxy conduit, without ever needing to change the server module.  This is a great example of OCP.

Hacking nowjs to reference socket.io locally

This last bit is to show a bit of hackery I put together that allows nowjs's reference to socket.io to resolve to the client's /lib folder instead of the default of being network served by the nowjs host.  There are a few reasons you might want to do this, mostly I guess involving testing and efficiency.  Follow this recipe for the hack:

  1. While viewing your nowjs site in Google Chrome, hit F12 to bring up your Developer Tools and switch to Sources view.
  2. Find socket.io.js listed under your server's name or IP and click it to view it.
  3. Right click it and choose Save As... and save it to your app's /lib folder or equivalent.
  4. Apply the Hack to your copy of now.js as shown in this SmartJs checkin.
  5. Re-run your app, being sure to clear the Js cache
  6. You should now see the socket.io.js listed under /lib in Chrome's Developer Tools Sources tab

Todo: better AMD support for locally hosted socket.io.js so it will be built by r.js correctly.
0 Comments

    About the Author

    Picture
    Hugh Anderson is a web frontend developer in Tennessee who loves JavaScript and C#. 

    View my profile on LinkedIn

    Archives

    August 2015
    January 2013
    December 2012
    November 2012
    October 2012
    September 2012

    RSS Feed

Powered by Create your own unique website with customizable templates.