There are many reasons you might end up needing to patch your Dojo source tree. Maintaining patches can be a pain, and sometimes outside of your control entirely. It could be a bug you’ve found, or something you really wish a Dojo component did/didn’t do, or you are having to work against an older release of Dojo, or there’s a patch in trac that fixes an issue you have, but it has not yet been committed. In this post, we’ll present a neat way to make the change, keep what you did explicit so other developers aren’t confused, and maintain it outside the Dojo source.

Here’s an example: Dojo 1.3 introduces dojo.create into Dojo Base – a new, handy API for creating DOM elements. But, if you’re already developing with a previous version of Dojo, it won’t be available to you until you upgrade to 1.3. You can create a shim to start using it immediately like this:

dojo.provide("yourns.patches.dojo.base");

if(dojo.version.major == 1 && dojo.version.minor < 3) {
	// a copy of dojo.create, from svn trunk's dojo/_base/html.js
	// lots of useful doc comments snipped for brevity
	dojo.create = function(tag, attrs, refNode, pos) {
		var doc = d.doc;
		if(refNode){		
			refNode = d.byId(refNode);
			doc = refNode.ownerDocument;
		}
		if(d.isString(tag)){
			tag = doc.createElement(tag);
		}
		if(attrs){ d.attr(tag, attrs); }
		if(refNode){ d.place(tag, refNode, pos); }
		return tag; // DomNode
	};
}

Now, to use it:

// if you've not already registered your namespace, do so...
dojo.registerModulePath("yourns", "../yourDirectory");

dojo.require("yourns.patches.dojo.base"); 

dojo.addOnLoad(function() {
  dojo.create("div", {innerHTML:"this worked"}, dojo.body());
});

The naming scheme here is:

  • "yourns" - placeholder for whatever your namespace is.
  • "patches" - a package/directory to contain all such patches. You might use the same directory to also keep static resources like CSS files that tweak/extend a Dojo CSS rule, or image. For this example, you'll have created a file at ../yourDirectory/patches/dojo/base.js
  • "dojo.base" - the name of the dojo module/method this patch impacts. To patch dijit.layout.BorderContainer you might call this "yourns.patches.dijit.layout.BorderContainer", or, bundle up all your Dijit patches into "yourns.patches.dijit". Though as a rule it is best to leave optimization to the build process and focus on clarity of intent and scope in your source. The goal here is to avoid "strange magic from a distance" by putting the change directly into the context in which it applies.

You can treat this like any other module in your build profile, just make sure you place it ahead of any code that relies on it being there. When you do upgrade, you can simply remove the patch, and the version check gives you a grace period to do so.

The Dojo Toolkit is just that - tools to help you produce better work, faster. The real world of web application development is a much more complicated place than most tutorials and code samples would like you to believe, and most projects throw you a curve ball at some point. Your toolkit should work with you at times like that, and this is just one technique that allows you to adapt gracefully and move on to the next problem to solve.