The Sweet Spot
On software, engineering leadership, and anything shiny.

AppStoreConnect UX

2. Dashboard: Reviews Tab

A series of UX workflow designs I did for AppStoreConnect, an overseas Android multi-market submission application. Completed November 2010.

Aristo, the shiniest jQuery UI theme of them all.

Let’s face it: jQuery UI skins suck. They’re flat, they’re boring, they don’t pop.

Enter Aristo, a jQuery UI port of the Cappuccino Javascript framework theme.

Much better. Clone the repo from GitHub here, or check out a demo.

On selling my soul and switching to Mac

A month ago I bought an ‘07 MacBook on Craigslist. No, it’s not one of those sexy aluminum hot rods, but it sure is pretty.

I was full of mixed emotions. I had finally joined the Tribe! I had sold my soul. I can now develop iPhone apps! I am property of SJ. Yes, I had interned at Apple in the summer of ‘08, but I haven’t really paid much attention to OS X until I’ve owned one of these suckers for myself.

It’s not easy making the switch. Here are some of my gripes with OSX and some stopgap replacements I’ve found:

  • No keyboard shortcut to maximize windows. (Solved with RightZoom)

  • MacPorts really sucks (that is, having to compile everything from source is really slow). (Still outstanding)

  • Switching windows between spaces is really clunky. (Sorta solved with Hyperspaces)

  • No keyboard shortcut to “move active window to space”. (Still outstanding)

  • No way to force windows to a grid. (Solved with Divvy)

  • No right Ctrl key makes things really painful in Emacs. (Remapped right “Enter” with DoubleCommand)

  • Aero Snap is cool. (Check out Cinch)

  • The MacBook keyboard keys feel cheap compared to a Thinkpad. (Still outstanding)

  • Really annoyed with Command-Tab switching. I just want to switch to a different window! (Still outstanding).

  • Expose feels limited compared to Compiz’ Scale plugin. Cannot Expose all windows in all spaces. (Still outstanding)

  • Closing window doesn’t kill the process. I suspect this is just a design philosophy I have to deal with. (Still outstanding)

  • Not sure why, but my wrists generally tend to hurt more after using the MB rather than my work Thinkpad.

Okay, I’m not going to do all complaining. Some things I really enjoy:

  • Drag-and-drop installation is totally elegant.

  • Time Machine just works, and the zoomable interface is totally slick.

  • Helvetica Neue, I love you.

  • Something about the font rendering is just amazing.

  • I get to look cool (and slightly cliche…) at coffee shops

  • Desktop graphics & animations render smoothly with CoreAnimation. This stuff just looks slick.

I guess it’s not as bad as I’ve made it out to be. Well here I am. Swore I’d never do it, but you got me with all that shiny, Mr. Jobs. You got me.

post-review, git-svn and Review Board

Here’s how to set up the excellent VMware-developed open-source Review Board and its [post-review]( command line review creation utility to work with git and git-svn on your computer.

My assumption is that you’re working with a local Git repository that is remotely linked to an SVN repository via the git-svn bridge. Let’s assume that your master branch is synced with the SVN repository, and you’re working on bug_12345_branch.

  1. Make sure you have RBTools installed (sudo easy_install rbtools for me on Ubuntu Linux), and Review Board set up elsewhere.

  2. Add a link to your Review Board URL in .git/config:

 url = <a href="#">https://(url_for_review_board)/</a>
  1. Make sure all your changes in bug_12345_branch have been locally committed.

  2. post-review -o, and…

  3. Voila! You should have a new review up on your Review Board instance.

  4. (After you get reviews, you can modify bug_12345_branch, pull the changes into master, and then git svn dcommit, blah, blah, blah.)

YUI 3 Widget lazy instantiation

At work, we make good use of YUI 3. It’s a really well-thought-out framework, from sandboxing and deep namespaces to CSS3 selector support and lazy-loading modules through the Yahoo! CDN. One of YUI 3’s biggest features is the Widget framework, which specifies an object on the page that the user can tweak to his or her whims.

Now typically, a YUI widget must be instantiated, then rendered onto the page. The render method is responsible for:

  1. Writing the widget’s DOM elements out to the page

  2. Binding handlers onto the DOM object.

  3. Updating the widget state to match the JS object state.

(This information didn’t come easily. I had to dig around in some YUI slides and found this in Satyen Desai’s “A Widget Walkthrough” presentation at YUIConf 2009.)

Now we have a page that generates hundreds if not thousands of these tooltips. Instantiating each tooltip, rendering them into the DOM and generating event handlers for each was wasteful and slowed IE browsers down to a crawl. So this brought us to the decision to lazily instantiate each Tooltip instance. My first thought was that I should be able to overwrite the render() method to write to the DOM only after a mouseover onto the Tooltip trigger.

Here’s the folly: note that in the previous slide, the event handlers don’t go live until after the widget HTML is rendered into the DOM. Rats. Is there any way I can get around this?

Here’s some peculiar code for the Tooltip wrapper:

function ttWrapper(triggerNode) { = null;
  /* First mouseover will instantiate the real TooltipWidget. */
  var mOver = Y.on('mouseover', function (e) { = new TooltipWidget(/*config*/).render();
    /* Detach this listener so it won't intercept any more mouseovers */
    /* A second mouseover must be simulated on the real TooltipWidget */
    Y.Event.simulate(triggerNode, 'mouseover'); 
  }, triggerNode);


The code installs a mouseover listener on the trigger node, then swaps itself out for the real mouseover listener that gets attached to the triggerNode when TooltipWidget gets instantiated. Event.simulate() is a strange, yet smart way to solve this problem.