Developer How-To: Mojo apps on the TouchPad | webOS Nation
 
 

Developer How-To: Mojo apps on the TouchPad 12

by Derek Kessler Fri, 15 Jul 2011 12:47 pm EDT

Developer Geoff Gauchet, the man you know as Zhephree and the force behind such fantastic apps as neato!, foursquare, and growlr shows up how to make your Mojo phone app scale up nicely on the big screen of the HP TouchPad.

The TouchPad is a pretty great device and what makes it even greater is the fact that it's backwards-compatible with pretty much every webOS phone app (read: Mojo). The only issue is that your Mojo apps run at their intended 320x480 resolution in a small Pre-looking frame with a ton of wasted black space round it. What if you've designed your app with a forward-thinking approach and it may scale up well? While you spend time porting your Mojo app over to Enyo, you can spend a few minutes making your Mojo app fullscreen and TouchPad friendly. I did this for growlr, so I'll walk you through it.

Getting Started

Really, before you do anything, plan. Go through every scene in your app and write down every single scene that requires you to perform a back gesture to leave it. You'll need this list so you know which scenes to add a back button to since the TouchPad doesn't have a gesture area.

The next step is to modify your appinfo.json file to tell the TouchPad to ditch the frame and go fullscreen. In your appinfo.json file, add this line:

uiRevision: 2

Load up your app and you’ll see that it’s huge! But, now everything looks funny. For instance, your buttons are stretched the full width of the screen, like on your phone, but now 1024 pixels instead of 320. This looks weird. Your text fields and groups may appear this way too. We’ll fix that later on.

Detecting the TouchPad

Now, we need to detect if we’re on a TouchPad or on a phone. Now, because there’s only one tablet device, we can sort of cheat. You may have to make other changes if a tablet of another size (like the rumored 7”) is ever launched. But this will be good enough until you can Enyo-ize your app.

Depending on your app’s file structure, you may have created a global JavaScript file with some common functions. If you have, we’ll be working there. If you haven’t and your app is a noWindow app, we’ll be working in you AppAssistant.js file, or if you have a single-stage, run-of-the-mill app, we’ll be working in your StageAssistant.js file. Either way, I’ll refer to whatever file you’re in as your “global file”.

In your global file, create a new function. A good practice is to have an object named after your app that’s accessible from anywhere and if you’re a Metrix user, you probably already have that. If not, go ahead an build an object like this:

var myApp = {};

Make sure this code is outside of any other functions and is on its own line so it can be globally accessed. Now, we’ll make our TouchPad detection function.

myApp.isTouchPad = function(){

};

Now, we need to fill in some code to make that function work. We’ll be accessing the Mojo framework’s DeviceInfo object. It’s not scary and is pretty straightforward. I’ll take each statement one-by-one and then put it all together for you.

if(Mojo.Environment.DeviceInfo.modelNameAscii.indexOf("ouch")>-1) {

    return true;

}

What this block does is looks at the human-readable name of the device and looks for the string “ouch” in it. I chose “ouch” because it avoids case-sensitivity, was short, and avoids the possibility of a space. A Regular Expression is probably better here, but I’m lazy.

But what if another large-screen device is launched, or what about the emulator? We'll add two more statements in case the first one fails. Again, this may not be the best way, but it works and in the end, you should port your apps to Enyo anyway. This is a stopgap.

if(Mojo.Environment.DeviceInfo.screenWidth==1024){ return true; }

if(Mojo.Environment.DeviceInfo.screenHeight==1024){ return true; }

What we're doing here is seeing if either the width or the height of the device is the largest side of the tablet, depending on its orientation.

And finally, we'll set a default value of false if the previous statements fail.

return false;

Now, putting it all together:

var myApp = {};

myApp.isTouchPad = function(){

    if(Mojo.Environment.DeviceInfo.modelNameAscii.indexOf("ouch")>-1) {

        return true;

}

if(Mojo.Environment.DeviceInfo.screenWidth==1024){ return true; }

if(Mojo.Environment.DeviceInfo.screenHeight==1024){ return true; }

 

return false;

};

Again, there's probably a better and more efficient way to handle this, but this works well.

Handling TouchPad-Specific Stuff

Now, let's put this function to good use! On scenes that need a back button, I slapped in this bit of code:

if(myApp.isTouchPad()){

 var menuModel = {

             visible: true,
             items: [
                    { icon: "back", command: "goBack"}
             ]
         };

     this.controller.setupWidget(Mojo.Menu.commandMenu,
         this.attributes = {
             spacerHeight: 0,
             menuClass: 'no-fade'
         },
         menuModel
     );   

}

Now, I used a CommandMenu widget, but this can be used as a ViewMenu widget instead, or you can use a command button, or any other widget. This snippet of code just puts a little circle back-arrow button at the bottom left for users to navigate back.

You'll want to put this in your switch in your handleCommand function for your scene:

case 'goBack':

    this.controller.stageController.popScene();

    break;

Or, whatever code would be applicable for your app to go to a previous scene.

Making Your App Prettier

As I mentioned before, your buttons and things are pretty wide now and, depending on your app, this may not looks great. Here's a simple way to fix that. Inside your scene's if-statement that detects if we're on a TouchPad, add this bit of code for whatever widgets need special styling.

this.controller.get("search-button").addClassName("touchpad");

This will add the class "touchpad" to the search-button widget. Now you can control it in your CSS. You can do things like...

#search-button.touchpad {

    width: 45% !important;

    margin: 5px auto !important;

}

This makes the button much smaller and centers it on the screen. What if your app has two buttons stacked? You could place them side-by-side like this:

this.controller.get("save-button").addClassName("touchpad");

this.controller.get("cancel-button").addClassName("touchpad");

And then in your CSS:

#save-button.touchpad {

    width: 45% !important;

    margin-left: 10px !important;

    float: left;

}

 

#cancel-button.touchpad {

    width: 45% !important;

    margin-right: 10px !important;

    float: right;

}

Now the buttons are next to each other. You may need to adjust some values to suit your app (as well as have an element that clear: both so your content appears as expected.

Other Stuff to Consider

If you have a background image on your scene, make sure you set it to repeat so it covers the whole device. Everything will be super-wide, so you may have to use TouchPad-specific images. With growlr, I didn't make everything stretch to fit the full size of the TouchPad. I mainly just wanted the app to be usable and quick on the TouchPad. Make your app look nice in the larger real estate, but don't break your neck restyling the whole app. That time is better spent porting it to Enyo.

And there you go! If you've got any ways to improve this, chime in in the comments.

12 Comments

Nice instruction article, Zhephree.
On behalf of all learning developers, I thank you.

Brilliant!

You should put out weekly developer tips and articles. A benefit to all webOSers out there.

why doesnt H/P just hire you? or give you a paid contract to help them come up with a solution to double the resolution of apps on TP.

This article was better than unicorn blood. It's a transfusion. Better, it's baby's breath. Thanks so much. I'm looking forward to updates to all (most?) of the phone apps I have running on my TouchPad. (I just hope there are developers left...)

I second the suggestion above. HP should hire this dude...

can something like this be done to shrink Pre apps into Veer size?

You don't need to shrink, in fact elements such as buttons and text should be the same size on both. You just have to adjust to the decreased screen real estate, which should be easy enough if you do portrait-only.

This is nice stuff. Thanks!

Zhephree, many thanks for sharing your trick!
Do you have an idea how to "beautify" the torn collapsible as well?

The next step is to modify your appinfo.json file to tell the TouchPad to ditch the frame and go fullscreen. In your appinfo.json file, add this line:

uiRevision: 2

Should be:

"uiRevision": 2

I'll also make a note about auto-generated Help scenes. I would recommend adding a scene item in appinfo.json in order to go back to the main scene:

{
"type": "scene",
"label": "Back to Main",
"sceneName": "first"
},

It's not elegant, IMHO, but it does allow the user to get back to the main scene from the auto-generated help scene.

Thank you Geoff, you made my life 10 times easier with this post. I will hopefully be submitting Soldier Talk and Soldier Talk Lite tonight to get them running full screen on the TouchPad and on phones in the same ipk.

Next up; Supersizing Super Ads!

Thanks again