Passing Data with Dojo
Introduction
Dojo is a toolkit devoted to making web applications easier to write. One feature that's been recieving a lot of attention lately is fetching data in the background using Javascript. GMail uses it to make the pages seem faster by fetching them before they're needed. Google Maps grabs parts of the map as you scroll around, so you don't have to load the whole thing.
As with all good things in Javascript, there's a lot of cross-browser compatiblity and user friendliness issues to deal with. The Dojo Toolkit can help with that. This article will just introduce the basic ideas and techniques for passing data to and from a server.
Introducing dojo.io.bind()
The Dojo method for getting a file is dojo.io.bind(). You
need to pass it some arguments in the form of an object with some
properties. For example, you could call it like this:
var params = new Object();
params.url = "something.txt";
params.load = someFunction;
dojo.io.bind( params );
Hello world!
I'm just a plain text file!
function dumpData( type, data, evt ) {
var msg = "Data dump:\n" + data;
alert( msg );
}
dojo.io.bind({
url: demoLocation + "demo_text.txt",
load: dumpData,
mimetype: "text/plain"
});
The curly braces are part of a shorthand syntax for creating an object in Javascript. It's sort of like declaring an array:
var arr = [ 1, 2, 3 ]
var obj = {
prop1: 1,
prop2: 2,
prop3: 3
};
arr[ 0 ] + obj.prop1 // 1 + 1 = 2
Note that in the above example, we pass three parameters to
dojo.io.bind():
url- URL to loadload- Javascript function to call once the data is done loadingmimetype- "MIME type" of the data. Common types includetext/plain,text/html, andtext/javascript.
Handling Errors
Not everything goes well. It's good practice to define a function for
handling errors, in case something goes wrong. You can tell
dojo.io.bind() what to call by specifying an
error parameter.
function errorHandler( type, error ) {
var msg = "Something went horribly wrong ...\n" +
error.message;
alert( msg );
}
dojo.io.bind({
url: demoLocation + "this_does_not_exist",
load: dumpData,
error: errorHandler,
mimetype: "text/plain"
});
In case you're wondering, the "SampleTransport" part tells you how Dojo is communicating with the server.
Running Javascript
So far, we've just loaded some text. You can also load and execute some
Javascript from the server. It's run automatically, so the
load handler is unimportant.
function helloWorld() {
alert( "Hello world!\n" +
"I'm some javascript." );
return "I have returned";
}
helloWorld();
function showReturnValue( type, evaldObj ) {
alert( "The script returned\n" +
evaldObj );
}
dojo.io.bind({
url: demoLocation + "demo_javascript.js",
load: showReturnValue,
error: errorHandler,
mimetype: "text/javascript"
});
Using a Query String
So far you've gotten some text and some code. You can read it and run
it. How about sending some data to the server? The most basic way to do
this is to add a query string to the URL. It's just an extra part in the
form of ?var1=something&var2=something_else
<?php
print "I'm a PHP script. This is what I recieved:\n";
// $_GET is a PHP array that holds recieved data
// print_r prints it out nicely
print_r( $_GET );
?>
dojo.io.bind({
url: "demo_php.php?foo=bartok",
load: dumpData,
error: errorHandler,
mimetype: "text/plain"
});
Submitting a Form
Another classic way to send data is using a form. The major advantage of
using dojo.io.bind() instead of a submit button is that the
page doesn't change. This means you can get data from the server while
the user is still editing the form (a la Google Suggest). You
can do it just by passing the form node as a parameter, aptly named formNode.
<form id="demoForm" action="demo_php.php">
<input type="text" name="baz" value="something" />
<input type="submit" name="submit" value="Don't press!" />
</form>
Client-side Javascript:
dojo.io.bind({
// look ma, no URL!
// (the form's action property is used)
load: dumpData,
error: errorHandler,
formNode: document.getElementById( "demoForm" ),
mimetype: "text/plain"
});
bind() is useless. Also, GET is always used.
Submitting Forms Made on the Fly
Sometimes you just want to send some data back to the server, without
the user fiddling with a form. Query strings are cryptic and a pain to
write by hand. If you use a form on the page, then you'd have to disable
it. Instead, you can just create the form using Javascript and pass it
directly to dojo.io.bind(). It never appears on the page.
// helper code omitted ...
function buildForm( loc, data ) {
var form = document.createElement( "form" );
form.action = loc;
for( prop in data ) {
buildFormHelper( form, prop, data[prop] );
}
return form;
}
function makeInput( form, name, value ) {
var input = document.createElement( "input" );
input.name = name;
input.value = value;
form.appendChild( input );
return true;
}
function buildFormHelper( form, prev, data ) {
var name;
if( ( typeof data == "object" ) ||
( typeof data == "array" ) ) {
for( prop in data ) {
name = prev + "[" + prop + "]";
// recurse
buildFormHelper( form,
name,
data[ prop ] );
}
} else {
// literal
name = prev;
makeInput( form, name, data );
}
}
function buildForm( loc, data ) {
var form = document.createElement( "form" );
form.action = loc;
for( prop in data ) {
buildFormHelper( form, prop, data[prop] );
}
return form;
}
var data = new Object();
data.foo = "bar";
data.arr = [ 1, "hello", 3 ];
dojo.io.bind({
load: dumpData,
error: errorHandler,
formNode: buildForm( "demo_php.php", data ),
mimetype: "text/plain"
});
Limitations
There are some limitations placed on your script.
- You can only load data from your own domain. For example your script running on foo.com can't load search results from google.com . This is to prevent you from sending user data elsewhere.
- You can not send data to the server using the POST method (yet) or upload files.
Conclusion
You can start making your applications more interactive right now, and Dojo will make it easier. Once you have some experience with the basics, you can also use Dojo to make your application friendlier. There's much more planned for the toolkit, so check DojoToolkit.org for more information and releases.