Thursday, August 2nd, 2007

Stuffing more Ajax in the Backpack

Category: Prototype, Scriptaculous, Showcase

Backpack, the simple web-based manager of to-dos, notes, ideas, and schedules from 37 Signals, has had an upgrade.

The team discussed some of the changes, and the biggest addition is the ability to move any “widget” (note, to-do list, picture gallery, etc.) anywhere on the page, or even to another page.

We talked to Sam Stephenson, also of Prototype acclaim, to get his thoughts on the changes, and what we may see in Prototype and coming out of this practical work. He gave us some detailed thoughts, and posted them on the 37 Signals blog:

Sam on Backpack

Under the hood, Backpack’s Pages tab has been completely rewritten. We moved nearly all of the application’s UI logic out of hand-written JavaScript files and into Ruby using RJS templates. This resulted in approximately 1600 fewer lines of application JS, and let us deliver pages with substantially less markup, since the edit states are now loaded on-demand instead of included in bulk with each page load. In addition, we’re running Backpack on the latest versions of Rails, Prototype, and from SVN.

Most of the custom JavaScript in the new Backpack is used for wiring the interface in reusable ways. We’ve built a handful of mini-libraries that sit on top of Prototype and, and we’re using them in several of our other applications in addition to Backpack.

One of these libraries adds support for specifying a CSS selector for Sortable containment. It uses Prototype 1.6’s new Function#wrap to add the behavior in an aspect-oriented way without modifying the original Sortable source code. This is the library that powers Backpack’s widget reordering. It’s currently being used in Backpack and Basecamp.

Another library, internally called Hover Observer, uses an unobtrusive technique (monitoring the entire page for mouse movement) to add and remove a “hover” class on element hierarchies with certain class names. Combined with CSS, this allows us to easily show the edit/delete/move “nubbins” when you mouse over widgets on the page, or show drop-down menus when you mouse over applications in Open Bar.
The library also lets us specify enter and exit delays, so if you accidentally mouse outside of a target area, the hover class isn’t removed immediately. Think of it as a cross-browser implementation of the :hover CSS pseudo-class, on steroids. Hover Observer was developed for Backpack and is now being used in Basecamp and Highrise.

The last library is tentatively known as Transitions, and provides an extremely simple API for animating transitions between DOM states. The animation resizes and fades an element’s content from one state to another, much like the effect you see when switching preference panes in OS X System Preferences. You’ll see the effect when you edit any item in Backpack. Because the API is simple, RJS-compatible, and easy to integrate into existing applications, we were able to develop it and drop it into Backpack in a single weekend.

I’m extremely pleased with how everything turned out, and I’m looking forward to open-sourcing as much of our JavaScript infrastructure as possible in
the very near future. If you have a Backpack account, I hope you’re pleased with the changes, too. :)

Posted by Dion Almaer at 10:50 am

3.6 rating from 28 votes


Comments feed TrackBack URI

I’ll get to writing and releasing my own transitions library now that the details are divulged! ;)

Comment by Steve — August 2, 2007

I don’t know how you implemented it, but I am using this for a year now:

child 1: current state
child 2: next state, display: none


And this effect definition:

Effect.Ueberblenden = function(element) {
element = $(element);
var el_von = element.firstChild;
var el_nach = el_von.nextSibling;
var el_von_groesse = Element.getContentDimensions(el_von, “static”);
var el_nach_groesse = Element.getContentDimensions(el_nach, “static”);
var el_von_position = Position.positionedOffset(el_von); // [left, top]
Element.setStyle(el_von, {position: “absolute”, height: el_von_groesse.height + “px”, width: el_von_groesse.width + “px”, top: el_von_position[1] + “px”, left: el_von_position[0] + “px”});
Element.setStyle(el_nach, {height: el_von_groesse.height + “px”, width: el_von_groesse.width + “px”, top: el_von_position[1] + “px”, left: el_von_position[0] + “px”});
Element.setOpacity(el_nach, 0.0001);;

return new Effect.Parallel([
new Effect.Fade(el_von, {to: 0.0001, sync: true}),
new Effect.Appear(el_nach, {sync: true}),
new Effect.Clip(el_von, 0, {sync: true, scaleFrom: el_von_groesse, scaleTo: el_nach_groesse}),
new Effect.Clip(el_nach, 0, {sync: true, resize: true, scaleFrom: el_von_groesse, scaleTo: el_nach_groesse})
afterFinishInternal: function(){
Element.setStyle(el_nach, {height: “”, width:””, top: “”, left: “”, clip: “”});
}, arguments[1] || {})

(I am sure this blog will mess the indenting up, sorry for that)

This is for a application of mine so it might not work well in some DOM/CSS conditions. If anyone wants to use it, feel free and modify as you need while Sam wraps his version up.

Comment by Martin — August 2, 2007

Since the updates the grey background isn’t showing on pages (randomly)…

Comment by Alex Egg — August 2, 2007

Really cool write up. Insightful. Thanks Sam (and Dion)-

Comment by Mark Holton — August 2, 2007

interesting that rewriting their JS in Ruby saved them 1600 lines of code..

Comment by c — August 2, 2007

Well, that RJS still generates Javascript, so it does not say anything about the number of JS lines that get send to the client.

Comment by Martin — August 2, 2007

Well what do you know… the Jquery and Mootools fans have already invaded the comments of the Signals vs.Noise post BY THE AUTHOR OF PROTOTYPE . Have these guys no shame?

Comment by NR — August 2, 2007

DOM – we’re all in it together

Comment by carmen — August 2, 2007

Nice clone of the CNN web 2.0 Website^^

Comment by Steve Jobs — August 7, 2007

Leave a comment

You must be logged in to post a comment.