It’s interesting that 2 months after an Adaptive Path essay coined the term “Ajax,” Apple released Mac OS X 10.4 “Tiger”, with its amazing and powerful dashboard widgets system. Within a couple of months, there were over 1,000 widgets available on the web, and these little babies were capable of completely replacing (almost all for free!) a number of system utilities, menubar items, and whole applications on the Mac. I’m tempted to think that awareness of Apple’s widgets helped promote awareness of, and interest in, what could be accomplished with rich Ajax/DHTML toolkits. After all, widgets are simply little Ajax/DHTML programs running in a special layer of Mac OS X called the Dashboard… They use exactly the same technologies as all of the Ajax/DHTML libraries, and in fact you can run them inside of Safari outside of the Dashboard.*
And so, it was fitting that when I finally found time to work on xCuts, a widget I’d been planning to build since last summer, I decided to use one of the leading Ajax/DHTML toolkits rather than Apple’s own, for most of the widget’s functionality. Having done most of my recent DHTML web work with Prototype and its light-hearted, freewheeling sidekick, Script.aculo.us, I naturally turned to those libraries to help me out.
Whenever I use script.aculo.us, I invariably get carried away and overdo the cool effects. (Witness this website!) But I do only use the effects when you’re supposed to–namely, as a visual cue to the user that some page content has changed. Without this visual cue, content can change so fast and smoothly on an Ajax page that users may not realize anything has happened… especially if they’re expecting the link they clicked to cause a page refresh that never comes. As an example, consider this paragraph with different text stored on the server., which replaces
See what I mean? Even though your eyes were actually on the content that changed, the difference was so subtle you might have missed it. Now take a look at the lists of articles and news items in my navigation panels in the sidebar. Without Ajax, one list would give way to another so similar-looking that you might not notice. On the other hand, if you add an effect or two to the change, it’s impossible to miss. For example, this paragraph with another one from the server., which replaces
Now, having said all that, my primary failing is in going overboard with the effects. Rather than one simple yellow-fade, I prefer a yellow-fade combined with a slide-down, or perhaps a slide-down combined with a scale-up. But hey–don’t blame me! Blame that elvin genius Thomas Fuchs, who keeps thinking these things up. Why, just this week he published an article explaining how to do custom effects, as if the ones that come with script.aculo.us aren’t enough! If you’ve looked at this library, you know that what I’m saying is true. In addition to some powerful Core Effects (opacity, scale, moveby, highlight, and parallel), script.aculo.us comes with a series of Combination Effects, which are built using the core ones. In fact, it’s the “Parallel” core effect that makes this magic possible, allowing a developer to mix and match the core effects as much as their time and imaginations permit.**
But that’s not all! I haven’t even mentioned the possibility of using Callbacks, Transitions, and Effect Queues to fine-tune your effects… As much as I’d like to, I don’t have time right now to go into a full tutorial on the script.aculo.us effects, but fortunately, the script.aculo.us wiki is bursting with useful demos, reference documentation, and sample code to study. I usually start at the wiki’s All Pages view, which links to pages describing all the script.aculo.us functions, most of the relevant prototype functions, and all the demos and other documentation as well.
So I approached building the new xCuts widget as if it were basically a little web page that uses prototype and script.aculo.us to work its Ajax magic.*** Besides the animation, effects, and basic Ajax server calls, the widget incorporates the very popular live search form, which is my first implementation. It was actually surprisingly easy to build using prototype’s Ajax.Update function. Speaking of the search, the input element implements Apple’s HTML extensions, which were actually developed as part of Dashboard but can be used on any website as well. Using them, you can surprise Safari-toting visitors to your website with nice, rounded search forms… you know, the ones with the little magnifying glass filling one end and the spiffy focus, blur, and clear bits Mac OS X users have come to expect from native Cocoa apps. Though they are non-standard, these extensions do no harm to other browsers and merely enhance the web experience for WebKit users.
In addition, at the last minute I found the great DOMinclude library from Chris Heilmann, which came in handy to add the “i” supplemental information about certain shortcuts. Here’s a case where DHTML (Chris would prefer we start referring to it as DOM scripting, and he has a point, but habits are hard to break…) can come to the rescue: How can you present a lot of information on a keyboard shortcut in a compact space? There are always trade-offs in such a design, but I try to focus the user’s attention on the primary bits of info and provide secondary info in an opt-in format of some kind that doesn’t detract from the presentation or otherwise draw too much attention to itself. As I saw it, I had three options:
- Squeeze the “other info” data column in either a third column of the lists, or as a second paragraph in the second column. The first option ended up squeezing the first two columns too much, which seemed silly since only a few shortcuts need the third column. The second option mingles the “other” info column with the “action” column, which may not be appropriate in many cases. It also makes the whole list longer than necessary.
- Use DHTML to slide in the “other info” data as a new row, just beneath the row for its shortcut. This would have been an effective choice, but was going to take a bit more custom programming and would have caused the whole column to shift up or down a lot, which seemed a bit ungainly.
One small note is that as I got the widget built out I wanted users to be able to copy and paste from it if they chose. Looking around, I noticed that nearly all Dashboard widgets only had text-selectable sections in form fields. That’s because the onmousedown function that lets you drag widgets around the Dashboard also prevent the widget from understand a “copy” style mouse drag. I finally found one or two widgets that overcame this, and a quick visit to the Apple Dashboard docs revealed that the proprietary CSS code that implements the drag function is DOM-element-specific. In other words, though most developers seem to go with the default example code Apple provides, which applies the “-apple-dashboard-region” style to the whole face of the widget, you can instead restrict the region to whatever parts of the widget you want to be draggable. Cool.
So… what did I use to build this widget? Gather round, and I’ll share this secret with you. Shhhh!! Here it is:
Find a widget you like, and use its code as a starting point.
As I pointed out last summer, one of the best things about building widgets is also one of the best things about building web sites: It’s all open-source code, and most developers release under free and open licenses that don’t make you feel like you’re stealing if you borrow a function here or there. That was certainly the case with one of my favorite widgets, SeeSS, a great CSS reference widget. Besides being at my fingertips when needed, I love this widget because it curls up into a tiny ball when you’re done, taking very little screen space. I also admire its overall layout and the fact that you can resize it as needed. By the time I was done, there really wasn’t very much of SeeSS left, but it was a great way to jump-start my work and gave me a nice framework to build from.
Tools? Definitely Widgetarium from Gandreas Software. I used this program for my first widget last July, and it has grown seriously more powerful since then. First of all, Widgetarium is great because you can start a project by choosing “File/New Project from Widget…”, after which you simply browse to any widget on your system, and select Open. Widgetarium automatically builds a new project for you from the components of that widget, including all image files, scripts, other source code, and–most conveniently–the XML .plist files without which the widget won’t work in Dashboard. After that, you can start tinkering with the code as you please without, of course, affecting the original widget.
Next, this tool still has that nice transparent window in which the widget builds, so you can stop and restart it all without leaving Widgetarium. As before, it has nice graphics tools for building pieces of the widget, but now you five tools instead of one. Besides the basic Panel Maker, you get a Button Maker, an Icon Maker, a “Roundie” Maker, and a slicing tool that lets you chop a panel into smaller pieces. I still export all the pieces to Photoshop for fine-tuning, and use Photoshop for the overall graphic design of the widget, but unless you’re extremely picky, the graphics tools in Widgetarium will give you a nice jump start on assembling the images you need. (You know, I’m seriously thinking of testing out other graphics editors since Adobe’s taking so long to get Photoshop Intel-ready. Anybody else thinking along those lines?)
Just as useful is the DOM tree Widgetarium provides. Here, once you navigate down to a particular node, you get 4 panes of info about the node:
- Attributes: The node’s ID and all other attributes (like attached events) visible in the HTML source code
- Value: Only for text nodes, this contains the displayed text
- Style: The node’s CSS style as defined in the project’s style sheet(s), and
- Properties: I invariably find this the most interesting pane. Here you’ll find the node’s offsetParent, its parentElement, and its top and left offset measures (see screenshot).
Even better than Widgetarium is the WebKit team’s Web Inspector, which presents the DOM and its nodes and styles in an incredibly compact, useful interface. The only problem with Web Inspector is that it isn’t finished. For now, it provides the Attributes, Value, and Style information you get from the other tools (including the “computed” style that’s so important in debugging), but not the Properties information. Web Inspector has two panes that stand empty as “Not finished” for now: Metrics, and Properties. I can’t wait to get them! Just like Mozilla’s Inspector, WebKit’s highlights the elements you select as you navigate, but Web Inspector has a far superior search interface. If you’re used to the Mozilla DOM Inspector search tool, you’ll be blown away by what you can do in Web Inspector.
- A pulldown showing various options for auto-indent, code-folding, syntax-coloring, line-numbering, and so on.
- A quick “go to line number” search, and
- The ability to split panes–as many times as you could possibly want! There are times I’d like to be able to bring another file into one of the split panes, but that wasn’t possible
The editing environment in Widgetarium is good, but not great. To improve it, my primary suggestion to the developer is to implement a single tabbed window. I find navigating among four or five open source code windows a bit tedious, especially after getting used to tabbed editing in BBEdit, TextMate, Eclipse, etc. Still, I no longer find myself using Widgetarium for some things and BBEdit for others, like I did last year.
There are many more useful features to Widgetarium, which I don’t have time to go into detail about but want to just mention here to whet your appetite (assuming you have one by now):
- Customizable syntax coloring
- Customizable key bindings
- Built-in lint and syntax checkers
- Incremental search option (should be the default, actually)
- Screenshot export options
- Image files viewer
- Top-notch documentation
- Built-in extensions for working with audio, speech, AppleScripts, data from Spotlight, the Mac OS X clipboard, the file system, and more.
If it sounds like I’m a Widgetarium fan, you’re right… I am. And if the developer continues to improve this tool, pretty soon I won’t have any quibbles with it at all! At $50, I’m more than glad I shelled out the bucks last summer.
It’s hard to believe I could have so much to say about this simple little widget. As usual, I meant to sit down for an hour and found myself writing for four instead… All without even talking about the widget’s functionality! I guess you’ll have to figure that out for yourself! I hope you find it useful and enjoyable, and please let me know if you think of a good idea for improving it.
But most of all, have some fun building your own Ajax/DHTML widget!****
* Yes, I know that widgets can incorporate many native Mac OS X technologies that web pages can’t–like AppleScript, Core Data, file system calls, Core Image, and so on–and some of them do. But they don’t have to, and most of them don’t.
*** Both libraries were updated to new versions during development, but xCuts 1.0 is behind one or two releases (it uses prototype 1.5.0_pre0 and script.aculo.us so the 1.5.3). I’ll be updating xCuts soon to bring it up to the latest (prototype 1.5.0_rc0 and script.aculo.us 1.6.1).
**** If you want to build for Windows or for a browser other than Safari, check out Yahoo’s free Widget Engine, or Opera’s spanking new
Widgets API, which you can check out in the Opera 9 public beta.