Menu

Think Spring

March 4, 2003

Jon Udell

It's been a long, cold, hard winter here in New Hampshire, and the snow is still pelting down. As I dream of spring, I've been taking another look at Spring, User Creations' "concept-centric" visual organizer for OS X. If you're running OS X, you can give Spring a fling with very little investment of time and effort. It's lightweight, non-invasive, and free: though User Creations would love you to license your copy. If you're not an OS X user, you might want to read this Register story by Andrew Orlowski, which traces the lineage of Spring (and Stardock's DesktopX) back to the likes of OpenDoc and Cairo. Orlowski nicely captured the essence of Spring:

Spring gives you a variety of panes, with objects inside them that can be grouped. These can tap into the underlying infrastructure -- the OS X address book, or AIM, or iTunes, or the Sherlock web services client -- thanks to the much underrated power of AppleScript. It's exceedingly well done and Spring offers you a way of organizing your life, and files, as you wish.

Books are one of the object types you can place on a Spring canvas, associate actions with, and trade (mainly, for now, by way of AIM) with other Spring users. When I first began writing about my LibraryLookup project a few months ago, Spring's creator Robb Beal wrote to me suggesting that he add LibraryLookup to the list of context menu actions associated with a Spring book object. When I noticed that Spring 1.2 didn't yet include that action, I decided to see for myself how this integration could be achieved. It was remarkably easy. There's almost no documentation for Spring, but none was needed. Nor, as it turned out, were any OS X or AppleScript skills required. Although it runs only on OS X today, Spring objects are wired together using the basic principles that I know and love: URL-based services, XML data, pipelined transformations.

When you install Spring, you'll find a collection of book objects in the directory SPRINGHOME/Spring/Spring Objects/Books. Each object is a directory named for the title of the book (e.g., BuildingCocoaApps.obj), containing an image of the book's cover and a data.xml file. Inside the data.xml file you'll find the usual book metadata: title, Asin (Amazon's name for ISBN), price, author(s), publisher, and so on. You'll also find an objectUpdateURI and an actionUpdateURI. For books, the actionUpdateURI points to http://www.usercreations.com/spring/objects/books/lite/actions.xml, which contains actionPairs like this one:

<actionPair>

  <actionName>

    Purchase at Amazon 

  </actionName>

  <actionURITemplate>

    http://www.amazon.com/o/ASIN/{Asin}/

  </actionURITemplate>

</actionPair>

It's easy to see how this works. When you drag BuildingCocoaApps.obj from Finder to a Spring canvas, you create a book object. Its visual representation is the cover image contained in that directory. The context menu (CTRL-click) lists the names of the actionPairs encoded in actions.xml. The actionURITemplates are URLs parameterized with variables corresponding to the metadata values stored in data.xml.

On my first iteration, I hardcoded an action that searches for a book in my local library's OPAC (online public access catalog):

<actionPair>

  <actionName>

    LibraryLookup (hardcoded)

  </actionName>

  <actionURITemplate>

    http://ksclib.keene.edu/search/i={Asin}

  </actionURITemplate>

</actionPair>

Then I tweaked the actionUpdateURI in data.xml to point to a modified actions.xml, including this new action, which I placed on my weblog. Now when I dragged BuildingCocoaApps.obj to a Spring canvas, the new action was available on the context menu. All done, right?

Not so fast. Unless you also live in Keene and use my local libraries, that action is not going to be useful to you. Central to the Spring experience is the ability to trade objects, by dragging them to objects that represent people. If I drag the book to your picture on a Spring canvas in order to AIM the book object to you, you'd prefer that the LibraryLookup function refer to your library rather than mine.

I can't solve that problem for you, but I can solve it for myself, and I can show you how to solve it for yourself. Spring's personalization system (Spring -> Me...), which stores the standard metadata that you use to create your person object (email address, AIM screen name, website address, zip code, all the usual suspects), can be extended with custom attributes. Here, I've added a custom attribute:

Personalizing Spring with a LibraryLookup action template
Figure 1. Personalizing Spring with a LibraryLookup action template

The name of the attribute is LibraryLookup. Its value is the URL template for my library: http://ksclib.keene.edu/search/i=. And here's the actionPair in actions.xml, adjusted to refer to the custom attribute:

<actionPair>

  <actionName>

    LibraryLookup (custom)

  </actionName>

  <actionURITemplate>

   {@app@/custom/LibraryLookup}{Asin}

  </actionURITemplate>

</actionPair>

If your Spring setup is customized in the same way mine is -- see the LibraryLookup generator for examples of the six general URL templates I've identified so far, which cover thousands of libraries worldwide -- we should be able to trade book objects while preserving each book's ability to look itself up in the appropriate local library.

But where do those books come from? The Books subdirectory of the Spring installation, which includes a handful of examples, also provides a URL that acts like an object factory:

You can generate Spring books by simply dragging URLs (from a browser or any text editor). For example, drag this URL to Spring:

http://xml.amazon.com/onca/xml?v=1.0 &t=usercreations-20 &dev-t=D1HTPQET64F8JH &AsinSearch=088730995X &type=lite &f=http://www.usercreations.com/xsl/amazonlite_dynaimage.xsl

To create a different book, simply replace the 088730995X above with the 10 digit ISBN/ASIN for the book.

This illustrates one of my favorite idioms at work. Using the RESTful variant of Amazon's API, you can fetch XML data about a book and pipe it through Amazon's XSLT processor for transformation. In this case the default transformation produces a standard Spring book object. We can easily intercept that transformation to extend the book object. And while we're at it, let's streamline the procedure for interpolating an ISBN into the URL that invokes that transformation:

var re=/([\/-]|is[bs]n=)(\d{7,9}[\dX])/i;

if (re.test(location.href)==true)

  {

  var isbn=RegExp.$2;

  var win = window.open

    ('','SpringBookFactory','resizable=1,scrollable=1,width=300,height=200');

  win.document.write('<html><head><title>Spring Book Factory</title></head> \

  <body><p>Drag this URL to a Spring canvas to create a book object:</p> \

  <p><a href=\"http://xml.amazon.com/onca/xml?v=1.0&t=usercreations-20& \

  dev-t=D1HTPQET64F8JH&AsinSearch='+isbn+'&type=lite& \

  f=http://weblog.infoworld.com/udell/gems/amazonSpring.xsl\">'+isbn+'</a> \

  </p></body></html>');

  win.document.close();

  }

Subtract extraneous whitespace, package it into this URL -- Spring Book Factory -- and you've got a LibraryLookup-style bookmarklet that you can drag to your toolbar and activate from any ISBN-bearing page at Amazon, All Consuming, or another book site. Clicking the bookmarklet's link brings up a window that contains a URL:

A bookmarklet-driven Spring object factory
Figure 2. A bookmarklet-driven Spring object factory

Drag that URL onto a Spring canvas to instantiate the book object. Because the URL replaces the default Spring XSLT file with one that redirects Spring to my weblog for the XSLT used when the object is refreshed, and for the actions.xml file that controls the context menus of derived objects, a book object created in this way has some new behavior:

A customized Spring book object
Figure 3. A customized Spring book object

In addition to the two flavors of LibraryLookup we've discussed, the context menu includes a "Visit in Safari Books Online" action.

It bodes well that Spring can be extended in these ways with no explicit support or cooperation from User Creations. The claimed benefits of Spring's visual approach are, however, not all that compelling to me. Icon collections very quickly grow unmanageable in my experience, and I don't see how Spring can scale without reintroducing the very kinds of search and navigation that it wants to liberate us from. Direct manipulation of hundreds or thousands of discrete objects is a tedious chore, as anyone who's been the parent of a three-year-old well knows. So I don't expect to find myself using Spring canvases to completely reorganize my data and relationships. I do see great value in Spring's ability to push metadata defined in XML, and actions invoked by URLs, into concrete representations that we can include in rich documents and pass around over networks. Ironically, by encouraging us to create usable XML representations of people, places, and things, Spring can help lay a foundation for improving the classic modes of search and navigation.