Replicating Flipboard's "page fold" animation with CSS 3D transforms and transitions #

Flipboard is an iPad app that has a distinctive "page fold" animation when going from page to page (visible in their intro video. I was curious if it's possible to replicate this effect using CSS 3D transforms and transitions. It seems to be (the demo works in Safari 5.0, WebKit nightly builds and to some degree in Chrome with accelerated compositing enabled)

The trickiest part about this was that 3D transforms are applied to the whole DOM node, but we only want to transform half of it for each fold. The best way to accomplish that for now is to clone the node to be transformed and then only show half of each clone, transforming each one separately. You can see that in a variant of the demo where "creases" are enabled (each half is outlined in a different color).

Moving down the stack #

After more than 5 years (!) of working on the Google Reader team, I'm switching to working on Google Chrome, and specifically the "web platform" piece that uses WebKit.

Reader has heen a lot of fun, I got a lot of things done and got to interact with a lot of users. Though Reader is by no means done, I've been having an "itch" lately to break out of my frontend development niche (where I've been working at higher and higher levels of abstraction lately).

I think there's still a value in knowing how things work at lower levels (even if there's way too much to know), and as much I told myself that I should skim through the Apache, Linux kernel or V8 sources to understand how they work, I never quite had the time. Now that web browsers are approaching OS levels of complexity, it seems like a good time to be forced to dive in.

Of course, the hope is that my web development background will help inform my Chrome/WebKit work, and I'm not the first to make this transition. It'll also be an interesting transition to be working on an open source project, with my (so far not very interesting) commits visible to the world.

Partychat Hacking #

I've been a user of Partychat for a few years now, both in its previous hosted-on-a-server-in-someone's-living-room implementation and in its current App Engine-based one.

Needing a fun side project (and having a few itches that I needed scratches), I've spent quite a few evenings over the past month making changes to the source code. So far I've managed to:

/share command
  • Make the homepage friendlier (and slightly prettier), especially the room creation form.
  • Improve web-based room management (building on what David started), so that you can join, leave, or request an invitation from the room's web page (here's a sample room for the current developers).
  • Prettify the plusplusbot display in the web UI.
  • Add a /share command that makes it easy to share URLs and give some context.
  • Clean up some data layer issues and fix some inconsistencies.
  • And of course, quite a few bug fixes (nothing like scanning the AppEngine logs looking for NPEs).

Like with all fun side-projects projects, they can also turn not fun once usage picks up. For example, yesterday a user invited room A as a member of room B, and vice-versa. As an unintentional side-effect of a change that I made to make the setup process more user-friendly, it became very easy to set off an infinite loop of messages. By the time I realized what was going on, we'd run out of App Engine bandwidth quota. Thankfully after some budget rejiggering and a some quick code change all was well. Similarly, a couple of weeks ago we had CPU usage issues (though optimizing that away was still fun).

It seems like chat is gaining in trendyness, with HipChat launching recently (presumably to challenge the incumbent Campfire) and Brizzly/Thing Labs's Picnics happening. Partychat will probably remain a hobby/fit-within-AppEngine-free-quota sort of project indefinitely, but it's been fun polishing it (and of coure, there's still quite a few things left to fix).

And of course, if you need IRC 2.0 a persistent chat room you should give it a try.

Google Reader Play Bookmarklet #

It occurred to me that it'd be pretty easy to make a bookmarklet for the recently-launched Google Reader Play:

PlayThis!

All it does is take the current page's feed and display it in the Play UI. You may find this useful when discovering a new photo-heavy site (or anything else with a feed, like a Flickr user page), or when you want to share, star or like an item from a site you're not subscribed to (you can also use the regular Reader subscribe bookmarklet for that).

P.S. If you're reading this in a feed/social content reader, you'll most likely have to view the original post, as the javascript: URL on the bookmarklet link will no doubt get sanitized away.

Most visible change #

I've been switching between Google Accounts a lot more lately, and it started to bother me that the login page that we show to mobile WebKit browsers doesn't use the email-specific virtual keyboard on iPhones, making it that much more annoying to type in an @ or a .com. The iPhone (as of iPhone OS 3.1) supports using a type="email" attribute on <input> tags, so I changed the login page template to use that.

It looks like the change is now live, and I'm pretty sure that this is the thing that I've done that will be seen by the most people (thus far).

iPhone screenshot

Of course it doesn't compare with Evan in the characters/user ratio.

Google Reader and Closure Tools #

Since Google Reader makes heavy use of the recently-open sourced Closure Tools, Louis Gray asked me to give a client's perspective on using them. He wrote up a great post summarizing my thoughts, and if you'd like to see the raw input, I've included it below:


There are three pieces to the Closure Tools, the compiler, the library and the template system. They appeared gradually, roughly in that order. The compiler in its current incarnation dates back to Gmail in 2004 (which is why Paul Buchheit refers to it as the "Gmail JavaScript compiler"), with the library and the template system starting a couple of years later.

Reader development started in early 2005, which meant that we always had the compiler available to us, and so except for early prototypes, we always ran our code through it. Until the last month leading up to the Reader launch in October 2005, the size benefits of the compiler were less important, since we were less focused on download time (and performance in general) and more on getting basic functionality up and running. Instead, the extra checks that the compiler does (e.g. if a function is called with the wrong number of parameters, typos in variable names) made it easier to catch errors much earlier. We have set up our development mode for Reader so that when the browser is refreshed, the JavaScript is recompiled on the server and is used with the page when it is reloaded. This results in a tight development loop that makes it possible to catch JavaScript errors as early as possible.

Since Reader development started before the library and template tools were available, we had homegrown code for doing both. There was actually shared code that did some of the same things as basic library functionality (e.g. a wrapper around getting the size of the window, handling different browser versions and quirks). However, that shared code was of various vintages (copied from project to project) and therefore not very consistent in style or quality. Erik Arvidsson's post talks a bit more about the inception of the Closure library (he's one of the co-creators, along with Dan Pupius).

Reader began using the Closure library and template systems gradually, first for new code and then replacing usages of the old shared library and our homegrown code. It was a gradual process, though I tried to keep it organized by doing an audit of all the usages of old code and their Closure equivalents, so that work could more easily be divided up (this was handled during "fixit" periods, where we focus on code quality more than features).

The benefits of the compiler system are tremendous. The most obvious are the size ones, without it Reader's JavaScript would be 2 megaytes, with it it goes down to 513K, and 184K with gzip (the compiler's output is actually optimized for gzip, since nearly all browsers support it). However, all of the above-mentioned checks, as well as many more that have been added over the past few years (especially type annotations) make it much more manageable to have a large JavaScript codebase that doesn't get out of control as it ages and accumulates features.

The library means that Reader is much less concerned about browser differences, since it tries very hard to hide all those away. Over time, the library has also moved up the UI "stack", going from just basic low level code (e.g. for handling events) to doing UI widgets. This means that it's not a lot of work to do auto-complete widgets, menus, buttons, dialogs, drag-and-drop, etc. in Reader.

One thing to keep in mind is that, as mentioned in the announcement blog post, these tools all started out as 20% projects, and for the most part are still dependent on it. If one project needs a feature from the compiler or the library that doesn't exist, they're encouraged to contribute it, so that other teams can benefit too. To give a specific example, Reader had some home-grown code for locating elements by class name and tag name (a much more rigid and simplified version of the flexible CSS selector-based queries that you can do with jQuery or with the Dojo-based goog.dom.query). As part of the process of "porting" to the Closure library, we realized that though there was an equivalent library function, goog.dom.getElementsByTagNameAndClass, it didn't use some of the more recent browser APIs that could it make it much faster (e.g. getElementsByClassName and the W3C Selector API). Therefore we not only switched Reader's code to use the Closure version, but we also incorporated those new API calls in it. This ended up making all other apps faster; it was very nice to get a message from Dan Pupius saying that the change had shaved off a noticeable amount of time in a common Gmail operation.

You can tell that there's something special about this when you look at the ex-Googlers cheering its release. If it had been some proprietary antiquated system that they had all been forced to use, they wouldn't have been so excited that it was out in the open now :)

If you'd like to know more about Closure, I recommend keeping an eye on Michael Bolin's blog. He already has a few posts about what makes it special, and I'm sure there are more coming.

PuSH Bot: PubSubHubbub to XMPP Gateway #

When XMPP support in Google App Engine was announced, it occurred to me that it would be pretty easy to use it to do a PubSubHubbub-to-XMPP bridge. Other things came up, but I was reminded again of the possibility when a "Oh, you didn't you see my Reader share?" conversation happened in a Partychat room. A bit of searching turned up someone else with the same idea, except it wasn't quite as user-friendly as it could be (i.e. as user friendly as a quasi-command-line interface, which isn't saying much).

After a bit of weekend hacking I've created PuSH Bot, which lets you subscribe to any PubSubHubbub-enabled feed and get notified of updates via XMPP (e.g. to your Google Talk account). It has some niceties like use of feed auto-discovery so you can just specify web page URLs, OPML import for bulk subscribing and throttling of updates. The homepage lets you know how to get started.

PuSH Bot Screenshot

The code is available, though there shouldn't be anything too special about it. Feed parsing is done via ROME (as is OPML parsing, though that needed some patching to get working). Feed auto-discovery is handled by Google AJAX Feed API because life is too short for HTML parsing.

Linkblog