PastryKit: digging into an Apple Pie

December 16th, 2009

Yesterday John Gruber wrote about Apple’s PastryKit, iPhone’s JavaScript framework that’s been discovered “in the wild” on the iPhone user guide at http://help.apple.com/iphone/3/mobile/. There’s a few ways to access the page:

  • with an actual iPhone or iTouch
  • by browsing with an iPhone/iTouch user agent. If you’re using Safari, enable the Developer menu in Safari>Preferences>Advanced and switching user agents by clicking on Develope>User Agent

What’s all the big fuss?

John was particularly interested in the responsiveness and native-like interaction of flinging through long lists, the fact the address bar is completely hidden, and the possibility of having a toolbar fixed to the top of the page. PastryKit makes all of these things possible and implements them better than anything else. And the result is nearly indistinguishable from a native app. Here’s a video I made of the iPhone user guide in action, powered by PastryKit. This is running on Safari – it’s not a native app!

PastryKit has been here for a while

As John Gruber points out, the code for PastryKit has been there for quite a while now. Stack Overflow has a question about it that was asked way back in July, and there are several more recent references to it by jQTouch developer David Kaneda on Twitter. Of course, since John’s post there’s been an explosion of interest in the form of even more tweets!

Hopefully with all of this increased attention, we’ll see Apple take notice and address it. Here’s hoping, anyway.

Some interesting features

There’s even more interesting takeaways from the PastryKit code, and I’m sure I’ve just barely scratched the surface:

  • implements its own form of Object-Oriented programming (obj.inherits and obj.synthetizes properties). When modules are declared, they’re registered as a PK Class (i.e. PKClass(PKBarButtonItem) registers PKBarButtonItem as a PK Class)
  • CSS3 wrapper functions (PKUtils.t() is a wrapper for translate3d, etc.)
  • no single library namespace (surprisingly) – which means there are many many global variables. This however is somewhat acceptable, as all variables are prefixed with “PK” and are declared to be constant (const PKStartEvent, const PKEndEvent) and cannot be overwritten.

There’s also some interesting takeaways not from PastryKit itself, but from the way the iPhone user guide is implemented. Most of the data on the page – including each menu icon (base64 encoded) – is located in a single 650kb JSON-encoded file called content.json. This means the initial loading of the page is quite slower than the user would normally expect, but once the initial payload has been delivered, it’s a relatively smooth browsing experience thereafter.

And as John Gruber already pointed out, this data is stored locally with the help of HTML5, allowing the user to continue reading even while offline!

iPhone user guide in Safari

iPhone user guide in Safari

PastryKit unminified and explained (sorta)

What I’m excited to show you now is a result of a bit of effort to make PastryKit more intelligible. Though there’s a minified version of the code on Apple’s website, it’s not obfuscated (and rendered unintelligible), so not all hope is lost! With the help of jsbeautifier.org we can now see the slightly unminified version of the code: PastryKit.js unminified.

The next thing I did was separate each module into its own file. I was able to separate the code into 27 numbered files, with the original ordering preserved (to prevent issues with dependencies). Viewing the code in this way definitely helps make sense of it all. You can download these separate files as part of a little unofficial SDK I made, which also includes a copy of the iPhone user guide with the JS iPhone-only redirect removed: PastryKit unofficial SDK.

PastryKit modules

The following is an explanation of each module I found. The descriptions are definitely incomplete and possibly inaccurate, so any comments or help is appreciated. But this should hopefully shed some light on the matter!

  • PKUtils – general helper functions (PKUtils.t() is a wrapper for CSS translate3d, PKUtils.degreesToRadians(), etc, etc.)
  • PKEventTriage – general event handler
  • PKPropertyTriage – handlePropertyChange() method – ?
  • Element – helper functions added to HTML Element prototype
  • Node – adds getNearestView() method to HTML Node prototype
  • PKClass – custom-rolled class with with “inherits” and “synthetizes” properties
  • PKObject – custom-rolled object with observer pattern. Most modules extend from this.
  • PKPoint – wrapper for WebKitPoint – used for touch events?
  • PKSize – wrapper for width/height properties
  • PKImage (inherits PKObject) – helper for creating Image elements and knowing when it’s finished loading (but doesn’t add the image to the DOM)
  • PKAnimator – basic animation tweens
  • PKTransition – helper for proprietary Webkit CSS transitions
  • PKTransaction – interacts with PKTransition – ?
  • PKView (extends PKObject) – manages a view, such as handling events that occur within that view – ?
  • PKContentView (extends PKView) – ?
  • PKRootView (extends PKContentView) – ?
  • PKScrollIndicator (extends PKView) – custom scrollbar
  • PKScrollView (extends PKView) – handles dynamically positioning the page when it’s scrolled
  • PKTableView (extends PKScrollView) – handles more touch/scroll events?
  • PKCellPath – ?
  • PKTableViewCell (extends PKView) – ?
  • PKToolbar (extends PKView) – manages the top toolbar
  • PKNavigationView (extends PKView) – manages bottom navigation bar
  • PKNavigationItem (extends PKObject) – manages bottom navigation buttons
  • PKControl (extends PKView) – manages generic controls
  • PKBarButtonItem (extends PKControl) – manages button controls
  • PKSearchBar.js (extends PKView) – manages the search bar

Conclusion after a first glance

As far as I can tell, this is no full-fledged JavaScript library. At least not for now.

On first glance PastryKit seems to be at most a nice development framework for making web apps with the same look-and-feel of native iPhone apps. And this framework in many ways does this better than anything out there (at the moment).

I echo the sentiments of Gruber – I do hope we hear more about this from Apple!

Tags: , , ,

  1. Ustun says:

    Hi, trying to subscribe to your blog results in an error since the XML has a blank line at the top. Removing that line, one can successfully parse the XML and subscribe. (I tested this in Opera.)

  2. David says:

    Doh! Sorry about that. The Google Syntax Highlighter plugin was inserting a blank line. Fixed now :)

  3. Paul Petty says:

    David –

    Regarding the “650kb JSON-encoded file” … After tearing a part & snooping through the User Guide I found that what’s most interesting is that Apple uses DATA URIs for lots of images (including inside that JSON fil). That drastically reduces the number of HTTP requests; great for WiFi. But even cooler, all that JSON is loaded into a browser-based SQLlite Db via JavaScript. Between using a local Db in the browser and HTML5 Page Caching it’s no wonder that the web app feels very fast on revisiting the UI.

    Paul

  4. [...] PastryKit Apple’s own Mobile Safari web framework for creating web apps that are nearly indistinguishable in their performance and look-n-feel from native apps. [...]

  5. [...] about it; that set off a minor feeding frenzy of digging deeper into it all over teh intertubes, like here, and here, and [...]

  6. [...] PastryKit is Apple’s undocumented not-yet-released framework for making iPhone web layouts work like native. IT’s very pretty, but this prettyness comes at a cost: there’s no docs, no help, and using it probably will get your app banned (Apple’s obscure denial rules, of course). To check it out, open http://help.apple.com/iphone/3/mobile/ on your iPhone. Any other browser gets detected, and blocked. [...]

  7. [...] Another framework worth noting is Apple’s own PastryKit. Although PastryKit’s UI isn’t cross-platform, it does have some nice tools for iPhone-specific web apps. Keep in mind, though, that PastryKit is not officially documented. Daring Fireball has a nice video overview, and developer David Calhoun has dug a bit deeper into how PastryKit works. [...]

  8. Todd says:

    Looks like PastryKit was just the predecessor to iAd.js — the current iPhone help uses iAd.js and some glue code from the original PastryKit.

  9. @Todd Wow! I think you’re right. A lot of the PastryKit methods look like they map onto the new iAd methods! Good to see parts of PastryKit were finally released!

  10. [...] I wouldn’t be so excited about a new technology to deliver ads, but a reader on my developer blog pointed out that Apple’s internal mobile JavaScript framework PastryKit seemed to be the [...]

Leave a Reply