Orange is my favorite color

I downloaded the Dojo Toolkit some time ago but the lack of documentation stalled my progress. For our version 3.2, there are a number of key improvements we want to make using DHTML and Ajax so it’s time to dive in head-first. We are not building a “Web 2.0″ app; we’re adding fancier Javascript and Ajax capabilities where they add value. Given how many web applications already exist, this is likely the more common model for experimenting with a toolkit like Dojo.

I’ve found these notes really helpful as a crib sheet for getting started but with the number of changes in Dojo since last year, a few things are already out of date. I’m going to record a multi-part series on getting started with the Dojo Toolkit with ColdFusion and how I’m solving some of my particular problems. Many of the notes will be helpful regardless of the server-side platform you use. If you’ve been searching Google as much as I have, this will be like a bottle of water in the middle of the desert – not enough to live on forever but certainly enough to keep going forward!

My assumptions:

  • You’ve already unzipped the Dojo release of choice into a directory on your webserver. I’m going to refer to my directory as “/bits/dojo/” so replace that with whatever your path actually is. I’m accessing Dojo as a Subversion external so I have the full 3.1 source tree in my /bits/dojo directory.
  • You have Firebug for Firefox or another client-side debugger. I don’t know how I would be debugging without it.
  • You understand how to create Javascript objects with shorthand. If you know Actionscript, this will be old hat. I’m referring to creating an object like: “var obj = {aKey: ’someValue’, aArray: [1, 4, 5], …}”. If not, search around for JSON first as I use this notation (and so do Dojo developers) frequently.

Dojo.require(…)

Dojo.require is sweet. It’s a packaging system so if you choose a barebones version of Dojo, you can load additional functionality on-the-fly. It’s mostly unnecessary if you use the “Kitchen Sink” build of Dojo but if you want to minimize file size, you’ll want to use this feature. However, it’s not always clear what to put into the require statement although there are some fresh docs in the Dojo Manual. I’ll show you some examples from my first real project:

dojo.require("dojo.debug.Firebug");
dojo.require("dojo.event.connect");
dojo.require("dojo.io.*");
dojo.require("dojo.json");
dojo.require("dojo.html.getElementsByClass");

For a production application, including dojo.html.* would be overkill when I only need the getElementsByClass() function.

However, trying to include only dojo.io.bind doesn’t work as there are support routines in the IO (the remote communications bits) library that are needed to make bind work, even though bind() is the only function I actually call.

How do you know which you need? So far, it’s trial and error with some poking in the source. Since the raw libraries are located in /bits/dojo/src/<library in question>, you can open it up and take a look at the line dojo.provide() to see what Dojo calls that file. Start off by including the entire library like dojo.require(“dojo.html.*”) and then winnow it as your development slows down to include only what’s necessary. It’s easy to tell when you’ve gone too far – refresh your page and you’ll find it no longer works!

Receiving Data with ColdFusion

In ColdFusion, I would normally submit a form post and then dump it with CFDUMP to see what is in there. If you’re making an Ajax call, you can’t see squat. This makes debugging a real PITA. It also means you can’t see how Dojo is even passing the data to your application. Let me save you some trouble with the following explanation:

sendData = function()
{
var bindArgs = {
url: "index.cfm",
method: "post",
mimetype: "text/json",
content:
{
save: 1,
data: prepData()
},
load: function(type, data, evt)
{
dojo.debug(data);
},
error: function(type, data, evt) { /* do stuff */ },
handler: function(type, data, evt) { /* do stuff */ }
};
var req = dojo.io.bind(bindArgs);
};

Let me address the bindArgs first, line by line:

  • The URL is obvious; it’s either relative (“../some/file.cfm”, “/hard/root/file.cfm”) or absolute (“http://domain.com/file.cfm”). It needs to be in the same domain as you loaded the toolkit from although there are ways around cross-domain restrictions.
  • The method is equally obvious – either GET or POST.
  • Mime type is whatever you expect back from the server. Dojo tries to be smart and do special things if you specify:
    • text/javascript – tries to evaluate and run the returned javascript
    • text/json – essentially eval()s the code returned
    • application/xml or text/xml – tries to create an XML document from the returned XML.
    • As of this writing, everything else (like text/plain and text/html, but also planet/foo) is just passed back as-is and you can work with it however you like.
  • Content is tricky. Many of the demos simply show you passing along a value like “content: myVarName”. If you try this with ColdFusion, you will find that it submits a dynamic number of FORM variables starting with index 1 and going up to the length of the submission. E.g., you could reference FORM["5"] and pull the 5th character of the post out. This is not really what you want when you’re a ColdFusion developer. Instead, you can pass in an object with named keys like I’ve done above. If you wanted to pass in different FORM variables, you just change my values for save and data to whatever names you like. In the above scenario, I can work with FORM.save (which has a value of 1) and FORM.data (which has the value returned from prepData()).
  • load, error and handler – think of these like a CFSWITCH/CFCASE statement where load is the function called when things go well, error is the function called when things fail, and handler is like CFDEFAULTCASE, the function called when neither of the above work. You don’t have to define the function right in line with function() { … }. You can instead reference a function you have declared somewhere else.
  • Dojo.io.bind is the magic that actually takes these arguments and executes the remote call. Every time I execute sendData(), the above arguments will be passed to dojo.io.bind() and the data will be sent to the server, in this case, to index.cfm via a POST with two FORM parameters: save and data.

Using JSON in Dojo

JSON is a short hand notation for writing Javascript that is typically smaller in size than XML. It makes it a good transport for data from client to server because of its small size. It wasn’t immediately obvious if I needed to use a third-party JSON encoder/decoder or if Dojo had one built-in. Thankfully there is one because they use it internally for dojo.io.bind() with mimetype “text/json”:

dojo.require("dojo.json"); // note this is NOT dojo.json.*
dojo.json.serialize(yourData);

To “deserialize” JSON, you just run eval(yourJSON). On the ColdFusion side, I’m using Jehiah’s JSON routines to encode and decode on the server. Pretty slick stuff. Let’s recap that workflow:

  1. Create some variables and data in your Javascript
  2. Transform the data into a JSON string using dojo.json.serialize()
  3. Send the data to the server via Dojo.io.bind with the JSON value in your “content” parameter
  4. Receive the JSON string as a FORM variable in ColdFusion and decode it using Jehiah’s decode routine referenced above
  5. Do whatever it is your server-side script might do such as work with the database, call a third party service, write a file, etc.
  6. Take the results and encode them into JSON and spit them back to the client. You will likely want to use CFCONTENT with the reset=”yes” in order to strip all of the whitespace or other content that might have come before your JSON string is output:
    ... (Lots of code that does something)
    <cfcontent type="text/json" reset="yes"><cfoutput>#jsonencode(someData)#</cfoutput><cfabort>
  7. If you used dojo.io.bind with mimetype “text/json”, then it should automatically eval the results. Otherwise, you can turn your JSON string into data by running: eval(returnedJSONstring);

Ok, that’s enough for round 1. Once finished, I’ll post some before-and-after examples of the utility that I’m converting and some metrics on how/why it’s better.

5 Comments

  1. Nathan Dintenfass said:

    on July 19, 2006 at 9:34 am

    Good stuff — can’t wait to see the rest of the series. Even if personally I’m so rusty that my coding days are seeming more and more a distant memory….

  2. Orange is my favorite color » Blog Archive » More on Dojo.require() said:

    on July 21, 2006 at 10:53 am

    [...] As I wanted to minimize the number of files included at runtime in my prior piece, I tried to narrow down my dojo.require() statements. Do this after you have done cross-browser testing! [...]

  3. fengtianxp said:

    on July 30, 2006 at 10:26 am

    Use dojo and json in ajax development

    TrackBack From:http://www.blogjava.net/fengtianxp/archive/0001/01/01/60920.html

  4. ramblings said:

    on October 12, 2006 at 3:41 pm

    [...] water in the desert No Comments so far Leave a comment RSS feed for comments on this post. TrackBack URI Leave a comment Line and paragraph breaks automatic, e-mail address never displayed, HTMLallowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> [...]

  5. Orange is my favorite color » Blog Archive » Dojo Toolkit Series: Finding a drink of water in the desert « The Screaming Carrot said:

    on October 26, 2006 at 10:37 am

    [...] Orange is my favorite color » Blog Archive » Dojo Toolkit Series: Finding a drink of water in the desert [...]

{ RSS feed for comments on this post}