updates @ m.blog

Palm Pre Mojo SDK Experiments

As a new Pre owner, I was curious to learn to code for the Palm WebOS SDK (Mojo). Whenever I try to learn a new technology, I try to build a functional test project. So… what to build for WebOS? Since the Pre’s web browser doesn’t currently support the W3C Geolocation spec used by Flickr Nearby, I figured a good “Hello World” might be an application to get the GPS coordinates from the Pre, and then load the appropriate Flickr page for that location.

location services call

CAVEAT: This is a trivial hack, which was never designed for a production release. I’m writing up this blog post on how it works because (much to my surprise!) some screenshots of my little hack generated a bit of interest. So, I’ll provide some background, which hopefully will be either helpful or interesting to someone. Also note, that while I’m a bit of a minor nerd, I’m not a software engineer by any stretch of the imagination (I primarily do business / strategy / management-y type stuff), AND this was pretty much my first foray in Javascript, so I’m sure there are horrible things in my code that will make real developers cringe. Sorry!

To begin, follow one of the existing tutorials out there for setting up your environment, learning the basic concepts, generating the project and first scene, etc. etc. I’m just going to show here what I did from when I actually started coding.

First, we’ll need some minor code to push our main “scene” to the stage.

1
2
3
4
/* in /app/assistants/state-assistant.js */
StageAssistant.prototype.setup = function() {
    this.controller.pushScene('main');
}

Let’s give the scene some content:

1
2
3
4
5
6
7
8
9
10
11
<!-- in /app/views/main/main-scene.html -->
<div id="main">
  <h1><img src='flickr_logo.gif' />(nearby)</h1>
  <div id="disclaimer" class="palm-body-text">
      This is a quick hack to enable "nearby" functionality on Flickr Mobile.
      When Palm supports the W3C Geolocation API natively in the web browser
      we won't need this application. :-)
  </div>
  <div x-mojo-element="Spinner" id='gpsSpinner' name='gpsSpinner'></div>
        <div id="status_zzz" class="palm-body-text"><em>Determining location...</em></div>
</div>

Note I’m not really bothering with too much of the special Mojo chrome here, but that’s fine, right? Yay for web standards! Let’s perhaps add some CSS to prettify stuff:

1
2
3
4
5
6
7
8
9
10
11
12
/* in /stylesheets/main.css */
body {
  background: #fff;
}
h1 {
  font-size: 18px;
}
#gpsSpinner {
  float: right;
  margin-right: 10px;
  margin-top: 5px;
}

Here’s what that scene will look like when it’s first loaded:

Now we get to the meat of the application, configuring the “assistant” for the scene. Which will be in /app/assistants/main-assistant.js for those following along at home.

First, in the setup method, I’m going to initialize the mojo widget for a spinner (mojo widgets are basically chrome that have special properties and methods built in.) Next, I’ll fire off a services request to the location manager to get info from the GPS, and bind it to callback handlers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MainAssistant.prototype.setup = function() {
/* this function is for setup tasks that have to happen when the scene is first created */
      
  // setup spinner widget
  this.gpsSpinnerModel = {
       spinning: true
  }
  this.controller.setupWidget('gpsSpinner',
       this.attributes = { spinnerSize: 'small' },
       this.gpsSpinnerModel
  );

  // get location from GPS   
  this.controller.serviceRequest('palm://com.palm.location', {
       method:"getCurrentPosition",
       parameters:{},
       onSuccess: this.locationSuccess.bind(this),
       onFailure: this.locationFailure.bind(this)
  });
}

The services request is an asynchronous call, so I have to create a function to catch the response when it comes back. Here I define that method, which reads the response and updates my interface accordingly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
MainAssistant.prototype.locationSuccess = function(response) {
/* this is the callback method for when we successfully get the location back */

    if (response.errorCode != 0) {
        $('status_zzz').innerHTML = "BONK. Something went wrong! error code: " + response.errorCode;
    } else {
        var gLat = response.latitude;
        var gLong = response.longitude;
        var coords = gLat + "," + gLong;

        $('status_zzz').innerHTML = "Sweet! Your location is:<br /> <small>" + coords + "</small>";
        $('gpsSpinner').mojo.stop(); //spinnaz no mo!

        this.handleGo(coords);
    }
}

And finally, here’s my method (separated out for code simplicity) that does something with the final coordinates. If I was being fancy, I would make some calls to the Flickr API and retrieve information about photos and build an interface, but it just so happens Flickr already has a nice webkit optimized webpage to display that information, so we’ll just use the browser:

1
2
3
4
5
6
7
8
9
10
11
12
13
MainAssistant.prototype.handleGo = function(coords) {
    var url_target = 'http://m.flickr.com/nearby/' + coords;

    /* In the future we could use an embedded webview to render this page,
     But for now, opening a web page in the browser works fine and dandy! */
    this.controller.serviceRequest('palm://com.palm.applicationManager', {
           method: 'open',
           parameters: {
               id: 'com.palm.app.browser',
               params: { target: url_target }
           }
    });
}

(Note, we could have also done this in an embedded webview, but I figured it was more polite to open a “real” browser window so the user could use their bookmarks etc.)

Done and done! mobile nearby page

I was pretty impressed with how easy it was to get running. Since this was a “trivially simple” example, I didn’t really get into the guts of what Mojo can do. There’s lots of neat stuff with system notifications, background applications, cloud services and other things that if you’re serious about I’d suggest checking out something like Mitch Allen’s book.

For existing Mojo developers looking for something to build an application about, I’d highly suggest looking into the Flickr API. It has options to return results in JSON which is super handy to use in Javascript, and there are plenty of utility libraries out there. (You can find all sorts of stuff from our sexy-smart enginerds on Flickr’s devblog.)

UPDATE: You can now get the source for this on github.

Comments