Tutorials webOS Porting Older App
There is no shortage of open source license (mostly variations on mit) older javascript apps out there. Games, calculators, sketchpads, whatever.
A walkthrough example of this process can be seen at the example page.
Before you start porting
Get the app working in a browser.
But my app works in the browser already! Ok, then Pre-pare the app by Pre-fitting it to the new mojo environment it will be running in.
Chances are, your app will need layout and css changes. Do them in a browser before you bring the code into the Pre. The following are things to consider:
- Graphic size -- the Pre screen is 320px wide by 480 tall, but remember notifications will shrink YOUR part of the screen vertically. Resize graphics to fit in 320px. Be aware that the bottom of the screen is "fluid."
- Control size -- targets (especially buttons) smaller than 25px square are all but impossible to hit with a finger. 45px is the suggested size. 35px works. 25px doesn't really work unless there is 10px or so of space between them, so why not use the 35px size as your minimum target. Re-jigger your controls and graphics to allow that.
- Control Interactions -- While you CAN hover over a control in mojo by holding your finger on the screen, you can not see what's under your finger so hovers are kind of useless. Re think how to arrange hinting to eliminate hovers.
- Graphic format -- the Pre wants graphics to be png. Change all images to png. ( Yes, gif's and jpg's will work. No they are not the suggested graphic format for the Pre. Take this opportunity to move to a format with real alpha transparency.
- Graphic location -- Mojo wants you to put the images for your app in the images folder for the app. When porting, run the web page off the local drive, create an images folder, and change source calls for your images to images/filename.png.
- Page Layout -- many web apps put controls to the right or left of the application itself. For a first pass, consider moving controls BELOW the app. Eventually you may want to move all controls into menus, but for a first pass this works.
- CSS Considerations -- Take this opportunity to move styling OUT of your html and INTO the css file.
- Fonts -- The pre just doesn't have the web standard fonts. All font calls on the Pre will be converted to Prelude. So, just strip them out. They're pointless.
- Canvas -- Newer web apps make use of the HTML5 Canvas element to render graphics on the page. These apps, or at least the Canvas aspect of these apps, should be very easy to port, since both webOS and webkit handle Canvas very similarly. If an app made exclusive use of Canvas, this app is a very good candidate to be ported, as it can be ported more-or-less directly, with a small amount of development time devoted to adding Pre-specific controls.
- Move JS into a separate file -- if scripts are embedded in the page holding your app, move them out to a "myapp.js" file. When you move to the pre, you will include myapp.js in the sources.json file. You can not include js in the scene.html file. Or rather, you can, but it won't actually RUN.
- Eliminate document.write -- Document.write is deprecated in any html app. If the app your porting uses it, replace all the document.write commands with calls to do some sort of $('mydiv').innerHTML = something instead. Document.write will screw up the whole pushing and popping scenes thing. You just should not ever use it any more.
- Worry about JS libraries -- unless you are a jQuery master, remember that the Pre automatically comes with the Prototype library. This may conflict with calls to other libraries. Be aware of that, and consider if that's what you really want to do.
Source Code Styling
- The next two sections describe using a combination of JSBeautifier and JSLINT to clean up and format your application.
- Together, they define a "house style" for the construction of Javascript programs. It is entirely possible to construct well formed JS programs which do not use this house style, but by complying with it, your code will be very readable and easy to maintain.
- Details of this style spec can be found at Code Conventions for the JavaScript Programming Language. This set of coding conventions and rules for use in JavaScript programming is inspired by the Sun document Code Conventions for the Java Programming Language. It is heavily modified of course because JavaScript is not Java.
- Specifically, this style calls for K&R style braces ( { at the end of a line ), four space indents, braces around all conditional statements, no trailing ++ or -- ending lines, and no "optional" semicolons.
- Feel free to ignore this advice, but don't come complaining to us.
Clean the app up.
Lots of the web-apps out there were worked on until they worked. Then the programmer stopped because they worked. This is a good opportunity to make sure that the program not only works, but will work on the Pre.
Many older javascript apps have been "packed" to remove all possible spaces out of them. This not only makes them hard to read, it makes it hard to edit them to modify for the Pre. Run your javascript through JSBeautify at [http://jsbeautifier.org/] and it will untangle it for you.
Of course, if you're using Komodo edit with Austin's wonderful WebOS IDE, jsbeautifer is only a mouse click away. http://www.templarian.com/komodo.
- Note: Packing had a point in the days of dial-up-internet. When you have 8 gig of flash in your pocket, not so much.
Use JSLINT [http://www.jslint.com]. Really. Use it.
Why?
Because javascript is not a compiled language, your code never gets the scrutiny that a compiler gives C or Java or even P-Code languages like Pascal and Foxpro. You just submit it and try to run. JSLINT provides the kind of code checking services that a compiler provides to a programmer. In addition, JSLINT embodies Douglas Crockford's programming source code styling suggestions.
Yes, but why do it? I'm careful.
There are structural issues in Javascript. Javascript has a lot of "bad things". Some of these are also good things. For example: Javascript uses dynamically typed variables. This is good. You never have to cast. On the other hand, this is bad, since no one is checking if your variables are undefined. JSLINT will produce a list of all your variables and functions at the bottom of its report, then, in future runs, if you paste that list into your script, JSLINT will look for mis-spelled variables and functions. Of course, this happens only if it gets that far. But you're going to have to clean code for "a while" before you get that far.
JSLINT will make you cry.
The javascript code you have isn't going to pass. JSLINT forces you to adhere to some strict formatting standards. This is due to a couple of the OTHER bad things that javascript will do.
- Javascript will add semi-colons for you. That's all nice and everything until it adds one where you didn't want it. Palm's example code uses semi-colon insertion. You should not take this example to heart. Fix them.
- Unless declared with a var command inside a function, variables in javascript are global. Global variables are evil. Let JSLINT find them and then you fix them.
- Javascript is not fussy about where you put the {braces} around a code block. This is fine until the javascript interpretor inserts a semi colon for you between a function name and the brace. JSLINT enforces K&R style formatting where { always comes at the end of a line, never at the beginning. (Javascript is not Java.)
- JSLint expects that if, while, do and for statements will be made with blocks {that is, with statements enclosed in braces}.
- JavaScript allows an if to be written like this:
if (condition) statement;
- Douglas Crockford, and the JSLINT community's position is that this form is known to contribute to mistakes in projects where many programmers are working on the same code. That is why JSLint expects the use of a block:
if (condition) { statements; }
- Experience shows that this form is more resilient.
- Javascript has two different equality operators == and ===. Never use the former. Always use the latter. The former does automatic casting in an attempt to help the novice programmer to get code that works, but it follows weird rules that you will never be able to remember. For example:
0 == "" '' true
- but
"" == 0 '' false
There is much more, please review http:www.jslint.com/lint.html
If you need help debugging your app, doing as much as possible before moving to the Pre is useful. The debugger for the Pre is currently broken. So, do all the debugging you can on a browser. Specifically, use firebug. If you haven't used firebug in the past, and you've been writing javascript, you've been wasting a lot of time. go get it now.
Everything worthwhile I know about javascript I learned from Douglas Crockford. If you do not own his book: Javascript: the good parts, run do not walk to get it. If you are a programmer of some other language and need a quick, free overview right now take the time to read through Remedial Javascript.
Enough about javascript, I want to port this app.
Now that you have a clean reliable app running in a webkit browser on your desktop (Safari or Chrome), you're ready to port.
- Start with a hello-world program. Test it. Make sure that your scene comes up. Unless it does, there's no point in messing with other code.
- Move the body of your desktop app's page into your scene file in apps/views/thisScene/thisScene-view.html. Note that the scene file does NOT have body or header tags. Just the body. That's all.
- Insert a reference to your myapp.js file in the sources.json.
- Test. It ought to run. It may not be pretty, but it ought to run. Now is the time to begin "Pre-ing up" the code. But first, a warning.
- alert() doesn't work in a mojo webos application. You will need to replace calls to alert() with calls to Mojo.errorDialog and to Mojo.alertDialog.
- Consider changing "onclick" calls in the html into Mojo.tap calls to the id of the element.
- Click and drag on the Pre is "hard." there's no mouse button to hold down. Think about how this effects your user interface.
Debugging
It would be very VERY useful if someone knew how to make the debugger work. Failing that, putting mojo.log calls into your code so you can see where it fails is super useful. Specifically, you can put in calls that look like this:
Mojo.Log.error("This will go into the error log.")
To see the error log, as the program runs you can use palm-inspector. It isn't as useful as you might hope, but if you hit the second button from the left at the bottom of inspector, it will display the error log for your program.
- If palm inspector just doesn't ever work for you, you can read the log at /var/log/messages use your favorite editor or less to review the file.
In order to inspect your program, you will need to launch it with palm-launch. Specifically use:
palm-launch -d tcp -i com.mydomain.myapp
this will launch the app on the emulator (assuming it's running) and make it "inspectable." Then run palm-inspector. (you can ignore any errors the batch file gives you.)
Debugging without the emulator
If you want to run the code and see the error log on your live Pre, you can ssh into a rooted Pre and type
cat /var/log/messages | grep com.mydomain.myapp
this will display the messages from your app. You need to do the fancy bit because messages contains messages from a LOT of programs, not just yours.