2010-01-19

Oplop web app, now using HTML5

Back in October I blogged about why I liked jQuery UI in my search for a JavaScript library that would let me create a wizard interface the way I wanted to do it for Oplop (which is a password hash algorithm app for creating unique account passwords; more details can be found in the How Oplop Works page). And while jQuery UI worked for the initial launch of the wizard approach I took, I quickly realized it was not going to work for me in the long term as I wanted the web app to work on both a desktop and a cell phone using a single version and that meant minimizing download size. While jQuery UI looked fine on my Android phone, it did have some extra overhead that was simply not needed by me. That's when I decided I would create my own replacement for my use of jQuery UI's accordion to get the same effect, albeit specifically tailored to my needs.

I also took this opportunity to completely go all out and only use HTML5 (which should now simply be called HTML). Having used the new version of HTML heavily for my thesis work, I have come to know and appreciate all of the new features in the spec. Add in Mark Pilgrim's wonderful Dive Into HTML5 site/book, and I knew I wanted to go nuts and be entirely cutting edge and essentially give Internet Explorer the finger (for now; I plan to add support for Chrome Frame in the future). While I am sure most of you pro developers are not looking at HTML5 yet, you should still at least give it a glance as there is already JavaScript out there to help make IE function properly with some of the new stuff (see Mark's discussion on this).

First thing I did for this redesign was go for a semantic markup of the site. There was to be no CSS styling embedded in a tag or the page, nor any JavaScript anywhere to be seen in the page layout markup. Based purely on tags, id, and class markups I should be able to look at the HTML have the UI be obvious and clean. I also wanted the page to render exactly how it should look upon initial load with nothing but the CSS stylesheet and HTML; JavaScript was to be purely for logic and later style changes, but it should not be an initial load requirement (although at the moment the JavaScript is blocking the loading of the rest of the page; I will talk more about how I might solve that later on). The idea is that the load should take no longer than downloading and parsing all the files and not have to wait on any JavaScript short of wiring up form controls; no nasty UI pop-in from JavaScript execution, etc.

Luckily my goal of using only CSS and HTML for the initial page load styling turned out not to be a problem. Thanks to various new tags like section (to encase each step in for semantic reasons) and new attributes on form elements like autofocus (so the proper text field is selected upon initial load) the page looks exactly as it should sans JavaScript, making the view cleanly separated from the controller, all while being proper HTML.

With the look out of the way I tackled replacing jQuery UI's accordion widget. Because I imposed my restriction that the UI had to look correct w/o JavaScript, I had used CSS to hide the steps of the wizard that had not been reached yet with an open class. Using that as a base, I decided to have transitions from one step to another occur by triggering a nextStep() method which uses jQuery to find the step that has the open class, toggle that class off, go to the next section, and then toggle on the class there. This made the query simple in jQuery and allowed the transition code to be generic from step-to-step (although I had to add some hook support through jQuery.data() for step-specific prep and validation stuff).

That got me as far as having the web app function just like it did before I started this endeavour. But at this point I wanted to extend the potential audience, so I added iPhone support as well. This turned out to  be basically simple, but I did have to tweak the UX just for the iPhone. When I designed the web app I was designing it for me while I am on my laptop, which means a full keyboard. I also made sure it worked on my adp1 (which is the developer version of the HTC Dream) which has a physical keyboard. And being somewhat of a UNIX geek, I made sure the entire web app could be driven from the keyboard under at least Google Chrome, from proper focus between form controls by pressing Enter, down to having your account password be in a text field that is already selected for easy cutting by hitting Cmd-X (or whatever your cut keyboard shortcut is). Nice and elegant and damn quick for getting your account password.

But the damn iPhone has no Enter key on its soft keyboard when you are filling out a form. Instead you get a "Go" button which acts as form submission. In my case that's useless as there is no place to submit the form to; everything is client-side for security reasons. That meant I had to tweak the UX so that you can not only press Enter to transition to the next step in Oplop, but you can also click the title of the next -- and only the next -- step as well to trigger a transition. In other words Oplop can be driven by a mouse now.

Since I was already adding UX support specifically because of the iPhone I figured I would also make the web app support being a web clip (web app that can be added to your home screen) as well. Thanks to Jonathan Stark's in-progress book on iPhone developement I made Oplop be zoomed in, have a proper home screen icon, and to ditch the location bar.

I would also like to thank ImageOptim while I am at it for being such a great little tool to optimize all the PNGs I have as icons (favicon, web clip icon, etc.).

So now I have a web app that works under (at least) Chrome, Safari (both desktop and Mobile), Firefox, and Android. I am rather happy with that browser coverage considering there is no magical browser detection stuff require, nor two versions of the web app.

But of course I am not finished yet. First thing is to write up some UX tests using Selenium 2/WebDriver and Jython. Now that everything is functioning as expected I want to keep it that way.

After that I want to clean up my JavaScript code to be more event-driven. While it is part way there thanks to having a generic function that handles step transition details, that function gets called explicitly. It would be better to instead trigger a custom event and have a single event handler for that at the top of my HTML structure. Minor, to be sure, but just feels more "right".

Once that is done comes time to start really optimizing the web app. I still have yet to use Google's Closure compiler to minify all of my JavaScript code into a single file to shrink total download size and minimize the number of HTTP connections required to download everything (which can matter on a cell phone that has a high latency connection). I also want to play with the new async attribute on link tags. My hope is that I can add that to my minified JavaScript file so as to have it start downloading concurrently while the rest of the page is downloaded and rendered and have them finish roughly at the same time. Unfortunately I don't know if that will work reliably enough to let this work w/o somehow letting the user know when everything is finally wired up. Plus no browser currently supports the attribute (although Firefox 3.6 will have support apparently). After that there will be lots of time spent with Speed Tracer to see if there are any other obvious things to tweak.

And then back to adding features! The next big ones will be adding offline web app support and creating a Google Chrome extension based on the web app. The former should be relatively straight-forward, but lead to some custom Mercurial hooks for properly updating the cache manifest (need to tweak the file every time something changes to trigger a new download of the app) and the latter should simply be fun as I think my planned approach will be more secure and have a better UX than the other password has algorithm extensions already available (if my idea works  =).

Expect more blog posts on Oplop in the future as it is turning out to be a fun personal project. And if you actually use Oplop let me know and I will consider setting up a mailing list or something for Oplop-specific announcements (e.g. like the Python 3 command-line version I just uploaded to the project site) if there is enough users beyond just a handful of friends of mine.