The Dojo Toolkit and Deft

By on August 3, 2008 12:09 am

A new top-level package was recently added to the Dojo Toolkit called Deft — an acronym for Dojo Experimental Flex Technology. The Deft package was created and is maintained by SitePen’s Tom Trenka, taking advantage of Adobe’s new MPL licensing, and the corresponding APIs of the Flash Player. Most articles focus on Adobe’s Flex Builder, which isn’t open source or free. The majority of articles about Flex and the Flex Builder also put an emphasis on components developed using a combination of ActionScript and XML-based description files, known as MXML.

Instead of taking this approach, Deft focuses on ActionScript components created in support of the various projects within the Dojo Toolkit (mostly for DojoX). Deft source files are well organized based in part on the organization of other Dojo Toolkit projects, as well as the package structure required by the Flex compiler. Most Flex applications are based on the Flex AS3 Application class, which forces you to write at least one “controlling” MXML file in order compile your code. Instead of this, Deft components inherit primarily from the Sprite class — which allows you to write pure ActionScript code.

Compiling components within Deft

To compile code within Deft, we use the command line Flex compiler called “mxmlc” — which is available with the Flex Open Source SDK. You can use this command to compile both full Flex applications (i.e. with an MXML definition file) and Deft components.

First, grab the latest Dojo nightly build that contains Deft, or download it with Subversion.

Then download the Flex SDK. I recommend placing it in an easily accessible location, as we’ll be using some absolute paths. It doesn’t require installation, so it’s ready to go after it’s unpackaged.

Hello World

Now let’s start with some very minimalist AS3 code that we can compile:

package {
	public class HelloWorld {
		public function HelloWorld():void {
		
		}
	}
}

This will be a top-level package (on the same level that our compiler will be) so we just use “package” without giving it a name (more about packages later). The next line is our class declaration, which is the same name as our file. And next is our constructor.

Of course, this will compile, but would be quite useless. Here’s a little bit of code that will add display capabilities, and add a text field to the stage:

package {
	import flash.display.*;
	import flash.text.*;
	public class HelloWorld extends Sprite {
		public function HelloWorld():void {
			dbgText();
		}
		private function dbgText():void{
			var myText:TextField = new TextField();
			myText.text = "Hello World";
			myText.background = true;
			this.addChild(myText);
		}
	}
}

This will give you a basic text display object on the Stage. If you’re used to AS2, some of the new concepts can be tricky. In AS3, there’s no _root or _level0, and not a very obvious way to attach display items. Here we are importing the flash.display package, which includes the Sprite class that we’re extending. The Sprite class can be thought of as a stripped down version of MovieClip. Since a Sprite is a child of the Stage, it contains methods for adding display elements – in this case, our TextField, which gets added with addChild().

Now let’s open Terminal and compile the code. I’m going to be using Unix conventions here, but for Windows users, it’s not much different. The basic parameters for our compiler are: mxmlc, file-input, file-output.

Now it Gets Tricky

NOTE: The path to my dojotoolkit directory is /Users/mike/Sites/Tests/. I’m going to represent this path with a tilde (~) to help make things clear. But I recommend use all absolute paths initially.

Package names, the directory structure, and the current “location” of compiler must all be in sync, or you’ll get the inevitable error:

Error: A file found in a source-path must have the same package structure
  '(folder name)', as the definition's package, '(package name)'.

Our HelloWorld.as file is going here:

~/deft/trunk/deft/HelloWorld.as

…and we will navigate our command line to the same location. Compiling from here should work. But in my case I got the dreaded error shown above. I fixed it by adding another parameter to the command:

-source-path= ~ /deft/trunk/deft

This clearly defines the root of the package. Finally we define the output file, which will also be in the same location:

-output= ~ /deft/trunk/deft/HelloWorld.swf

The following is my Terminal command for compiling. If you add the mxmlc to your system path, you can use mxmlc instead of the entire path. NOTE: This is formatted for readability. I used line breaks instead of spaces for clarity.

mike$	/Users/mike/Documents/FlexDocs/flex_sdk_3/bin/mxmlc 
-source-path= ~ /deft/trunk/
HelloWorld.as 
-output= ~ /deft/trunk/HelloWorld.swf	

If successful, the last line will print HelloWorld.swf. If that’s not there, you’ll be shown an error. The most common error at this stage of setup is about the path conforming to the class name – but other common errors involve naming conventions and incorrect syntax.

Shell Script

That was a heck of a command to be typing. The simplest thing to do is put this in a shell script. This way, more complicated scripts can be written, but more importantly, this long command can be saved to disk. Here are the steps for anyone not familiar with shell scripts:

  1. Copy and paste the previous command into a text file.
  2. Save the text file in the same path location as the HelloWorld.as file, and name it HelloWorld.sh (in Windows it would be .BAT). Make sure it was saved with that extension, and not something like “HelloWorld.sh.txt”.
  3. You may have to change the permissions to make it executable. Go back to your Terminal (if it’s still open, we should still be in the right directory) and enter: chmod 777 HelloWorld.sh

Shell scripts are protected from external attacks by requiring you to use a period slash before your script name. So to execute the script, type:

./HelloWorld.sh

Now it’s easier to maintain that long command. You can of course add more options to it, or loop through and compile several files, or any other shell script wizardry you can dream up.

Hello Real World Example

Deft Multi File Upload Shot

Now let’s look at one of the latest projects in Deft, the Uploader. The fully qualified class name is deft.form.UploaderUploaderis the class name, and deft.form is the package to which it belongs. It’s very similar to Dojo’s package system – the compiler reads the import of a deft.form file, and expects to look in a deft folder, and then a form folder. In our HelloWorld example, there was no package name – so the compiler expected to find the file in the same folder where it resided.

deft.form.Uploader is the main file and imports two other custom files, deft.form.UploadList and deft.common.debugging.Tracer. Tracer is a multi-output debugging tool, which can parse and log objects and messages to the Output panel in the Flash IDE, the Flash Player Debugger, and/or the Firebug console.

You’ll find that the shell script, “uploader.sh” is located in the trunk, the same level as the deft directory. You’ll see how the source-path option points to the location of the shell script, and the path to Uploader.as is continued from there. Finally, the output points to a location where the SWF will be used in dojox.form, in the resources folder.

You won’t have to go through this build process to use dojox.form.FileInputFlash. All you have to do is get the latest Dojo nightly build or wait for the 1.2 release, and the SWF will be in the resources/ folder. The Deft files are there in the event that a developer needs to make custom modifications for a project, or permanent modifications, and optionally contribute them back to Dojo.

Those are the basics for SWF compilation. The Deft project is still in its infancy, but there are currently a few goodies in it including the multi-image uploader, pre-alpha quality support for dojox.gfx. Future plans include support for audio and video. Hopefully Adobe will continue its current path towards being open source friendly, helping Deft flourish.