BUY THIS BOOK
Add to Cart

Print Book $39.99


Add to Cart

Print+PDF $51.99

Add to Cart

PDF $31.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £24.99

What is this?

Looking to Reprint or License this content?


Dojo: The Definitive Guide
Dojo: The Definitive Guide By Matthew Russell

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Toolkit Overview
This chapter provides an overview of Dojo's architecture, takes you through installing Dojo, introduces some domain-specific jargon, runs through the bootstrapping process, and then provides some example code that should whet your appetite for the chapters that follow. Like any other introduction, much of this chapter paints in broad strokes and sets the tone for the rest of the book. Hopefully, you'll find it helpful as you begin your journey with the toolkit.
As you're about to see, describing Dojo as a toolkit is no mere coincidence. In addition to providing a JavaScript standard library of sorts, Dojo also packs a collection of feature-rich, turnkey widgets that require little to no JavaScript coding at all, build tools, a testing framework, and more. This section provides an overview of Dojo's architecture from a broad point of view, shown in . As you'll see, the organization for the rest of this book is largely driven by the toolkit's architecture. Even though DojoX is displayed as an independent entity from Dijit, DojoX resources could also be built upon Dijit resources, just as your own custom widgets could leverage any combination of Dijit and DojoX resources.
Figure : One depiction of how the various Dojo components can be thought of as relating to one another
The kernel of Dojo is Base, an ultra-compact, highly optimized library that provides the foundation for everything else in the toolkit. Among other things, Base provides convenient language and AJAX utilities, a packaging system that allows you to pull in Dojo resources on-the-fly instead of requiring them to all be slurped in when the page loads. It also supplies you with tools for creating and manipulating inheritance hierarchies, a means of almost universally querying the DOM using CSS3 selectors, and a fabric that standardizes DOM events amongst various browsers. Everything that Base provides is available in the top level of the toolkit's namespace as a dojo.* function or attribute. Base comes packaged as a single file, dojo.js, which comes across the wire at under 30KB, and when you consider that most Flash-based advertisements that inundate the web are considerably larger than 30KB, such a small number seems quite amazing.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Overview of Dojo's Architecture
As you're about to see, describing Dojo as a toolkit is no mere coincidence. In addition to providing a JavaScript standard library of sorts, Dojo also packs a collection of feature-rich, turnkey widgets that require little to no JavaScript coding at all, build tools, a testing framework, and more. This section provides an overview of Dojo's architecture from a broad point of view, shown in . As you'll see, the organization for the rest of this book is largely driven by the toolkit's architecture. Even though DojoX is displayed as an independent entity from Dijit, DojoX resources could also be built upon Dijit resources, just as your own custom widgets could leverage any combination of Dijit and DojoX resources.
Figure : One depiction of how the various Dojo components can be thought of as relating to one another
The kernel of Dojo is Base, an ultra-compact, highly optimized library that provides the foundation for everything else in the toolkit. Among other things, Base provides convenient language and AJAX utilities, a packaging system that allows you to pull in Dojo resources on-the-fly instead of requiring them to all be slurped in when the page loads. It also supplies you with tools for creating and manipulating inheritance hierarchies, a means of almost universally querying the DOM using CSS3 selectors, and a fabric that standardizes DOM events amongst various browsers. Everything that Base provides is available in the top level of the toolkit's namespace as a dojo.* function or attribute. Base comes packaged as a single file, dojo.js, which comes across the wire at under 30KB, and when you consider that most Flash-based advertisements that inundate the web are considerably larger than 30KB, such a small number seems quite amazing.
If you look at the actual size of dojo.js on disk, you'll see that it is around 80KB, but because web servers generally process content as it comes "across the wire" to the browser, it's the size of the compressed content that drives the amount of time it takes to download. If you manually apply gzip compression to
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Prepping for Development
You don't need any fancy tools nor do you have to be able to configure a beast of a web server like Apache to learn how to develop with Dojo. In fact, very few examples in this entire book require you to interact with a web server at all. Most resources will be resolved via relative paths on your local machine or they will be cross-domain loaded, so for the most part, it's just you, your favorite text editor, and your web browser.
There are three primary ways you can download Dojo and prep for development: downloading an official release, checking out the latest and greatest from Subversion, and using a cross-domain (XDomain) build that's available from AOL's Content Developer Network (CDN). Let's walk through each of these options. Although downloading an official release to your local machine may be the most typical approach, there can be specific value in the other approaches as well.
There are three primary ways you can use Dojo: downloading an official release to your local environment, checking out a copy from Subversion to your local environment, and using an XDomain build from AOL's CDN. This section walks you through each of these options.

Downloading an official release

Downloading the latest official Dojo release is by far the most traditional way to prep for development. An "official" release is really nothing more than a tagged, blessed snapshot from the Subversion repository that has been well-tested and that comes with some helpful release notes. You can find official releases of the toolkit at http://dojotoolkit.org/downloads; the only notable caveat when downloading an official release is that it does not come packaged with the build tools. To retrieve the build tools, you either need to use Subversion or download a source release, which you can find at http://download.dojotoolkit.org/.
When you uncompress the downloaded archive, you'll find it expands into a folder that has the general form dojo-release-x.y.z, where, "x," "y," and "z" correspond to the major, minor, and patch numbers for a particular release. To keep your setup and URLs as generic as possible, you may want to rename the folder in place so that it is simply called
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Terminology
It will be helpful for us to take just a moment and clarify some of the terms that we'll use in discussions throughout the book. A precise explanation of JavaScript's mechanics packs a lot of lingo that requires precise terminology, and the lines only get blurrier when you start building a powerful toolkit on top of it—not to mention a toolkit that does things like simulate classes for a language in which proper classes from an object-oriented context does not exist.
Hopefully, you'll find the following list of terms helpful as we progress through some of these murky waters:
Toolkit
A toolkit is simply a collection of tools. It just so happens that toolkits in the computer programming realm are frequently used within the context of user interface design. Dojo is most accurately defined as a toolkit because it's more than just a library of supporting code that provides a set of related functions and abstractions; it also provides items such as deployment utilities, testing tools, and a packaging system. It's easy to get wrapped around the axle on library versus framework versus toolkit, and so forth, but Dojo has been dubbed a toolkit, so let's go with it.
Module
Physically, a Dojo module is nothing more than a JavaScript file or a directory containing a cohesive collection of JavaScript files. As it turns out, this top-level directory also designates a namespace for the code it contains. In a logical sense, modules in Dojo are similar to the concept of packages in other programming languages in that they are used to compartmentalize related software components. Do note, however, that while Dojo's packaging system refers to the actual mechanism that performs tasks such as determining and fetching dependencies, Dojo modules themselves are not called "packages."
Resource
When it becomes necessary to split a Dojo module into multiple files, or when a module consists of only a single JavaScript file, each JavaScript file is referred to a resource. Although a resource could strictly be used to logically organize the various abstractions that are associated with a module, there is also the consideration of minimizing the size of a JavaScript file. The trade-off essentially amounts to minimizing file size so that you don't download superfluous code that isn't needed, while also not downloading too many small files—all of which are synchronous requests and incur the overhead of communicating back to the web server (although using the build tools to create layers can make this overhead somewhat of a moot point).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Bootstrapping
This section discusses some material that you may want to initially skim over and come back to review once you feel well acquainted with Dojo.
Before you can use Dojo at all, you have to somehow get it into the page. Regardless of whether you install Dojo locally or load it via AOL's CDN, you simply provide a SCRIPT tag that points to the file that loads some JavaScript code, and then magic elves inside of your web browser miraculously causes everything to "just work," right? Well, not quite. Like most other things in computing, it all comes back to pure and simple automation, and Dojo's bootstrap process is not different.
The term "bootstrap" refers to the idea of "pulling yourself up by your own bootstraps." In other words, it's the idea of getting up and running without help from anywhere else. The notional idea of Dojo bootstrapping itself is the same concept as your computer "booting up" when you turn it on.
For the record, is the absolute minimum effort that is generally required to get some XDomain Dojo goodness into your HTML page. What's especially notable about loading Dojo from the CDN is that less than 30KB of data comes across the wire. Chances are good that you'll use the previous code block, or some variation of it, quite often. Save yourself some typing by copying it into a template that you can reuse.
Example . A minimalist application harness example
<html>
  <head>
    <title>Title Goes Here</title>
    <!-- A lightweight style sheet that smoothes out look and feel across browsers -->
   <link rel="stylesheet"  type="text/css"
       href="http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css" />

    <script
      type="text/javascript"
      src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js">
    </script>

    <script type="text/javascript">
        /* If needed, Dojo modules may be asynchronously requested into the page
here via dojo.require statements... */

        dojo.addOnLoad(function(  ) {

            /* Any content that depends upon dojo.require statements goes here... */

        });
    </script>

  </head>
  <body>
    <!-- ... -->
  </body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Exploring Dojo with Firebug
Although the rest of this book systematically works through the entire toolkit, let's take a moment to tinker around with Dojo from the Firebug console. During development, there may be times when it is helpful to try out a few ideas in isolation, and the Firebug console provides an environment that behaves much like an interpreter.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
This chapter barely scratched the surface of your journey with Dojo, but it nonetheless covered a lot of ground. After reading this chapter, you should:
  • Know where to go to download the toolkit and set up a development environment
  • Understand the toolkit's architecture and the key differences between each component
  • Understand some of the common parlance used in Dojo development
  • Realize some of the benefits of using Firebug during the development cycle
  • Understand the basic ideas behind how the toolkit bootstraps itself
  • Have an appreciation for how easy it is to use Base and plug out-of-the-box dijits into a page
  • Be familiar with the look and feel of Dojo code
  • Be excited to read the subsequent chapters and learn more about Dojo
The next chapter will discuss language and browser utilities.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Language and Browser Utilities
This chapter formally introduces the language utilities that you'll find in Base. The language utilities are designed to streamline some of the most commonly worked-around problems in JavaScript programming, and they're designed to be ultra-portable and highly optimized. Regardless of whether you use anything else in the entire toolkit, the constructs presented in this chapter are worth a hard look because they provide augmentation that is difficult to imagine living without once you've gotten used to using them. Manipulating arrays, cloning nodes, adding and removing classes, and calculating margin and content boxes for DOM nodes are among the topics included in this chapter.
The previous chapter introduced dojo.byId, a toolkit-specific mechanism for looking up DOM nodes in a manner that is more portable and predictable than document.getElementById. Although dojo.byId absolutely pervades Dojo development, there is little value in repeating the previous discussion from ; refer back to the previous chapter for a detailed outline involving some of the issues with document.getElementById and how dojo.byId alleviates them. As a reminder, though, here's the full API call for dojo.byId :
dojo.byId(/*String*/ id | /*DomNode*/ node, /*DomNode*/doc)  // Returns a DOM Node
lists some other common use patterns.
Example . Quick reminder about dojo.byId
var foo = dojo.byId("foo"); //returns the node with id=foo if one exists
dojo.byId(foo).innerHTML="bar"; //the lookup is a no-op since foo is
                         //a node; then sets innerHTML to "bar"
var bar = dojo.byId("bar", baz); //returns the node with id=bar in document
                         //referenced by baz if one exists
In a language with dynamic typing like JavaScript, it's often necessary (and a very good idea) to test the type of variable before performing any operations on it. Although it might not seem like much to test for the type of a variable, it isn't always a freebie, and in practice can simply result in annoyances and bugs because of subtle differences. Base provides a few handy functions to simplify the nuances entailed. Like the other issues we've touched on so far, there are subtleties amongst various browsers involving some of the finer points. The following list summarizes:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Looking Up DOM Nodes
The previous chapter introduced dojo.byId, a toolkit-specific mechanism for looking up DOM nodes in a manner that is more portable and predictable than document.getElementById. Although dojo.byId absolutely pervades Dojo development, there is little value in repeating the previous discussion from ; refer back to the previous chapter for a detailed outline involving some of the issues with document.getElementById and how dojo.byId alleviates them. As a reminder, though, here's the full API call for dojo.byId :
dojo.byId(/*String*/ id | /*DomNode*/ node, /*DomNode*/doc)  // Returns a DOM Node
lists some other common use patterns.
Example . Quick reminder about dojo.byId
var foo = dojo.byId("foo"); //returns the node with id=foo if one exists
dojo.byId(foo).innerHTML="bar"; //the lookup is a no-op since foo is
                         //a node; then sets innerHTML to "bar"
var bar = dojo.byId("bar", baz); //returns the node with id=bar in document
                         //referenced by baz if one exists
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Type Checking
In a language with dynamic typing like JavaScript, it's often necessary (and a very good idea) to test the type of variable before performing any operations on it. Although it might not seem like much to test for the type of a variable, it isn't always a freebie, and in practice can simply result in annoyances and bugs because of subtle differences. Base provides a few handy functions to simplify the nuances entailed. Like the other issues we've touched on so far, there are subtleties amongst various browsers involving some of the finer points. The following list summarizes:
isString(/*Any*/ value)
Returns true if value is a String.
isArray(/*Any*/ value)
Returns true if value is an Array.
isFunction(/*Any*/ value)
Returns true if value is a Function.
isObject(/*Any*/ value)
Returns true if value is an Object (including an Array and Function ) or null.
isArrayLike(/*Any*/ value)
Returns true if value is an Array but also allows for more permissive possibilities. For example, the built-in arguments value that can be accessed from within a Function object is especially an oddball in that it does not support built-in methods such as push ; however, it is array-like in that it is a list of values that can be indexed.
isAlien(/*Any*/ value)
Returns true if value is a built-in function or native function such as an ActiveX component but does not respect the normal checks such as the instanceof Function.
A concept commonly involved in dynamic programming languages like Python and JavaScript called duck typing provides a common thread for many of the functions just introduced. Duck typing is based upon the saying that if it walks like a duck and quacks like a duck, then it's a duck. Basically, what that means is that if a particular data member exhibits the minimal necessary properties to be a particular data type, then that's good enough to assume that it is that particular data type.
For example, the built-in arguments member qualifying as an array via the isArrayLike function hopefully ties this theme together. When you consider the inherent dynamism in a language that does not require you to declare a particular variable to always be a particular data type (dynamic binding), duck typing is a great vehicle to inspect the type of an object when necessary.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
String Utilities
Trimming any existing whitespace from a string is an increasingly common operation. The next time you need to do this, use Base's trim function instead of writing your own.
There can be subtle performance issues with even the seemingly most trivial utility functions, and using the toolkit provides you with the benefits and collective knowledge of a community that has given careful consideration to such issues.
Here's an example of trim at work:
var s = "  this is a value with whitespace padding each side    ";
s = dojo.trim(s); //"this is a value with whitespace padding each side"
Core's string module also includes a few other useful string functions. Each of these examples assumes that you have already fetched the dojo.string module via a dojo.require statement.
dojo.string.pad
Pads a string value and guarantees that it will exactly fill a particular number of characters. By default, padding fills in on the left. An optional parameter causes padding to fill in from the right:
dojo.string.pad("", 5); // "00000"
dojo.string.pad("", 5, " "); // "     "
dojo.string.pad("0", 5, "1"); // "11110"
dojo.string.pad("0", 5, "1", true); // "01111"
dojo.string.substitute
Provides parameterized substitution on a string, optionally allowing a transform function and/or another object to supply context:
//Returns "Jack and Jill went up a hill."
dojo.string.substitute("${0} and ${1} went up a hill.", ["Jack", "Jill"]);

//"*Jack* and *Jill* went up a hill."
dojo.string.substitute("${person1} and ${person2} went up a hill.", {person1
: "Jack", person2: "Jill"});
dojo.string.substitute("${0} and ${1} went up a hill.", ["Jack", "Jill"],
function(x) {
  return "*"+x+"*";
});
dojo.string.trim
At the cost of a little more size than Base's implementation, Core's string module provides a slightly more efficient version of trim that can be used when performance really matters:
dojo.string.trim( /* your string value */);
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Array Processing
Arrays are one of the most fundamental data structures in any imperative programming language, including JavaScript. Unfortunately, however, standardized array operations are not supported by all mainstream browsers, and as long as that is the case, it's immensely helpful to have a toolkit that protects you from the bare metal. For that matter, even if the next version of each major browser supported arrays in a completely uniform manner, there would still be way too many people out there using older browsers to begin thinking about going back to the bare metal anytime soon.
You may find it interesting that the various language tools have been optimized for performance, providing wrapped usage of the native Array implementations wherever possible, but emulating functionality for browsers like IE when it is missing.
Fortunately, Dojo strives to keep up with Mozilla's feature rich implementation of the Array object (http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference). As long as you have the toolkit with you, you'll never be caught defenseless again. And in case you have already forgotten from our discussion of dojo.byId in that you really can't take much for granted in the current browser ecosystem, the next section should reinvigorate your enthusiasm and might even surprise you.
Two very routine array operations involve finding the index of an element, which is really one and the same as determining if an element exists at all. Base facilitates this process with two self-explanatory operations, dojo.indexOf and dojo.lastIndexOf. Each of these functions returns an integer that provides the index of the element if it exists; the value -1 is returned if the element was not found at all. These function signatures also include an additional parameter that indicates the value that should be used as an initial location in case you don't want to start from the very beginning or end of the array. The signature is the same for each function:
dojo.indexOf(/*Array*/ array, /*Any*/ value, /*Integer?*/ fromIndex)
//returns Integer

dojo.lastIndexOf(/*Array*/ array, /*Any*/ value, /*Integer?*/ fromIndex)
//returns Integer
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Managing Source Code with Modules
If you've programmed for any amount of time, you've been exposed to the concept of grouping related pieces of code into related blocks, whether they be called libraries, packages, or modules, and pulling in these resources when you need them via a mechanism like an import statement or a #include preprocessor directive. Dojo's official means of accomplishing the same kind of concept is via dojo.provide and dojo.require, respectively.
In Dojo parlance, reusable chunks of code are called resources and collections of related resources are grouped into what are known as modules. Base provides two incredibly simple constructs for importing modules and resources: dojo.require and dojo.provide. In short, you include a dojo.provide statement as the first line of a file that you want to make available for a dojo.require statement to pull into a page. As it turns out, dojo.require is a lot more than just a placeholder like a SCRIPT tag; it takes care of mapping a module to a particular location on disk, fetching the code, and caching modules and resources that have previously been dojo.require d. Given that each dojo.require statement incurs at least one round trip call to the server if the resource is not already loaded, the caching can turn out to be a tremendous optimization; even the caching that you gain from requiring a resource one time and ensuring it is available locally from that point forward is a great optimization.
For anything but the smallest of projects, the benefits of using this approach are irrefutable. The ease of maintenance and simplicity gained in extending or embedding code in multiple places is a key enabler to getting work done quickly and effectively. As obvious as it may sound, importing code in the manner just described hasn't always been obvious to web developers, and many web projects have turned into difficult-to-maintain monstrosities because of improper source code management in the implementation. For example, a typical workflow has been to take a JavaScript file that's in a static directory of a web server and to insert it into the page using a
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
JavaScript Object Utilities
Three of Base's language utilities facilitate operations you may need to routinely perform on objects: mixin, extend, and clone.
Dojo uses mixin and extend in its dojo.declare implementation, which is the toolkit's mechanism for simulating class-based inheritance. dojo.declare is covered extensively in .
JavaScript allows you to approximate lightweight classes by housing a collection of properties and methods inside a constructor function. You may then create object instances of these classes by invoking the constructor function with the new operator. As you might expect, it can sometimes be quite convenient to add additional properties to an object, whether it be to make something dynamic happen on-the-fly or as part of a well crafted design that maximizes code reuse. Either way, mixin provides a compact way of handling the implementation details for you.
In terms of object-oriented design with JavaScript, you'll see mixin used extensively throughout the toolkit to reuse blocks of code.
The API for using the toolkit's mixin functions entails providing an indeterminate number of objects, where the first objects gets the other objects mixed into it:
dojo.mixin(/*Object*/ o, /*Object*/ o, ...) //Returns Object
Here's an example of mixin:
function Man(  ) {
  this.x = 10;
}

function Myth(  ) {
  this.y = 20;
}

function Legend(  ) {
  this.z = 30;
}

var theMan = new Man;
var theMyth = new Myth;
var theLegend = new Legend;

function ManMythLegend(  ) {}
var theManTheMythTheLegend = new ManMythLegend;

//mutate theManTheMythTheLegend by mixing in the three objects
dojo.mixin(theManTheMythTheLegend, theMan, theMyth, theLegend);
Note that all parameters to mixin are actual object instances—not function declarations.
Base's extend function works just like mixin except that it adds all properties and methods of the mixins to a constructor function's prototype so that all future instances created with the constructor will automatically include these new properties and methods:
dojo.extend(/*Function*/constructor, /*Object*/props, ... ) //Returns Function
Here's an example:
function Man(  ) {
  this.x = 10;
}

function Myth(  ) {
  this.y = 20;
}

function Legend(  ) {
  this.z = 30;
}

var theMan = new Man;
var theMyth = new Myth;
var theLegend = new Legend;

function ManMythLegend(  ) {}

var theManTheMythTheLegend = new ManMythLegend;

Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Manipulating Object Context
Although the global window object provides the outermost layer of context for a web application, there may be times when you need to swap out the default context for another one. For example, you may want to persist the exact state of a session when the user exits an application, or you might have a custom execution environment that's already been preconfigured for a particular circumstance. Instead of having code that manually iterates over sets of conditions to configure the environment each time, you might opt to use Base's window facilities to swap out the existing context for another one.
The following function allows you to change out the dojo.global object and dojo.doc at will. Note that while dojo.doc is simply a reference to the window.document by default, it does provide a uniform mechanism for identifying the context's current document, which again can be quite useful for situations in which managed object contexts are involved. dojo.body() is a shortcut for obtaining the body of a document.
The body element is not explicitly defined for a strict XHTML document and some other documents you may encounter.
At a minimum, you should be aware of the following three functions from Base for manipulating context:
dojo.doc //Returns Document
dojo.body(  ) //Returns DomNode
dojo.setContext(/*Object*/globalObject, /*Document*/globalDocument)
Finally, in the spirit of flexibility, Base also provides two functions that allow you to evaluate a function in the context of either a different dojo.global environment or a different dojo.doc than the one that currently exists:
dojo.withGlobal(/*Object*/globalObject, /*Function*/callback, /*Object*/thisObject,
/*Array*/callbackArgs)
dojo.withDoc(/*Object*/documentObject, /*Function*/callback, /*Object*/thisObject,
/*Array*/callbackArgs)
It should be noted that using a Dojo function to operate extensively in another document or window is not a well-tested usage of the toolkit, so you may encounter support issues if going down that route. Standard usage normally entails loading Dojo into every document where you plan to use it. For lightweight operations, however, the context functions discussed in this section should work fine.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
DOM Utilities
Recall that Dojo intentionally does not attempt to replace core JavaScript functionality; on the contrary, it only augments it where value can be added so that you can write portable code and incur less boilerplate. For this reason, you won't see direct replacements for common DOM operations such as appendChild, removeChild, and so on. Still, there are many utilities that could make DOM manipulation a lot simpler, and this section is all about how Base helps to make that happen.
Base packs several useful functions that augment and supplement common DOM functions. The first of these functions, isDescendant, shown in , is self-descriptive. You provide it two arguments (id values or actual nodes), where the first argument is the node of interest and the second argument is a potential ancestor. If the node of interest is in fact a member of the potential ancestor's DOM tree, the function returns true.
Table : Base function for manipulating and handling the DOM
Name
Return type
Comment
dojo.isDescendant(/*String | DomNode*/node, /* String | DomNode*/potentialAncestor)
Boolean
Returns a Boolean value indicating if a node has a particular ancestor or not and works in nested hierarchies as would be expected.
The need to make a text on the page unselectable via the cursor is not uncommon and sometimes can actually enhance usability. Virtually every browser has a specific way of accomplishing this task, but no need to worry—you have Dojo. Whenever the need arises, just use the dojo.setSelectable function. Here's the self-descriptive API:
dojo.setSelectable(/*String | DomNode*/node, /*Boolean*/selectable)
Hopefully, it goes without saying that no client-side operation should ever be relied on to protect sensitive content because if something is being viewed in the browser as a native display, it can and will be reverse-engineered.
Base's dojo.style function provides a comprehensive means of getting or setting individual style values for a particular node. Simply provide the node and a style value in DOM-accessor format (e.g., borderWidth
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Browser Utilities
This section provides an overview of the toolkit's utilities for managing cookies and the browser's Back button—two topics that are quite common in any modern web application. Because both of these topics are provided by Core, you must dojo.require them into the page before trying to use them.
Because HTTP is a stateless protocol, as soon as a web server finishes serving up a page, it knows nothing else about you. While this aspect of the Web is magnificent in many respects, it is less than ideal for situations in which an application could personalize a page based upon preferences you've already defined. For example, it might be nice for a weather-related site to remember your zip code so that you don't have to enter it every single time you visit the page.
Cookies are a concept originally devised by Netscape that mitigate this kind of problem and give browsers a limited form of short-term memory. In short, web page designers can use JavaScript or server-side scripts to create a cookie that contains name-value pairs about your visit to the page. When you visit the page again, scripts can be used to fetch the cookie and dynamically affect your experience. Cookies generally have an expiration date and are always associated with the specific domain from which they originated.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
After reading this chapter, you should:
  • Understand Base's general feature set
  • Be able to configure djConfig to register module paths and be aware of the various other options you can pass into this structure to configure the bootstrap process
  • Understand how to use dojo.addOnLoad and dojo.addOnUnload functions and be aware of how dojo.addOnLoad can protect you from creating race conditions in your code
  • Be able to construct and namespace your own modules with dojo.provide and dojo.require
  • Understand how (and when) to use the map, filter, and forEach functions
  • Know the difference between and be able to effectively use mixin and extend
  • Effectively use Dojo's utilities for manipulating style with hasClass, removeClass, addClass, and toggleClass
  • Understand the basics of the CSS box model and be able to use functions like coords and marginBox to manipulate the placement of DOM nodes
  • Be aware of Base's Array processing utilities
  • Be able to wire up arbitrary connections of Object and DOM events
  • Be able to manage cookies
  • Be able to use Core's facilities for managing the back button for a single page app
Next, we'll take a look at event listeners and pub/sub communication.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Event Listeners and Pub/Sub Communication
Base provides extremely useful and versatile utilities for communication between JavaScript objects, DOM nodes, and any combination thereof. This chapter introduces these constructs as well as guidelines for when each of them might be most appropriate to employ. As writing portable code that involves DOM events necessarily depends on a standardized event model, you'll also learn a little bit about how Dojo works behind the scenes to smooth out some of the inconsistencies amongst mouse and keyboard events. The chapter concludes with a discussion of publish/subscribe communication, which provides a great vehicle for realizing an architecture with loosely coupled components.
Some of the oldest code in the toolkit was written to smooth out inconsistencies with the underlying event model amongst different browsers. This section provides a brief overview of the events that you can count on being normalized when you use Dojo to develop an application. The basis of standardization is the W3C model.
The dojo.connect machinery that you'll read about in the following section often involves a mouse event on a particular DOM node. Whenever you use Dojo, you can rest assured that the following mouse and keyboard events are supported in accordance with the W3C standard:
onclick
onmousedown
onmouseup
onmouseover
onmouseout
onmousemove
onkeydown
onkeyup
onkeypress
In addition to supporting the standardized W3C events, the nonstandard onmouseenter and onmouseleave events are also supported.
In addition to being able to count on these events firing in a standardized way, you can also rely on the event objects that are passed to event handling functions to also be normalized. In fact, if you ever have a need to normalize events yourself, you can use the following Base function:
dojo.fixEvent(/*DOMEvent*/ evt, /*DOMNode*/ sender) //Returns DOMEvent
DOMEvent is the standard convention that'll be used in the rest of the book to refer to the DOM event objects.
In other words, pass in the event and the node that should be treated as the current target, and you'll get back a normalized event that you can count on meeting the W3C specification. provides a synopsis of some of the most commonly used properties on a
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Event and Keyboard Normalization
Some of the oldest code in the toolkit was written to smooth out inconsistencies with the underlying event model amongst different browsers. This section provides a brief overview of the events that you can count on being normalized when you use Dojo to develop an application. The basis of standardization is the W3C model.
The dojo.connect machinery that you'll read about in the following section often involves a mouse event on a particular DOM node. Whenever you use Dojo, you can rest assured that the following mouse and keyboard events are supported in accordance with the W3C standard:
onclick
onmousedown
onmouseup
onmouseover
onmouseout
onmousemove
onkeydown
onkeyup
onkeypress
In addition to supporting the standardized W3C events, the nonstandard onmouseenter and onmouseleave events are also supported.
In addition to being able to count on these events firing in a standardized way, you can also rely on the event objects that are passed to event handling functions to also be normalized. In fact, if you ever have a need to normalize events yourself, you can use the following Base function:
dojo.fixEvent(/*DOMEvent*/ evt, /*DOMNode*/ sender) //Returns DOMEvent
DOMEvent is the standard convention that'll be used in the rest of the book to refer to the DOM event objects.
In other words, pass in the event and the node that should be treated as the current target, and you'll get back a normalized event that you can count on meeting the W3C specification. provides a synopsis of some of the most commonly used properties on a DOMEvent.
Table : Commonly used properties on DOMEvents
Name
Type
Comment
bubbles
Boolean
Indicates whether the event can bubble up the DOM tree.
cancelable
Boolean
Indicates whether the event can have its default action prevented.
currentTarget
DOMNode
The current node whose event listeners are being processed. (Useful for when an event bubbles.)
target
DOMNode
The node that originally received the event.
type
String
The type of the event, e.g., mouseover.
ctrlKey
Boolean
Indicates if the Ctrl key was depressed when the event fired.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Event Listeners
Direct communication channels are constructed by explicitly chaining together functions and/or DOM events so that when one executes, another is automatically invoked afterward. For example, each time an object changes via a "setter" method, you may want to automatically trigger a change in the application's visual interface. Or, perhaps each time one object changes, you might want to automatically update a derived property on another object. The possibilities are endless.
The two primary methods involved in a direct communication scheme are dojo.connect and dojo.disconnect. In short, you use dojo.connect to chain together a series of events. Each call to dojo.connect returns a handle that you should keep and explicitly pass to dojo.disconnect whenever you are ready to dispose of the connection. Conveniently, all handles are disconnected automatically when the page unloads, but manual management of the handles may be necessary for preventing memory leaks in long-running applications that invoke a lot of connections that are used temporarily. (This is particularly the case on IE.) Coming up is the API that was introduced in .
Don't ever connect anything until after the page is loaded. Trying to use dojo.connect before the page is loaded is a very common mistake and can cause you to sink a lot of time into trying to debug something that isn't very easy to track down the first time you run into it. You should always set up your connections within the function that you pass into dojo.addOnLoad to stay safe.
Setting up and tearing down connections is easy. Here's the basic API:
/* Set up a connection */
dojo.connect(/*Object|null*/ obj,
            /*String*/ event,
            /*Object|null*/ context,
            /*String|Function*/ method) // Returns a Handle

/* Tear down a connection */
dojo.disconnect(/*Handle*/handle);
For all practical purposes, you should treat the handle that is returned from a call to dojo.connect as an opaque object that you don't do anything with except pass to disconnect at a later time. (In case you're wondering, it is nothing special—just a collection of information that is used to manage the connection internally.)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Publish/Subscribe Communication
While there are plenty of times when the direct "chained" style of communication provided by dojo.connect is exactly what you'll need to solve a problem, there are also a lot of times when you'll want a much more indirect "broadcast" style of communication in which various widgets communicate anonymously. For these circumstances, you might instead use dojo.publish and dojo.subscribe.
A classic example is a JavaScript object that needs to communicate with other objects in a one-to-many type relationship. Instead of setting up and managing multiple dojo.connect connections for what seems like one cohesive action, it's considerably simpler to have one widget publish a notification that an event has transpired (optionally passing along data with it) and other widgets can subscribe to this notification and automatically take action accordingly. The beauty of the approach is that the object performing the broadcast doesn't need to know anything whatsoever about the other objects—or even if they exist, for that matter. Another classic example for this kind of communication involves portlets—pluggable interface components (http://en.wikipedia.org/wiki/Portlet) that are managed within a web portal, kind of like a dashboard.
The OpenAjax Hub (http://www.openajax.org/OpenAjax%20Hub.html), which you'll read more about in , calls for publish/subscribe communication to be used as the vehicle for effectively employing multiple JavaScript libraries in the same page.
In many situations, you can achieve exactly the same functionality with pub/sub style communication as you could by establishing connections, so the decision to use pub/sub may often boil down to pragmatism, the specific problem being solved, and overall convenience of one approach over another.
As a starting point for determining which style of communication to use, consider the following issues:
  • Do you want to (and can you reliably) expose an API for a widget you're developing? If not, you should strongly prefer pub/sub communication so that you can transparently change the underlying design without constantly wrangling the API.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
After reading this chapter, you should:
  • Be aware that dojo.connect standardizes the event Object that is passed into event-handling functions, providing portability across platforms
  • Understand how dojo.connect allows you to arbitrarily chain DOM events, JavaScript Object events, and ordinary functions together to create an event-driven response
  • Use publish/subscribe to facilitate connections and achieve a loosely coupled communications backbone in an application
  • Be aware of some of the considerations and trade-offs for using dojo.connect versus pub/sub in an application architecture
Next up is AJAX and server communication.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: AJAX and Server Communication
The common thread of this chapter is server-side communications. Performing asynchronous requests, using the IFRAME transport to submit forms behind the scenes, serializing to and from JavaScript Object Notation (JSON), and using JSONP (JSON with Padding) are a few of the topics that are introduced in this chapter. You'll also learn about Deferred, a class that forms the lynchpin in the toolkit's IO subsystem by providing a uniform interface for handling asynchronous activity.
AJAX (Asynchronous JavaScript and XML) has stirred up considerable buzz and revitalized web design in a refreshing way. Whereas web pages once had to be completely reloaded via a synchronous request to the server to perform a significant update, JavaScript's XMLHttpRequest object allows them to now behave much like traditional desktop app