Archive for the ‘dojo’ Category.

Widgets within Widgets

At the day-job we do a lot of Widget work. We have Container widgets that hold Panel widgets, which hold Box widgets, which hold other widgets. The widgets themselves create other widgets and place them in their own ownership. Our full-page/no-refresh/Ajax-app with the long lived page views creates and destroys all these widgets based on the various events published around the page, but we ran into a problem along the way: a lot of the widgets weren't being destroyed. Ever.

The whole system is quite sound, though lacked in this one regard. To be fair, Dijit cleans up after itself. Everything that is created when a Dijit widget instance is new'd up is removed when that instance is destroyed. Everything that is created declaratively in a template is cleaned up automatically for you when a widget is destroyed. The problem only exists when one widget creates another widget programatically, either for permanent placement or temporary use. Let me illustrate with a basic Widget example:

 
// file is my/Thinger.js
dojo.provide("my.Thinger");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.declare("my.Thinger", [dijit._Widget, dijit._Templated], {
 
    // the listItem in the template is "tracked" and cleaned
    widgetsInTemplate:true,
    templateString:"
<div>
<ul><" + "li dojoType='my.ListItem' dojoAttachPoint="li">${foo}</" + "li></ul>
</div>
 
",
 
    postCreate: function(){
        // some self-cleaning event connections. These are disconnected upon destruction.
        this.connect(this.domNode, "onclick", "_clicker");
        // this item is leaked when Thinger is destroyed.
        new my.ListItem().placeAt(this.li, "after");
 
    }
 
});
 

Here, we're creating new my.ListItem instances and adding them to our own DOM, but not keeping track of them in any way. This is an exceptionally common pattern of code compartmentalization. The my.Thinger scopes all DOM references and event connections to itself. It contains other widgets which handle some part of the overall functionality. By making a whole ListItem Class, we compartmentalize that bit of logic into little pieces.

We can see the leak pretty easily:

 
console.log(dijit.registry.length); // 0
var x = new my.Thinger().placeAt(dojo.body());
console.log(dijit.registry.length); // 3, A Thinger, and Two ListItem instances
x.destroy();
console.log(dijit.registry.length); // 1. A ListItem
 

So I'll show my solution to this little dilemma in hopes you can adopt a similar method to suite your own needs. My solution requires imposing a style guideline on how new widgets are bound and added to other widgets, but I feel it to be well worth the extra efforts.

The first thing we do, because all Dijit widgets clean up properly after themselves already, is make our own Base Widget class, extending dijit._Widget. Here we'll add a few functions to add new APIs to the lifecycle so we can track our own widgets.

 
dojo.provide("my.Widget");
dojo.require("dijit._Widget");
dojo.delcare("my.Widget", [ dijit._Widget, dijit._Templated ], {
    // summary: Our custom dijit._Widget base class. All our widgets should inherit from this. 
 
    adopt: function(cls, props, srcNode){
        // summary: Take ownership of a new widget
        // returns: The added widget
    },
 
    orphan: function(widget, destroy){
        // summary: relinquish ownership of an owned widget. optionally destroy.
        // returns: nothing.
    },
 
    destroy: function(preserveDom){
        // summary: an overridden destroy method. call the parent method, but we'll add stuff here too.
        this.inherited(arguments);
    },
 
    _kill: function(widget){
        // summary: destroy properly this widget instance
        // returns: nothing.
    },
 
    _addItem: function(/* Widget... */){
        // summary: Add any number of widgets to this instance
        // returns: nothing.
    }
 
});
 

So we've stubbed out the API with two new public functions, a single overridden destroy method, and two private helper functions. _addItem will do most of the work, so we'll show it first:

 
    _addItem: function(/* Widget... */){
        this._addedItems = this._addedItems || [];
        this._addedItems.push.apply(this._addedItems, arguments);
    },
 

The code will create or reuse an instance member (array) called _addedItems. This contains the list of widgets we've created programatically. It accepts any number of arguments, so you can add multiple items in the same line of code.

 
    this._addItem(
        new dijit.form.Button().placeAt(this.fooNode),
        new dijit.form.Button().placeAt(this.barNode)
    );
 

When the widget calling addItem is destroyed, the two anonymously created Button instances will go with it. Well, not quite yet, but we only have to add a line to our destroy method to handle that action. We'll also add the code for the _kill function, which we'll reuse in orphan in a moment. _kill is a simple function which will destroy a single widget instance properly. In destroy we call _kill by passing it to the forEach call:

 
    destroy: function(){
        dojo.forEach(this._addedItems, this._kill);
        this.inherited(arguments);
    },
    _kill: function(widget){
        if(widget.destroyRecursive){
            widget.destroyRecursive();
        }else if(widget.destroy){
            widget.destroy();
        }
    }
 

So we now have a way to add tracked widgets to ourself and to destroy them cleanly when we go away. Admittedly, I don't like the API for _addItem ... Not only is it _private, I still have a lot of boilerplate stuff repeated, now being wrapped with _addItem(). This is where the adopt API. It takes the repetition down one notch, and wraps the creation and adding into a single function call:

 
    adopt: function(cls, props, srcNode){
        var x = new cls(pros, srcNode);
        this._addItem(x);
        return x;
    }
 

All Dijit _Widget derivatives accept two constructor arguments: an object hash of properties, and an optional source-node reference (from which to create the instance). We simply relay those two arguments into a single 'new' call, add the item to ourselves, and returning the widget instance otherwise unmodified. To use it is simple:

 
    postCreate: function(){
        this.adopt(my.ListItem).placeAt(this.li, "before");
    }
 

The ListItem in this example doesn't need any constructor args, so they are omitted. The return from adopt is the widget instance, so you can chain placeAt calls on it, or save the return value to reuse in other scoped functions. Here's a small example of everything working "together":

 
    postCreate: function(){
        this.dialog = this.adopt(my.Dialog, { onClick: dojo.hitch(this, "_click" )});
        setTimeout(dojo.hitch(this.dialog, "open"), 2000);
        this.connect(this.destroyButton, "onclick", "_close");
    },
    _click: function(e){
        e && e.preventDefault();
        this.close();
    },
    _close: function(){
        this.dialog && this.dialog.close();
    }
 

The last function is wildy useful, but not as mind-blowing as having tracked programmatic instances. In the above example we tracked an instance of my.Dialog locally as this.dialog. We're checking the presence of this.dialog before calling close() on it. Sometimes we only need a widget for a short while ... where we want to destroy it upon closing, or destroy a single reused variable holding a widget. That is what orphan is for:

 
    orphan: function(widget, destroy){
        this._addedItems = this._addedItems || [];
        var i = dojo.indexOf(this._addedItems, widget);
        if(i >= 0) this._addedItems.splice(i, 1);
        destroy && this._kill(widget);
    }
 

The code loaded the local list of added children, searches for a passed reference, and removes it from the tracking list. Optionally, you can destroy the widget while being orphaned by passing any truthy value in the second argument. Now, the code pattern which looks like:

 
    _click: function(){
        this.dialog && this.dialog.destroy();
        this.dialog = new my.Dialog();
    }
 

can be reduced to:

 
    _click: function(){
        this.dialog && this.orphan(this.dialog, true);
        this.dialog = this.adopt(my.Dialog);
    }
 

The latter example is slightly more verbose, but it has the benefit of not leaking any widgets. Memory costs more than keystrokes methinks.

The full, documented code is as follows. Feel free to use it in your own app: the migration is painless:

 
dojo.declare("my.Widget", [ dijit._Widget, dijit._Templated ],
{
    // summary:
    //    The Foundation widget for our things. Includes _Widget and _Templated with some custom addin methods.
 
    adopt: function(/* Function */cls, /* Object? */props, /* DomNode */node){
        // summary: Instantiate some new item from a passed Class, with props with an optional srcNode (node)
        //  reference. Also tracks this widget as if it were a child to be destroyed when this parent widget
        //  is removed.
        //
        // cls: Function
        //      The class to instantiate. Cannot be a string. Use dojo.getObject to get a full class object if you
        //      must.
        //
        // props: Object?
        //      An optional object mixed into the constructor of said cls.
        //
        // node: DomNode?
        //      An optional srcNodeRef to use with dijit._Widget. This thinger will be instantiated using
        //      this passed node as the target if passed. Otherwise a new node is created and you must placeAt() your
        //      instance somewhere in the dom for it to be useful.
        //
        // example:
        //  |    this.adopt(my.ui.Button, { onClick: function(){} }).placeAt(this.domNode);
        //
        // example:
        //  |   var x = this.adopt(my.ui.Button).placeAt(this.domNode);
        //  |   x.connect(this.domNode, "onclick", "fooBar");
        //
        //  example:
        //  If you *must* new up a thinger and only want to adopt it once, use _addItem instead:
        //  |   var t;
        //  |   if(4 > 5){ t = new my.ui.Button(); }else{ t = new my.ui.OtherButton() }
        //  |   this._addItem(t);
 
        var x = new cls(props, node);
        this._addItem(x);
        return x; // my.Widget
    },
 
    _addItem: function(/* dijit._Widget... */){
        // summary: Add any number of programatically created children to this instance for later cleanup.
        // private, use `adopt` directly.
        this._addedItems = this._addedItems || [];
        this._addedItems.push.apply(this._addedItems, arguments);
    },
 
    orphan: function(/* dijit._Widget */widget, /* Boolean? */destroy){
        // summary: remove a single item from this instance when we destroy it. It is the parent widget's job
        // to properly destroy an orphaned child.
        //
        // widget:
        //      A widget reference to remove from this parent.
        //
        // destroy:
        //      An optional boolean used to force immediate destruction of the child. Pass any truthy value here
        //      and the child will be orphaned and killed.
        //
        // example:
        //  Clear out all the children in an array, but do not destroy them.
        //  |   dojo.forEach(this._thumbs, this.orphan, this);
        //
        // example:
        //  Create and destroy a button cleanly:
        //  |   var x = this.adopt(my.ui.Button, {});
        //  |   this.orphan(x, true);
        //
        this._addedItems = this._addedItems || [];
        var i = dojo.indexOf(this._addedItems, widget);
        if(i >= 0) this._addedItems.splice(i, 1);
        destroy && this._kill(widget);
    },
 
    _kill: function(w){
        // summary: Private helper function to properly destroy a widget instance.
        if(w && w.destroyRecursive){
            w.destroyRecursive();
        }else if(w && w.destroy){
            w.destroy()
        }
    },
 
    destroy: function(){
        // summary: override the default destroy function to account for programatically added children.
        dojo.forEach(this._addedItems, this._kill)
        this.inherited(arguments);
    }
 
});
 

Does anyone have any alternate solutions they've found to combat this problem?

140 Characters of awesome

A few days ago I tweeted a line of code and decided it was wonderful enough to warrant further explanation. While the code itself may have fit into 140 characters, the examples and use cases go on and on. Because of a few architectural decisions made by Dojo long ago, these 140 characters are powerful and flexible as well as mindlessly simple to use.

One thing a dojo.NodeList does not have by default in Base (dojo.js) is a way to fetch and inject content into a node (or nodes). This isn't necessarily an oversight, there are several ways this can be accomplished. In fact it is so simple an operation with so many possible edge cases it may even not be worth implementing. Here I present to you my own take on this super simple concept, built by using standard Base (dojo.js) functionality.

The function will be called grab(). It will grab a url, and inject it into some nodes. Here is the first iteration of this idea:

 
dojo.extend(dojo.NodeList, {
	grab: function(url){
		dojo.xhr("GET", { url:url })
			.addCallback(this, function(response){
				this.addContent(response, "only");
			});
		return this;
	}
});
 

We're simply mixing a new function in dojo.NodeList.prototype via dojo.extend, giving all instances of a NodeList this method. The plugin calls "return this;" to allow further chaining. Ajax operations by default are asynchronous

We work with NodeLists via dojo.query, so to use this code now we simply query the dom and load some content via Ajax:

 
dojo.addOnLoad(function(){
	dojo.query("#header").grab("header.html");
});
 

That is all well and good and works brilliantly until you need to a) load non-html content b) issue an xhrPost instead of get or c) configure the xhr call in any way. No worries, with just a few more bytes we can add all of that functionality piggybacking on the behavior of dojo.Deferred and objects.

First, we'll add support for mixing in extra parameters into the object passed to the XHR call. Currently, we're only passing { url: url }, giving the Ajax call an endpoint to fetch. dojo.xhr accepts a lot of options in this magic object, so allowing a developer/user to mix in their own custom information here is as simple as calling dojo.mixin with an optional parameter. mixin() is safe like this, in that if extraArgs is undefined or null nothing happens. The url:url aspect is still retained, and any args passed as extraArgs are overwritten into the call.

 
dojo.extend(dojo.NodeList, {
	grab: function(url, extraArgs){
		dojo.xhr("GET", dojo.mixin({ url:url }, extraArgs))
			.addCallback(this, function(response){
				this.addContent(response, "only");
			});
		return this;
	}
});
 

This now allows us to mix extra items into the Ajax call like timeout, sync, error handlers and so on. Back to the nature of Ajax calls being asynchronous: if we issue a grab() call on some node, the next items in the chain will not apply to the new content until an undetermined point in the future. We can overcome this limitation by passing { sync:true } to the Ajax call, making the operation synchronous and thus making the following chains not execute until after the transfer is complete.

 
dojo.addOnLoad(function(){
	dojo.query("#content").grab("/article/12345", { sync: true })
		.find("p.title").onclick(function(e){ alert(this.innerHTML); });
});
 

If we had omitted the { sync:true } here, the find() call would be querying the dom of the node with id="content", though the content of /article/12345 url would not yet be in the container. We don't have to use synchronous Ajax here, it is just a possibility. For instance, we could have connected the click handler to the #content NodeList and delegated from the bubble, or used plugd's connectLive plugin to simple connect to "p.title" and delegated that way.

We can use the extraArgs in so many ways it's ridiculous. What if you wanted to know if the loading error'd out for some reason:

 
dojo.query("#content").grab("/foo.html", {
	error: function(e){
		console.warn("error fetching foo.html");
	}
});
 

Or, more importantly, what if you wanted to load content other than plain HTML. Perhaps you have a JSON object to load in. This is entirely possible because of the way dojo.Deferred works. When we call addCallback() on the Deferred chain in the plugin we're really registering the last chain. Anything we mix in to the Ajax call directly is executed before the final callback which calls this.addContent(). The secret is: the return value from a previous callback is passed to the next callback in the chain. So if we register a load: callback in the extraArgs we are permitted a pre-processing step for whatever content comes in. We simply need to supply an alternate handleAs to tell Ajax to process as JSON, and the load callback to process the JSON and return HTML so addContent works.

 
dojo.query("ul > li").grab("person.json", {
	handleAs:"json",
	load: function(data){
		// again, broken string for a broken wordpress highlight.
		return dojo.replace("<" + "p>{username} - {age} / {sex}</" + "p>", data);
	}
});
 

The [new in Dojo 1.4] function dojo.replace does simple template substitution. In the above example, data.username is substituted into {username}, and the full HTML is returned to the second callback for this Ajax call, then injected into the appropriate node(s). In version prior to Dojo 1.4 you can use dojo.string.replace to accomplish mostly the same goals (though the templating is done differently, ${username} would need to be substituted). Above will inject a paragraph into each of the matched list items with some data. If our data came back as an array, we could simply make up the list items as well.

 
dojo.query("ul#mainlist").grab("tweets.json", {
	handleAs:"json",
	load:function(data){
		var response = [];
		dojo.forEach(data, function(item){
			// string intentionally broken up because wordpress highlight breaks it.
			response.push(dojo.replace("<l" + "i><" + "p>{username} - {age}</" + "p></l" + "i>", data));
		});
		return response.join("");
	}
});
 

Here we're building up a string of list-items to be injected into the unordered list with id="mainlist". When the full response is joined and returned, that value is processed by addContent and injected appropriately.

The last little piece of the puzzle is to assume you don't want to issue and xhrGet call. There are several HTTP verbs to use, each with their own purpose: PUT, DELETE, or POST come to mind. With a simple adjustment to the grab function we can allow the developer to optionally overwrite this as well:

 
dojo.extend(dojo.NodeList, {
	grab: function(url, extraArgs, method){
		dojo.xhr(method || "GET", dojo.mixin({ url:url }, extraArgs))
			.addCallback(this, function(response){
				this.addContent(response, "only");
			});
		return this;
	}
});
 

Now, if we pass a method parameter the default value of "GET" is ignored. Otherwise the defaults take over. Again utilizing the extraArgs "mixin", we can make an Ajax POST request and send along custom data:

 
dojo.query("#login").grab("/user/login", {
	content:{
		name: dojo.byId("username").value,
		pass: dojo.byId("password").value
	}
}, "POST");
 

One implementation detail I don't like about grab is the forced emptying of the target node. In the addCallback function where we call addContent with a parameter of "only" we are forcefully emptying out the nodes before injecting the new content. Unfortunately, this is the only behavior we've permitted here. It would be trivial to omit to "only" (and less bytes, too) and require the developer to call empty() manually before injecting new content if that behavior was desired. By default then we'd be adding the content "last", which is the default addContent position. Let's rework the grab function to handle this:

 
dojo.extend(dojo.NodeList, {
	grab: function(url, extraArgs, method){
		dojo.xhr(method || "GET", dojo.mixin({ url:url }, extraArgs)).addCallback(this, "addContent");
		return this;
	}
});
 

It got even smaller! the "(scope, method)" pattern used in addCallback above is found throughout Dojo, and is super handy. That function "pair" (this.addContent) will be passed whatever value is returned from the Ajax call still, in the first position. The difference is we are not permitted to pass a position (without lamba's in JavaScript). Now, to inject some content into a node and empty it we must do that manually:

 
dojo.query("#foo").empty().grab("bar.html");
 

Without the empty(), "bar.html" content would be appended to the node rather than replace the content. I have yet to decide which behavior I like better. Opinions? I'll need to decide that before adding this functionality to Base Dojo proper. It currently lives in plugd, along with a slew of other new functionality for Dojo 1.4.

One last thing to do to grab function: there is no point in sending off the request if no nodes were found in the query. A simple check on the .length of the NodeList will prevent any unnecessary XHR calls from taking place:

 
dojo.extend(dojo.NodeList, {
	grab: function(url, extraArgs, method){
		this.length && dojo.xhr(method || "GET", dojo.mixin({ url:url }, extraArgs)).addCallback(this, "addContent");
		return this;
	}
});
 

And there you have it, 140 characters of awesome. (it may be a bit more with the longhand variables, pre-shrinkage. Also the inclusion of the extend call and so on add a few bytes, but in plugd's base.js these were already there for the other plugins provided, so is moot)

Degrading Script Tags, an aside.

A few months ago John Resig published a 'degrading script tag' post, which outlined a very simple pattern for better utilizing a script element. I liked it, it has always bothered me a simple construct like:

 
<script src="foo.js">
	foo(); // woohoo!
</script>
 

doesn't "just work". It makes perfect sense: load foo.js and execute some code when the script is ready. If the script fails or doesn't exist, don't execute the code. It is the perfect pattern for progressive javascript.

This makes perfect sense for Dojo as well: load dojo.js and execute the content therein if everything is OK. It would be great to support a syntax like:

 
<script src="dojo/dojo.js">
	dojo.require("dijit.layout.TabContainer");
	dojo.addOnLoad(function(){
		// make some tabs, and stuff.
	});
</script>
 

Not satisfied with John's scripts[scripts.length - 1] solution, and [at the time] lacking a better idea of my own, I dismissed the idea as novel. A few days ago it dawned on me: Dojo can do this already. I quickly threw together a hack. All we need is the script element.

Base Dojo is broken into several files (though works transparently between the "development" version and the "built" base, aka: dojo.js), and uses a sophisticated build system to make a custom deployment as simple as:

./build.sh profile=myStuff

My quick solution involves suggesting some incredibly simple changes into some deep bits of the Dojo loader. Some background: Dojo 1.x supports an optional "djConfig" parameter placed on the script element loading the library. eg:

 
<script src="dojo.js" djConfig="parseOnLoad:true"></script>
 

As a result of the lookup involved in having maintained this behavior for years, Dojo "knows" the element loading dojo.js (or dojo.xd.js), but only in a browser environment. We can add a single line to the hostenv_browser.js, saving a reference to our own script node:

 
// after we are in the regexp match looking for ourself:
d._scriptElem = scripts[i];
 

Then, we create a new base module to process the content if it exists:

 
dojo.provide("dojo._base._loader.self"); // tell package/build system about this module/plugin
(function(e){
 
	// execute this content [if] found in the script tag for dojo.js
	e && e.innerHTML.length && dojo["eval"](e.innerHTML);
	delete dojo._scriptElem; // cleanup?
 
})(dojo._scriptElem);
 

Hooking the two parts together is another one-liner: add a conditional require to the "base layer" file. As the last line to ensure it is the last piece of code executed by dojo.js:

 
dojo.requireIf(dojo.isBrowser, "dojo._base._loader.self");
 

If we are building for non-browser situations the code is ignored. We can go a step further and save a few bytes by excluding the whole module as an optional build parameter:

 
//>>excludeStart("noself", kwArgs.noSelf);
dojo.requireIf(dojo.isBrowser, "dojo._base._loader.self");
//>>excludeEnd("noself");
 

This way, if we build dojo.js with noSelf=true, the code never even becomes a consideration for base, and the innerHTML of our degrading script tag is simply ignored.

So my solution/hack here fixes a couple of the issues raised in John's blog comments, such as XHR loading of the script, delayed or deferred loading of the script, and most importantly the assumption the script would be the last in the page. I've thrown together some simple tests double checking delayed loading and basic success, and made up a small shell script which will fetch Dojo, apply the patch, and run a build (giving you a dojo.js with these behaviors, though the 'development' dojo.js works identically). I don't agree with the assumption John made about the code being executed within a $(document).ready function, as there is a lot of Dojo functionality that doesn't require the DOM to operate (eg: dojo.require) so I omitted that bit.

I'm torn on if this is worthwhile for Dojo or not, as we try to avoid any ubermagic that goes against what trained developers are expecting ... but I agree with John: the syntax is quite sexy and ridiculously clear as to what is and should be happening.

My initial pass at this was slightly more sloppy, but misguided. I had a nasty bit of code in self.js like:

 
var	how = "textContent" in e ? "textContent" :
		"text" in e ? "text" :
		"innerHTML" in e ? "innerHTML" :
		null;
 
e && e[how] && dojo["eval"](e[how]);
 

But that was just me being neurotic from my experience of injecting raw code into a newly created script element. Turn's out .innerHTML works across browsers for reading the current content.

Interestingly, Opera stores the src="" value in .text and the actual innerHTML in .textContent, whereas IE only has .text. I even made a log from my findings (before I noticed John was only using .innerHTML, at which point I stopped populating my mini ppk-inspired-compatibility table)

... so if the use of eval() bothers you, I've worked up a small bit of code to create a script and safely inject some JavaScript within (where I copy/pasted my sloppy self.js lookup code from):

 
(function(d){
 
	d.noteval = function(/* String */code){
		// summary: Execute some javascript.
 
		if(!code) return;
 
		var	e = d.create("script", { type:"text/javascript" }),
			// jump through the cross-browser hoops:
			how = "text" in e ? "text" :
				"textContent" in e ? "textContent" :
				"innerHTML" in e ? "innerHTML" :
				"appendChild"
		;
 
		if(how == "appendChild"){
			e[how](d.doc.createTextNode(code));
		}else{
			e[how] = code;
		}
 
		return d.doc.getElementsByTagName("head")[0].appendChild(e);
 
	};
 
})(dojo);
 

I've used this in a slightly more verbose version to support a very sloppy injection of JavaScript in XHR content via the dojoType attribute and utilizing the dojo.parser. It could probably be reduced. I should make a table.

More on Dojo “plugins”

Dojo doesn't call any of the hundreds of optional/add-on modules available on either CDN a "plugin", though they all ultimately behave as such. Dojo has had a custom package system for several years now: a way to modularize script files and create dependencies between them, loading them as you see fit and optionally compressing or concatenating them as part of the automated build system.

So for the sake of argument, we'll call the various Dojo modules available "plugins". On top of Base Dojo (dojo.js), there are a number of great plugins available "out of the box". This is how you load them:

 
// cookie setter-getter plugin
dojo.require("dojo.cookie");
 
// advanced string substitution stuff
dojo.require("dojo.string");
 
// the back-button management plugin
dojo.require("dojo.back");
 
// advanced Animation support. chain/combine, some prefab fx
dojo.require("dojo.fx");
 
// advanced number formatting functions
dojo.require("dojo.number");
 
// currency conversion, formatting, etc
dojo.require("dojo.currency");
 
// date formatting and utility functions
dojo.require("dojo.date");
 
// fast selector-based live api plugin
dojo.require("dojo.behavior");
 

Most are simply optional utility functions to help with the tasks you will face as a developer (especially if you are considering internationalization and accessibility issues). Load as needed, omit as desired. (There are a series of UI controls in Dijit, and hundreds more plugins in DojoX, again, all available on the CDNs, all just a require() away)

You could of course point <script> tags at each of the files, but should you change the location of anything you'll need to adjust each path to accomodate. By using the Dojo package system we're able to create a list of requirements to load, and only need to ensure the relative location to dojo.js is correct. dojo.js typically lives in a folder named 'dojo'. All dojo.* modules are floating around there as well. eg:

src/
	dojo/
		- dojo.js
		- behavior.js
		- number.js

As a design decision, Dojo uses clear namespaces to compartmentalize all plugins. This prevents any possible overlap and destruction of items fighting for the same name. If you've ever tried to include both Prototype and jQuery in a page you know what I'm talking about, as both "fight" for the right to use the global "$" function (jQuery for it's entire API and Prototype as a byId selector). jQuery bows out of that contest by providing a 'noConflict' function, allowing Prototype to keep $, and tells users to do something similar to:

 
(function($){
	// I can use $ again!
})(jQuery);
 

to regain control of the $ in a localized scope. This is similar to something I do in plugd, and other places throughout the Dojo plugin landscape (though I do it because typing 'd' is three characters less than typing 'dojo', not because of any interoperability issues):

 
(function(d, $){
	// I can use $, too!
})(dojo, dojo.query);
 

So the issue isn't that you can't "plugin" to Dojo, it is simply that as a best practice Dojo suggests you don't ... Doing so will likely cause headaches in the future. Though the API's in Base Dojo (dojo.js) are always backward compatible between releases, the addition of new APIs may conflict with whatever name you've chosen. I'm actually experiencing this myself a bit in plugd, where I chose to place all the plugins into the dojo namespace directly. For example, plugd's `create` function came first, and creates DOM markup from either a single element or complex markup. Dojo's `create` (as of 1.3) does not do this, `dojo.place` does.

In hindsight, I should have copied the dojo namespace into plugd and made my extensions all namespaced plugd. That way, using it in the dojo namespace would simply be:

 
(function(dojo){
	// that's an interesting circle, though JavaScript likely allows it.
	// not tested this approach any, so don't quote me.
})(plugd);
 

But the idea of stubbing functions onto dojo.query for the chaining and whatnot is entirely appealing, and entirely valid. dojo.query returns an instance of a dojo.NodeList, leaving the work of querying to a single module focused exclusively on querying, and treating the extensions externally. The typical way would be:

 
dojo.extend(dojo.NodeList, {
	setColor: function(color){
		// summary: set the color to "color", and return this NodeList
		return this.style("color", color);
	}
});
 

Though, as per my dojo.Patterns talk and brief blog on the topic, I would suggest making a single function to act upon a node (byId or node reference), and make that act upon the nodes in the list. This, simply put, is faster. There is no overhead of querying the DOM, instantiating a nodelist and so on, unless you know you need to. This pattern looks just like:

 
(function(d){
 
	d.setColor = function(n, color){
		// summary: A function to set a color for some node
		d.style(n, "color", color);
	}
 
	// make this function an iterable when used with dojo.query
	d.NodeList.prototype.setColor = d.NodeList._adaptAsForEach(d.setColor);
 
})(dojo);
 

Now we can use the setColor method either way: fast and on a single node, or marginally slower and across all nodes. Having the choice is nice:

 
	// way one: force a byId lookup from a string:
	dojo.setColor("someId", "blue");
 
	// way two: from a saved node reference eg:
	var node = dojo.byId("someNode").parentNode;
	dojo.setColor(node, "green");
 
	// way three: in bulk, allowing for further chaining:
	dojo.query(".someNodes").setColor("red");
 

The most 'complicated' bit about this pattern is having to set a function directly on NodeList.prototype ... To shelter you from dealing with prototype's directly, I've devised a fun plugd plugin, aptly named "dojo.plugin". It does two things:

  1. Creates dojo.fn as an alias to dojo.NodeList.prototype, so you can simply write a plugin like: dojo.fn.myPlugin = function(props){ ... }
  2. Defines a dojo.plugin function to create both a single function and NodeList variant with a single syntax

To use, simply require in the module (assuming you have plugd checked out. Alternately you can simply download the single file and use a <script> tag and place it anywhere):

 
// load the resource/plugin
dojo.require("plugd.plugin");
// define dojo.setColor and dojo.fn.setColor:
dojo.plugin("setColor", function(n, color){
	dojo.style(n, "color", color);
});
 

With those few lines, again, all the available patterns are made available to us. There are a whole collection of "dojo plugins" in the plugd project, all of which follow this "stub into dojo namespace willy nilly" pattern in the hopes some will be upgraded to Dojo Core or Base.

The source for the "plugd.plugin" module is simple. Sans comments, it weighs about 8 lines:

 
dojo.provide("plugd.plugin");
(function(d){
 
	d.fn = d.NodeList.prototype;
	d.plugin = function(pluginNamespace, fn, way){
 
		//>>excludeStart("safetyFirst", kwArgs.noWarnings == "on");
		// leave safety in optionally, build with noWarnings=on to disable check
		if(d[pluginNamespace]){
			console.warn("cowardly won't clobber '" + pluginNamespace + "' method");
			return fn; // Function
		}
		//>>excludeEnd("safetyFirst");
 
		var f = d[pluginNamespace] = fn;
		d.fn[pluginNamespace] = d.NodeList[way || "_adaptAsForEach"](f);
 
		return f; // Function
	}
 
})(dojo);
 

I added a "safetyFirst" #ifdef-like block for the build system. This way, I can disable the checking to see if my plugin will conflict with an existing function as a build option, further reducing the code. There is very little smoke and mirrors in Dojo - teaching fundamental JavaScript principals and suggesting some working practices along the way. Checkout some of the sample plugins in plugd's trunk, or check it out directly into a plugd/ folder next to your dojo/ folder and dojo.require some stuff. Most of the code is commented to the hilt, and few (if any) of the functions exceed 8 lines of code. Excellent way to view and understand some fairly cool JavaScript magic.

Dojo Build string interning revelation

I made an interesting random discovery today which opened a door for a whole new breed of Templated Dojo widgets (aka: Dijits). The Dijit portion of the Dojo Toolkit really could be broken into two parts: A Collection of pre-fabricated UI components and a well thought out framework for creating your own UI components.

At the heart of Dijit are two modules used everywhere: dijit._Widget and dijit._Templated, but those pull in a number of _base modules used to power the framework. dijit.registry, dijit.byId, dijit.typeomatic, and all the various accessibility and utility functions used internally exposed. The overall size of the Dijit framework is about 10k gzipped, including dijit._Widget and dijit._Templated, so it hardly a drop in the bucket on the wire.

dijit._Templated does a cool thing and does a ton of caching, loading and managing of templates for widgets allowing a developer to define either a templateString or templatePath to use for the rendering:

 
dojo.provide("my.TemplatedWidget");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.declare("my.TemplatedWidget", [dijit._Widget, dijit._Templated],{
	templatePath: dojo.moduleUrl("my", "templates/TemplatedWidget.html")
});
 

Basic example using templatePath, which the widget will fetch as necessary using XHR. The interesting part happens after running a Dojo build. As Neil had previously investigated, any matched templatePath variables will have their remote markup inlined into the javascript source as a templateString member.

I often run into a situation where I want to use the Dijit framework to create widgets that have children, but seldom need to make the children classes themselves. Delegating a number of identical items underneath the outer most widget instance is a great way to squeeze performance out of your app, especially when you don't need the children to compartmentalize any of their own behavior.

One solution is to handle this manually, and define some kind of childtemplate member, creating the children as you go:

 
dojo.declare("my.Thinger", [dijit._Widget, dijit._Templated], {
 
	// the containerNode in Thinger.html is an unordered-list
	templatePath: dojo.moduleUrl("my", "templates/Thinger.html"),
	childtemplate: "
<li>${foo}</li>
 
",
 
	addChild:function(/* Object */data){
		// render a child in this widget from the passed data.
		dojo.place(dojo.string.substitute(this.childtemplate, data), this.containerNode);
	}
});
 

But this immediately breaks the separation of concerns and leaves us with markup in our JavaScript, which is never a good idea. I wanted to specify an external template for the children items, but still get the advantage of the string-interning the build provides. On a whim, I decided to test how accurately the build was matching "templatePath" for the conversion, and to see if I would be able to pull something like this off:

 
dojo.declare("my.Thinger", [dijit._Widget, dijit._Templated], {
 
	// the containerNode in Thinger.html is an unordered-list
	templatePath: dojo.moduleUrl("my", "templates/Thinger.html"),
	childtemplatePath: dojo.moduleUrl("my", "templates/Thinger-child.html")
 
});
 

and have the resulting built version contain a "childtemplateString" equaling the contents of my now external Thinger-child.html template.

My whim proved accurate, though if this is a bug or a feature is yet to be determined. Taking advantage of this behavior, I know I can shim in some extra code creating a dijit._Templated variant which allows for the 'childtemplate' pattern I seek.

We're going to create a "subclass" of dijit._Templated, hooking into the buildRendering method and do some templatePath handling of our own. We need to support three things:

  1. A childtemplateString and childtemplatePath should work transparently together. String should take precedence over Path.
  2. The developer should not have to know which is being used, so make the normalized string version available as "childtemplate"
  3. The template member should be configurable, optional, and default to "off" (maintaining backwards compatibility)

The task was incredibly easy. I chose using a "subTemplate" member as indication a child template exists, and to avoid ambiguity in naming selections. If no subTemplate is passed, nothing new happens. If a subTemplate string is passed, that string dictates where the template will be available. Eg: subTemplate:"foo" creates this.footemplate from either footemplateString or footemplatePath.

 
dojo.provide("beer._Templated");
dojo.require("dijit._Templated");
(function(){
 
	var cachedString = {};
 
	dojo.declare("beer._Templated", dijit._Templated, {
 
		// subTemplate: String
		//		An identifier for this childtemplate relationship. eg: Set to 'item',
		//		which allows for "itemtemplateString" or "itemtemplatePath" usage as
		//		you would a normal `dijit._Templated`. After `buildRendering`, an
		//		instance member is provided based on this `subTemplate` name as well.
		//		eg: this.itemtemplate will always be available in `postCreate` for
		//		use internally.
		subTemplate:null,
 
		buildRendering:function(){
			// hook into _Templated's buildRendering, cache templates on a
			// per-class basis. 
 
			if(this.subTemplate){
				var identifier = this.subTemplate + "template",
					s = "String";
 
				// there is a lot of repetition between cache and this[something],
				// but it only happens once, so isn't so bad (vs more code?)
				if(!cachedString[this.declaredClass]){
					if(!this[identifier + s]){
						// assume we have an itemtemplatePath in the absence
						// of an itemtemplateString
						dojo.xhrGet({
							url: this[identifier + "Path"],
							sync: true, // we should be only doing this once
							load: dojo.hitch(this, function(template){
								this[identifier + s] = dojo.trim(template);
							})
						});
					}
					// cache the string for the template
					cachedString[this.declaredClass] = this[identifier + s];
				}
				this[identifier] = cachedString[this.declaredClass];
			}
			// always call native buildRendering
			this.inherited(arguments);
		}
 
	});
 
})();
 

Now you can declare classes inheriting from beer._Templated, and have all the support of dijit._Templated in addition to a nice shorthand/custom templating solution. To use:

 
dojo.provide("my.Thing");
dojo.require("dijit._Widget");
dojo.require("beer._Templated");
dojo.declare("my.Thing", [dijit._Widget, beer._Templated], {
 
	// core:
	templatePath: dojo.moduleUrl("my","templates/Thing.html"),
	// extra:
	childtemplatePath: dojo.moduleUrl("my", "templates/Sub-Thing.html"),
	subTemplate:"child",
 
	// using it:
	addChild: function(data){
		var n = dojo.place(dojo.string.substitute(this.childtemplate), data), this.containerNode);
		dojo.style(n, "opacity", 0);
		dojo.fadeIn({ node: n }).play(200);
	}
 
});
 

The only problem I have with this so far is the naming convention. "childtemplatePath" should be written as "childTemplatePath", as per the Dojo style guidelines. A quick (3 line) adjustment to the build utility, and that support can be added as well.

The 'beer' namespace comes from me discovering this tidbit while working on twitterverse, which [for whatever reason] is using 'beer' for the code.