Mobile Cross-Platform Development: Palm Pre

December 2nd, 2009
David Aurelio

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-scrollerElement (“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:
    1
    <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:
    1
    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:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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:

    1
    2
    3
    4
    5
    6
    7
    8
    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:

1
2
3
4
5
6
7
8
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.

Comments

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!

1

February 1, 2010 — 09:34 pm
Josiah

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”).

2

February 10, 2010 — 10:43 am
David Aurelio

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.

3

May 8, 2010 — 02:07 pm
mobile crazy

very nice posint

4

May 10, 2010 — 09:55 am
Jame martin

very nice postng

5

May 10, 2010 — 10:21 am
Light up

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.

6

July 28, 2010 — 04:16 pm
gravel driveway

Dude, please inform me that youre heading to write a lot much more. I notice you havent composed 1 far more website to get a while (Im just catching up myself). Your weblog website is just also vital to be missed. Youve obtained so a lot to say, this kind of data about this subject it will be a shame to decide this internet site disappear. The net demands you, guy!

7

December 17, 2010 — 08:50 pm
windows vista live gadgets

,’; I am really thankful to this topic because it really gives useful information ‘-’

8

January 29, 2011 — 11:52 pm
Body Pillow

Hi, thanks for very useful information. For last issue you described, is there a way to generate mojo-tap event in Palm emulator? Right click at link in emulator gave me ‘click’ event.

9

May 14, 2011 — 09:24 am
Iwan

Leave a Reply