Mobile Cross-Platform Development: Palm Pre

This entry was posted on Wednesday, December 2nd, 2009 at 9:22 am and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Porting a W3C widget to webOS should not take a lot of effort, should it? webOS is built on top of web technologies, and in my mind the web is tagged “#universal”. But unfortunately, webOS isn’t universal. It’s different. I’m going to show you which differences you need to be aware of when doing cross-platform development and your application is supposed to run on webOS.

Background

Developing applications for mobile devices using HTML, CSS, and JavaScript is possible through different runtimes and frameworks. On Nokia devices, you can use the Vodafone Apps Manager (a runtime for W3C widgets) as well as Nokia Web Runtime (Nokia WRT). PhoneGap is a framework that allows building of applications for iPhone, Android, Blackberry, Windows Mobile, and Nokia WRT with web technologies. On all of this platforms you basically throw in a base HTML file (e.g. index.html) that contains references to scripts and stylesheets. Easy, isn’t it? But not on webOS …

webOS

webOS uses a concept of stages and scenes. A “stage” represents a card (similar to a window in desktop operating systems), whereas a “scene” can be imagined as a layer on a stage. Each stage consists of a stack containing at least one scene. While I really like this concept, I am of the opinion that using this model shouldn’t be obligatory. It provides an elegant possibility to develop webOS based GUIs, but gets in your way as soon as you want to deploy your app on different platforms. All porting issues pointed out in this post arise from the stage/scene model.

First Try

When trying to repackage a W3C widget for webOS for the first time, I used the palm-generate command line tool to create an empty app skeleton and copied the source code into it. After packaging with palm-package and deploying on the emulator I was happy to see that everything seemed to work just fine. Far from it!

Issue: Scrolling

When simply converting a W3C widget (or any browser-based application) to a native webOS app you will notice that everything works fine except for scrolling. If the contents of the application are longer than the viewport, they are simply cut off, and scrolling isn’t possible. To enable scrolling in webOS it is necessary to make use of a mojo-scroller Element (“Mojo” is the name of palm’s framework). The easiest way to achieve that is to “push a scene onto the stack”:

  1. Include the mojo framwork into your HTML file by adding a script tag before you include any other scripts or stylesheets:
    <script src="/usr/palm/frameworks/mojo/mojo.js" type="text/javascript" x-mojo-version="1"></script>

    Mojo will add a whole bunch of webOS-specific stylesheets to your application. If you like, you can use the classes defined there to achieve a more “native” feeling by using palm-specific classes.

  2. If you created the app skeleton with palm-generate you will find the constructor StageAssistant in the file app/assistants/stage-assistant.js. An instance of StageAssistant will be generated automatically on application start, and its setup method will be called. Add the call this.controller.pushScene("main"); to the empty setup method of the prototype. This will create a new scene called “main” (which is a set of div-Elements inserted into document.body).
  3. Generate the scene skeleton using palm-generate:
    palm-generate -t new_scene -p "name=main" <app-dir>

    When “pushing” a scene, the corresponding assistant is being instantiated, and the contents of the scene’s main view file are made visible (while everything else is hidden behind the newly created scroller). The two files are app/assistants/main-assistant.js. and app/views/main-scene.html.

  4. The last step is to transfer the DOM/HTML of your application into the scene. My approach is to remove all DOM nodes from document.body and reinsert them into the scene element. It is also possible to use innerHTML, but already registered event handlers will be lost. Change the setup method of StageController to:
    StageAssistant.prototype.setup = function() {
    	var body = this.controller.body,
    	    fragment = this.controller.document.createDocumentFragment();
     
    	while (body.firstChild) {
    		fragment.appendChild(body.firstChild);
    	}
     
    	this.controller.pushScene("main", fragment);
    }

    The second parameter passed to pushScene will be passed to MainAssistant as soon as it is instantiated.

    To reinsert the nodes into the DOM change main-assistant.js to:

    function MainAssistant(nodes) {
    	this.nodes = nodes;
    }
     
    MainAssistant.prototype.setup = function() {
    	this.controller.sceneElement.appendChild(this.nodes);
    	this.nodes = null; // unset to release references
    }

    This way, your original nodes are transferred to the visible and scrollable “main” scene. Don’t forget that any CSS selector like body > .foo will stop working as intended, because your DOM is wrapped by two additional div elements!

After these steps, scrolling finally works in apps ported to webOS. The code shown here is very generic. It can be used for every application. You should be aware that scrolling via window.pageYOffset is not possible, because the scrollable element is the mojo scroller, not the body element.

Event listeners

Developers who like registering event listeners on document.body will notice that those quit working after cut’n’pasting the DOM nodes to the scene elements. The reason is simple: in webOS, events only bubble up to the scene element (the inner one of the DIVs mentioned above). Simply don’t do that. And if you are using jQuery’s live(), stop using it. Sorry. Don’t blame it on me.

Scrolling, Part Ⅱ

Everything seems to work pretty well now, right? Well, there’s one more thing …

When you scroll (or drag) your app, and stop dragging above a clickable element, that element will be clicked. It took me quite some time to figure out the reason, because the same HTML/JavaScript will work flawlessly in the browser built into webOS. You need to listen for the “mojo-tap” event rather than for the “click” event. The “click” event will be fired after a drag has ended, but the tap event will only be fired when a “true” tap has taken place. I really can’t understand why it has to be that way, and if it wouldn’t have been easier not to alter the default behavior of WebKit.

The method I’m using is to have a variable containing the name of the event to bind to. That way, an application can still run on different platforms:

var myapp = { CLICK_EVENT : "click" };
 
if (typeof Mojo != "undefined") {
	myapp.CLICK_EVENT = Mojo.Event.tap; // contains "mojo-tap"
}
 
/* snip */
somElm.addEventListener(myapp.CLICK_EVENT, function() { /* … */ }, false);

Why?

When I was hearing about webOS for the first time, I really looked forward to have “it [the Web] as the SDK” of the OS (quote from Dion Almaer). And while the SDK offers some nice features – like the stage/scene architecture – it really gets in your way as soon as you don’t want to code exclusively for it. Unfortunately, you don’t have any choice, say some sort of “compatibility mode” to the web (couldn’t resist this one). You have to bend to webOS and stick to its rules.

Apparently Palm is working on better compatibility. On Ajaxian you can find an article stating that “The company [Palm] is involved with the BONDI and W3C widgets standardisation effort” (quoting Ben Galbraith and Dion Almaer). Honestly: Shouldn’t somebody have considered that in the first place?

To me, the web is a universal platform. We’ve had many issues with proprietary “solutions” in the past millennium and still have them. I don’t like seeing proprietary features being introduced once more. It is obvious that functionality of the operating systems must be accessible in some way. But does that imply breaking things that have worked before?

I would love to see the possibility of making simple applications run on webOS without too much efforts. At least it should be possible to run W3C widgets without big hassles.

Sometimes one might be supposed to think that Palm isn’t really interested in compatibility. The acceptance criteria of their “App Catalog” state that “They [the applications] need to be written specifically for webOS and not delivered through the browser.” Whatever that may mean.

9 Responses to “Mobile Cross-Platform Development: Palm Pre”

  1. Pingback by W3C-Widgets in webOS - webos-hilfe.de | webOS Forum & Community — December 4, 2009 @ 12:47 pm

    [...] in webOS hier ein interessanter Artikel um w3c-widgets in webOS zu installierten Uxebu.com – JavaScript addicts Mobile Cross-Platform Development: Palm Pre ist noch etwas umst


  2. Comment by Josiah — February 1, 2010 @ 9:34 pm

    Any chance you would want to post the source code to this tutorial? I’ve tried it a few times to no avail. That just proves I’m an idiot though.

    Thank you very much for posting this, btw. It’s just about the only article I can find on the net that mentions this flaw. It’s been driving me crazy!


  3. Comment by David Aurelio — February 10, 2010 @ 10:43 am

    Hi Josiah. You can download a zip containing an “empty app” and simply drop your sources into the folder. The entry HTML page must be named “index.html”, and you can add an icon (“icon.png”).


  4. Pingback by window.scrollTo for WebOS / Palm Pre at Luminescente — March 29, 2010 @ 2:54 pm

    [...] As WebOS wraps the app content inside a scene/stage structure, scrolling does not work like in other widget runtimes, as you can see here. [...]


  5. Comment by mobile crazy — May 8, 2010 @ 2:07 pm

    Very well said. Technologies are certainly developed like mad. There is really a race among all companies. to invent something which has not been in market by other corporations. Take example of mobile phones, I am incredibly fond of new mobile devices, mobile wallpapers and ringtones. I’m constantly seeking for new or exciting functions in mobile phones. But, I uncover some new or extra ordinary functions in all of them.


  6. Comment by Jame martin — May 10, 2010 @ 9:55 am

    very nice posint


  7. Comment by Light up — May 10, 2010 @ 10:21 am

    very nice postng


  8. Comment by Stephaine Deluca — July 19, 2010 @ 2:20 am

    I’ve had my Pre given that shortly soon after launch and am glad to find (by way of this forum) that I can now set a ring tone on incoming text messages and can research through e-mails and this kind of. Now is there any hope for an upcoming release through which I can look for my calendar? Would make my career a great deal less difficult, locating dates of last appointments. No other complaints, except that yesterday I was in and out of Sprint program (not unusual). I believe I had been roaming, and looked at my calendar. Almost everything from the calendar was one particular hour earlier than what I had input. The clock was one particular hour early as properly. I had been scared to death–then, as soon as we got back into Sprint program again, everything was normalized. Has this happened to anyone else?? Hunting forward to answers, but please remember, I’m no techie and speak English rather than technospeak.


  9. Comment by gravel driveway — July 28, 2010 @ 4:16 pm

    It’s strange to find out how many different blogs there are about this topic I don’t know if I’m ever going to need to come back here, but it’s great to know I found the one that provides a little practical info if this ever comes up for me again.


Leave a Reply