You’ll note that I’ve also brought in the JQuery.tmpl library for templating. This has actually been discontinued by the JQuery team, but its replacement isn’t yet available. Since one templating solution is very much like another, I decided to carry on using it for this demo.

In addition to the third-party libraries, the app itself is broken up into a number of Javascript files:

We’ll dig into the Javascript some more in a moment, but the next thing we should look at is the index.html. JQueryMobile works by serving a single div’s at a time, and does all the animation between those div’s. In some apps those div’s could be pulled down from a server dynamically; in the case of this app, though, all the div’s we need are already within the index.html:

This renders a single button on the page. The inline Javascript binds that to a JQueryMobile function to change page to the provided URL.

As you can probably guess, that URL actually corresponds to the “toDosForToday” action provided by the ToDoItems domain service. In the normal scheme of things, if that URL served up a div, then JQueryMobile would automatically bring that div into the browser’s DOM, and render it. For our app, though, things are a little more complex, because invoking that URL will retrieve JSON. What we need to do is to use that JSON to generate a div and then transition to it.

This will cause the page transition ($.mobile.changePage) that we requested in the Javascript earlier to actually call the generic.submitRenderAndNavigate() function. You can find this function in generic.js:

The function can be called by JQueryMobile in two different ways: either the pageChangeData.toPage is a string, or it is an in-memory page object. We intercept the former case (checking that the URL is parseable), and then delegate off to generic.submitAndRender() to do the ajax etc. The call to e.preventDefault() suppresses JQueryMobile’s usual page handling.

We’re going to look at generic.submitAndRender() in a second, but for now it’s worth understanding that the end result of that processing is a page object. This is given back to JQueryMobile, which then calls back into this function. The second time around the function just returns; because in this flow the e.preventDefault() is not called, JQueryMobile does its usual page transitions.

But, let’s look to see how generic.submitAndRender() function ends up generating the page. For a start, this is the method where the ajax call gets made:

The example given here is only a demo, so there’s no sad-case failure handling. But assuming that the ajax call completes, the success callback looks up a
handler function based on the returned “Content-Type”. Here’s the lookup table:

Perhaps no surprise, the handler functions that the action result handler delegates to one-and-the-same as those we noted earlier. So let’s look at generic.handleListRepresentation in more detail (starting there simply because that’s what the demo app does when you invoke the “todaysTasks” service action):

The function uses a helper function generic.itemLinks to build a list of link objects. Then, we identify the template script $(“#genericListView .tmpl”), and pass both to the util.applyTemplateDiv helper function. This in turn calls the jQuery.tmpl library to do the heavy lifting.

The href’s of the link objects are formulated such that, when followed, they will again trigger the generic.submitRenderAndNavigate() function. In this way, we are able to walk between (the representations of) connected domain objects.

Once the content has been generated, we call a bunch of JQueryMobile functions (page.page() and so on) to tell the framework to “enhance” the generated page. And once that has been done, we call the generic.pageAndOptions() function to create the in-memory page. We’ll drill into that helper shortly.

Let’s now have a look at the biggest of the handlers, the generic.handleDomainObjectRepresentation:

Although this handler is longer, it’s doing much the same thing as the list handler. Specifically, it processes the JSON into three lists, one for value properties, one for references properties, and one for collections. For each, it uses the util.applyTemplateDiv function again in order to render against the corresponding templates, $(“#genericDomainObjectView .valueProperties-tmpl”) and so forth.

The template for value properties is, admittedly, a little ugly: it uses the {{if}} template in order to bring in either a checkbox or a textbox widget dependent on the value’s type. A more fully-featured application would probably generalize this to use subtemplates (and might even be extensible) to allow richer value types such as images or maps to be rendered accordingly.

The last of our handlers, generic.handleObjectCollectionRepresentation, is very similar to the generic.handleListRepresentation:

This little function returns a tuple consisting of the newly created page, along with an options object that has a dataUrl. This options.dataUrl property that is important, because it is what appears in the browser’s address bar.

As you can see, I’ve designed it to include both the view name (as an anchor), along with a ?dataUrl query param. Why so? Well, it allows the page to be bookmarked, so that the user can come back to any domain object rather than starting from home. The little bit of processing to do this is in app.js:

Here we try to extract the dataUrl from the locationHref, in other words the dataUrl query param. If successful, we call generic.submitAndRender(), as described above. Or, if the dataUrl cannot be interpreted, then we just revert back to the home page.

I hope the above run-thru has been useful. Bear in mind that this is far from production quality, and there could be bugs in it (in fact, I’m pretty sure that there are…). And there are, of course, plenty of things that this demo doesn’t yet support – invoking actions, for one.

In the future we expect that there’ll be a fully fledged generic REST client. In the meantime, though, hopefully this is a good demonstrator for the potential of the Rest API that ships with Isis.

PS: If you’re interested in the source code, you can either just save the files from the online demo (index.html, app.js, generic.js, util.js, namespace.js), or you can browse to the Isis subversion repository.

Very well written. I have been looking for some kind of step by step to this and the jquery mobile documentation is a bit underwhelming in this subject. As far as the templating engine you are using have you tried jqote2. I migrated from tempo to jqote2 and the performance difference is measurable. The application I am working on was taking about 5-10 seconds to make transitions to pages heavier with dynamic content, whereas now, I render the page faster than the transition. Now I will be migrating away from the pagebeforehide event and to the pagebeforecreate event. Thanks again ^_^

Thanks for the nice words, and glad the post was of help. To be honest I’m still something of a noob with JS/JQ/JQM, so it was all a bit of trial and error. I think it’s not too bad as a first effort, but I’m hoping that I might get a few other comments telling me how to improve the code. All being well, at some stage we’ll factor this into Apache Isis‘ Maven archetype.
No, I haven’t tried jqote2 as a templating engine, thx for the suggestion…
Cheers
Dan

Lol if your a noob then I must be a nub then cause I’m still trying to wrap my head around the whole Isis thing. Oh and I rigged my system together with the pagebeforechange event and got it working for the most part.