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.

A Dojo Plugin Pattern

I created a new widget last night based on a couple small functions in base plugd: dojo.twit ... It is a very simple widget with a minimal 2k overhead and illustrates just how truly "plug-able" and flexible Dojo is.

For the horribly impatient: checkout the twitter feed on the sidebar (another degradable example of Dojo) or download the full built twit.js (requires Dojo 1.3)

There are three existing patterns in Dojo that are loosely related:

  • Acting upon a node - eg: dojo.style(node, {}), dojo.anim(node, {})
  • Acting upon a list of nodes - eg: dojo.query(".nodes").style({})
  • Converting a node into a "widget" - eg: new my.Widget({}, node)

The first two go hand-in-hand. Anything you can do to one node you should be able to repeat across a list of nodes in the same way with only a marginal cost for the iteration. The functions to act upon a node follow a very simple API:

 
some.func = function(/* String|DomNode */node, /* Object? */props){
	// summary: do something to node.
	// node: Can be a DOMNode reference, or string ID or a DOMNode to use
	// props: Object-hash of properties and parameters for this function call
	node = dojo.byId(node);
	// now do something to node.
}
 

The functions that act upon a list of nodes are simply mixed into dojo.NodeList:

 
// new in Dojo 1.3.0:
dojo.NodeList.func = dojo.NodeList._adaptAsForEach(some.func);	
 
// old Dojo 1.0 - 1.2.x way:
dojo.extend(dojo.NodeList, {
	func: function(props){
		// summary: run `some.func` for each of the nodes in this list
		return this.forEach(function(n){
			some.func(n, props);
		});
	}
});
 

To use the some.func function either way:

 
// one node
some.func("someId", { arg1: "a" });
// all with class="bar"
dojo.query(".bar").func({ arg1: "a" });
 

Note the above use of a new Dojo 1.3 API _adaptAsForEach ... These are private API's put in place to allow little to no duplication between Dojo's own following of this pattern. The direct forEach method will always work as shown, as they are public APIs, though _adaptAsForEach may change. (I'm taking the gamble they will remain in place in some form for quite some time, and enjoy the savings they provide)

By following this pattern, Dojo is able to provide incredibly fast low-level APIs, then map them directly into the Selector engine (aka: dojo.query) for bulk operations.

The last item ("Widgets") actually has two use cases: programatic and declarative. The programatic v. declarative argument has been going on for a long time, and many people still cry standards-foul when referring to Dojo -- this is entirely unnecessary. The declarative way is the optional method of the "plain old JavaScript" way of instantiating some class[like] object:

 
// programatic:
new dijit.TitlePane({ title:"The Title" }, "nodeOrId");
 
<!-- declarative -->
<div dojoType="dijit.TitlePane" id="someId" title="The Title"></div>
 

The pattern here is simple. The dojoType attribute maps to some object/function (in the example: dijit.TitlePane). The dojo.parser is the only thing in Dojo that understands the dojoType attribute. The Parser's sole job is to:

  • find nodes with a dojoType attribute. eg: dojoType="Thinger"
  • read the attributes on the found nodes, and convert them to an object.
  • call new Thinger(thatObject, foundNode) for each of the nodes

The attributes which are read by the parser aren't entirely arbitrary. For performance reasons, the attributes must be defined in the class you plan to instantiate in order for the parser to find them:

 
dojo.declare("Thinger", null, {
	exampleAttrib:"default-value"
	constructor: function(args, node){
		// generic ctor function
		dojo.mixin(this, args);
		this.node = dojo.byId(node);
	}
})
 

The above "Thinger" example will only attempt to locate an "exampleAttrib" parameter on a passed node:

 
<div dojoType="Thinger" exampleAttrib="overridden" ignoredAttrib="useless"></div>
 

So the widget pattern is nearly identical to the Dojo pattern (only reversed). Again together:

 
	var args = { prop:"b" };
 
	// functions go node, args
	my.func("someNode", args);
	dojo.query("#someNode").func(args);
 
	// widgets go args, node
	new Thinger(args, "someNode");	
<p dojoType="Thinger" prop="b">
 

The reasoning behind the parameter order difference is simple: with widgets the node is optional and with functions the node is explicit. If you are programatically creating a Thinger, you can omit the node (at least in the case of Dijit) as one will be created for you. You must place the node in the DOM manually in this case.

 
	new dijit.TitlePane({ title:"Title", content:"
 
The inner content
 
" }).placeAt(dojo.body());
 

The parser simply passes the node with the dojoType, and no new nodes are created.

All of this explanation is leading into my twit.js code, albeit an incredibly shortened version of the final file. The above use cases exist in Dojo, and are more or less a constant across the toolkit. I wanted to make my little tweeter plugin work for all of them, without any duplication.

First things first: define the dojo.twit() and dojo.NodeList functions as skeletons. We're making this a full module, so we must include the dojo.provide() call.

 
dojo.provide("plugd.twit");
 
dojo.require("dojo.string"); // required for template substitution
dojo.require("plugd.script"); // simple/tiny dojo.io.script replacement
 
(function(d){
 
	// the defaults we can override
	var defaults = {
		"user":"phiggins",
		"count":"7",
		"template":"
<p" + ">${text}</" + "p>"
	}
 
	// the main function
	d.twit = function(node, args){
		node = d.byId(node);
		// mix in the defaults with the args
		var opts = d.mixin({}, defaults, args);
 
		/* the rest of the twit code */
	}
 
	// 1.3+ only. use this.forEach method for 1.0 - 1.2
	d.NodeList.prototype.twit = d.NodeList._adaptAsForEach(d.twit);
 
})(dojo);
 

This, so far, allows us the two functional examples following the Dojo pattern. We need to fill in some code in the core dojo.twit() function to have this complete, but the keys are there:

  • follows the same API pattern of accepting a string ID or domNode
  • accepts an object hash of properties to mix over the defaults
  • and works transparently with dojo.query

Before we move into making this work as a typical widget would, I should point on special thing out. The "template" member in the defaults is using dojo.string.substitute for basic variable replacement. When we fetch the list of tweets for the opts.user, we will apply this template to each data item returned. No extra work on my part was needed:

 
	d.twit = function(node, args){
		node = d.byId(node);
		// mix in the defaults with the args
		var opts = d.mixin({}, defaults, args);
 
		/* the rest of the twit code: in pseudo-code */
		fetch(twitterUrl, function(data){
			dojo.forEach(data, function(tweet){
				// append a new DOM to this node based on the passed template:
				dojo.place(dojo.string.substitute(opts.template, tweet), node)
			})
		})
	}
 

The substitute function simply mixes the tweet data into opts.template string, eg: ${text} becomes whatever tweet.text (the tweet content) is. By passing this result directly to dojo.place we are creating the new dom (this is also new in 1.3 -- not place(), but place() acting as a dom-creation API), and appending it to the node we targeted.

This is awesome until we go to implement the Class-based / dojo.parser version. The template:"" option needs to be an HTML snippet, and it would be incredibly ugly to support a pattern like:

 
<ul dojoType="dojo.Twitter" template="&lt;li&gt;${text}&lt;/li&gt;"></ul>
 

That makes me cringe, and I'm ok with the general use of a dojoType. I needed a better solution. I decided it would be simple enough to use the content of the widget node as the template. For example:

 
<ul dojoType="dojo.Twitter" user="phiggins">
<li>${text}</li>
</ul>
 

To do this we'll need to read the innerHTML at the time of instantiation, then empty the node (to clear out the template):

 
	d.Twitter = function(args, node){
		node = d.byId(node);
		d.twit(node, d.mixin(args, { template: n.innerHTML }));
		d.empty(node);
	}
	// mix in the defaults into the .prototype, making parser recognize them:
	d.extend(d.Twitter, defaults);
 

Now, officially, if dojo.twit does what is is supposed to (and it does), all the following API's are available with almost no repetition. Pick your style:

 
// functions:
dojo.twit("nodeId", { user:"phiggins", template:"
 
${text}
 
" })
dojo.query("ul.foo").twit({ template:"
<li>${text}</li>
 
" });
 
// plain class
new dojo.Twitter({ user:"foo" }, "nodeId")
// and the infamous dojoType
<ul dojoType="dojo.Twitter" user="phiggins">
<li>${text}</li>
</ul>
 

You can see this in action in the sidebar. Entirely degradable. If no JS, no "Twitter" label is shown. Two lines in my global.js trigger the rest:

 
dojo.addOnLoad(function(){
	dojo.style("tweets", "display", "block"); // show the block, js is enabled
	dojo.query("#twitter").twit({ template:"
<li>
 
${text}
</li>
 
 "}); // make it a list
});
 

I love JavaScript, and Dojo 1.3 makes JavaScript that much more fun. Even if you don't agree with the library, and functionality deemed important and common enough for the base dojo.js -- there are years of professional-grade coding living in there, available to learn from and grow upon.

Changing APIs, or: why JavaScript rocks.

Dojo has an exceptionally fast and performant "custom event" system that allows a developer to communicate ambiguously between components with little overhead, and [much like Dojo itself] in a "use as needed" manner: dojo.publish and dojo.subscribe, both provided in base Dojo (dojo.js)

The API's are basic: dojo.subscribe some function to a topic, and dojo.publish some data on that topic. Bonus points for being able to unsubscribe at will:

 
	var h = dojo.subscribe("/dojo/rocks", function(data){
		console.log(data); // "A message";
	});
	dojo.publish("/dojo/rocks", ["A message!"]);
	dojo.unsubscribe(h);
 

The most immediate issue seen is having to pass an array to the publish() call. Dion pointed this out to me shortly after I reviewed the newly-ported-to-Dojo Bespin code base. The "array as the first parameter" bit is defined by the API docs and expected, though in many cases entirely unnecessary. The reason makes absolute sense: dojo.publish converts the passed array into ordered arguments:

 
	dojo.subscribe("/dojo/kicks", function(a, b, c, d){
		console.log(a,b,c,d); // one, 2, three, 4
	});
	dojo.publish("/dojo/kicks", ["one", 2, "three", 4]);
 

Without getting into the details, the reason is the subscribed function is called with the array passed to .apply:

 
	// define dojo.publish:
	dojo.publish = function(topic, args){
		var f = dojo._topics[topic];
		if(f){
			f.apply(f, args||[]);
		}
	}
 

This triggers an empty function bound to the the topic name, and the magic of dojo.connect calls any attached functions, passing the same arguments to each. Because .apply() only accepts an array an empty array is passed in the event the passed args parameter is 'falsey'.

... which makes perfect sense until one of two things happen (which are arguably the most common):

 
	// I want to pass one, single, parameter:
	dojo.publish("topic:foo", "bar");
	// I want to pass a list of parameters in order:
	dojo.publish("topic:foo", "a", "b", "c");
 

The second example makes less sense until you understand that dojo.connect executes all attached functions with the same parameters as the called function:

 
	var obj = {
		bar: function(a,b,c){
			// ... anything.
		}
	}
 
	// this won't work out of the box:
	dojo.connect(obj, "bar", dojo.partial(dojo.publish, "foo"));
	dojo.subscribe("foo", function(a,b,c,d){
		console.log(a,b,c,d); // one, two, three, undefined
	});
 
	obj.bar("one", "two", "three");
 

When obj.bar() is called, the dojo.partial call executes "dojo.publish('foo', ...)", where '...' is equal to any arguments passed to the original obj.bar() call. In the above case, "one", "two", "three" is passed to the bound connected function. The connected function is a curried version of dojo.publish, pushing to the topic "foo".

I wanted to allow for either publish() syntax as mentioned, and not break backwards compatibility. I attempted to do this with:

 
	// _this_ is why JavaScript is cool:
	var old = dojo.publish;
	dojo.publish = function(topic, args){
		return old(topic, dojo.isArray(args) ? args : [args]);
	}
 

But this has the unfortunate (non-back-compat) side effects of a) potentially passing a literal undefined to the subscribed functions 2) is an additional call to some [possibly] expensive functions, and c) generally breaks down for anyone expecting publish() to work as they've been explained previously, and 4) doesn't cover the case of an ambiguous length of arguments.

A quick solution to a) would be:

 
	return old(topic, dojo.isArray(args) ? args : [ args || {} ]);
 

... but you must still check the passed argument before dot-accessing any of it's members.

My solution was a new API, "pub", which simply wraps "dojo.publish" with some fun JavaScript foo:

 
	dojo.pub = function(){
		// summary: wrap `dojo.publish` to allow any number of arguments
		var a = dojo._toArray(arguments);
		return dojo.publish(a.shift(), a);
	}
 

Thought I won't take credit for it, I may have just just invented the most compelling use of an inline .shift() call, ever. Briefly: dojo._toArray, while private, will convert any enumerable object to a real array. Our function "pub" takes any number of arguments, converts them to an array (a), then returns the value from calling dojo.publish() ... what we pass to publish() is the fun:

a.shift() will return the first element of the array (a). This return value is passed to the first argument of the dojo.publish call. The shift() call also modifies the array (a) to be one element shorter, so our next reference to (a) will the reduced list. We're passing this reduced array to the second.

Following this pattern in your own functions is easy, even without Dojo. dojo._toArray does more, but in these examples all we've done is convert 'arguments' to an array. We can likely do this faster (and without Dojo):

 
	var aps = Array.prototype.slice;
	// simple version of `dojo._toArray`
	var toArray(obj){
		return aps.call(obj, 0);
	}
 

`dojo.pub` is implemented in plugd, which will have a new version to coincide with Dojo 1.3.0 to be released shortly. Hopefully the dojo.pub API will take over the existing dojo.publish API in Dojo 2.0, where we get to fix these kinds of things.

update Mar 7 2009: I mistakenly transposed the function as .slice(). It should have been .shift() in this blog. Thanks Wolfram for catching that! PlugD was using .shift() and the unit tests pass.