OWL Desktop With ExtJS colorful lead photo

About a year ago, I started an ambitious project to push the boundaries of what could be done with the ExtJS JavaScript framework. ExtJS had a "desktop" example to showcase their widgets, but it didn't do anything. I asked the question, could you make this work? Could you build a framework to bring traditional windowing OS concepts to the web? I started working on it in my own time, and soon had my answer: "yes".

To make it work, I built an MVC file-system, an application registry, a window manager, alerts and notifications, and a few simple applications inside the framework. The result is a fully-functional desktop environment. Try it yourself:

Go and play around with it: it's largely self-documenting. You'll find sample text files describing how things work and hints will appear automatically; there's even a built-in source code viewer.

It's not perfect. I learned a huge amount by exploring these ideas, I never put it through professional quality control. That's why it's sat on my hard-drive for a year; I didn't want to show it until it was "done," but couldn't really find any time to work on it. But I finally just said, "there are a lot of great ideas here, other's could learn from it, I'm just going to put it out there, perfectionism be damned."

The OWL Desktop project does not have an open source license yet; I have decided to reserve all rights for the time being. Partly because I know it's not quite finished, and partly because it's not really useful for anything beyond an idea incubator. I encourage you to read and understand the code, judge for yourself how useful each idea is, and to take that knowledge with you to your own projects rather than copying any code directly.

If you've had a chance to go and look at and are interested in how it works, I'm going to briefly go into some the biggest lesions learned from the project.

MVC File System

I wrote my own File and Directory classes to serve as models (the M of MVC) and gave them a good event model so that the folder window views (the V) could always show a synchronized, up-to-date view of what's really going on. The controller (the C) is the FileManagerApp, equivalent to Windows Explorer or Nautilus. It's basically an ordinary application. The file system is strict subset of the Unix file system: The rules for when you can view, edit, delete, rename, or move a file follow UNIX exactly, resulting in a familiar, time-tested, and intuitive system. However, there are no groups and only one privilege bit: public or private, so it's a simplified but faithful model of UNIX.

Drag and Drop

Implementing drag-n-drop between windows was kind of a pain, but absolutely necessary to get that "native desktop" feel. When windows overlap, and you drag a file into the intersection, both windows get notified of the drop. It took me a while to figure out what was going on and come up with a solution. I queued up drop events without processing them right away, and then had a deferred handler go back and determine which drop was on top and ignoring all the others. I had to dig pretty deeply into ExtJS's drag-n-drop library but in the end I learned a tremendous amount and got a pretty good solution.

Window Manager

Windows can be minimized or maximized. Every window gets an entry on the Taskbar that can be used to minimize or restore a window, or bring one to the front. All of this is possible because of the AppWindowMgr, a registry of windows. The Taskbar and AppWindowMgr have an MVC relationship: the AppWindowMgr has events that the taskbar binds to in order to stay in sync, and each AppWindow notifies the AppWindowMgr when it's created or destroyed.

Application Manager

Applications can be "plugged-into" the framework, by loading a separate .js file which registers the application with the AppMgr (a registry of applications.) This gets it an entry on the Start button. You can also register an application to be the handler for any number of file extensions: for example, the TextEdit app handles the ".txt" extension and the HtmlEdit app handles the ".html" extension. By using Dependency Inversion consistently, I've completely eliminated any dependency of the framework on individual applications, allowing any number of "apps" to be registered, even at runtime, longer after the initial page load.

Notifications

I introduced logging and notification utilities to serve as a Single Point of Logging as well as to provide a neat little prepackaged UI for showing them. Not only do these look cool, but they're recorded and available in the centralized SystemManager app. These are important services for a framework to provide; otherwise, everyone does it themselves in their own way, log files are fragmented, and the user experience is inconsistent.

Unit Tests

I'm a big advocate of unit testing, and for this project I wrote a complete JavaScript port of Kent Beck's unit testing framework. My implementation is more closely related to his Python unittest module than JUnit, because that's what I'm most familiar with. All essential features are there, though: separate TestCase, TestResult, and TestSuite classes, several test loaders, and a test runner, all de-coupled from one another. The test runner is the only piece that depends on the OWL Desktop framework, by design. To use this unittest framework in another project, all I'd have to write is a another test runner. It even includes a "MetaTest:" a unit test suite that serves to test the unittest framework itself, exercising all the various asserts and so on.

Utilities

Also included, in the top-level owl namespace, are some really powerful utilities: a clone() function, a powerful array search/slice utility, an extensible comparison operator called same() (inspired by the MochiKit comparison framework) and a namespace utility.

The last one, the namespace utility, is probably the most widely useful of them all. I can't even imagine starting a large JS project now without a similar utility. It's a small thing, to be sure, but is needed again and again. You can see throughout the source code how it's used to cleanly give each .js file its own namespace.

Thoughts

This project was the second time I designed a large JavaScript project from the ground up (the first being for my day job.) Where I'd turned right before, I now turned left, experimenting without pressure. The results were fantastic. This kind of "blue sky" project is opens up new horizons for you. Keep in mind, this is all pre-HTML5. There's no CSS3 here. But you'd be hard pressed to find a site that looks anything like this. To a web developer, this is very exciting, because it means we're definitely on the right road: there are vistas and mountain peaks that we haven't even begun to explore. There's so much open space to build into! And now that web standards are moving forward again... well, all I can say is it's going to be an exciting ride.

- Oran Looney October 30th 2010

Thanks for reading. This blog is in "archive" mode and comments and RSS feed are disabled. We appologize for the inconvenience.