Configuring Dojo with dojoConfig

The dojoConfig object (formerly djConfig) allows you to set options and default behavior for various aspects of the toolkit. In this tutorial we'll explore what's possible and how you can put dojoConfig to use in your code.

  • Difficulty: Beginner
  • Dojo Version: 1.6

Introduction

The dojoConfig object (known as djConfig prior to Dojo 1.6) is the primary mechanism for configuring Dojo in a web page or application. It is referenced by the module loader, as well as Dojo components with global options. It can further be used as a configuration point for custom applications, if desired.

The old object name of djConfig is deprecated, but any existing code using it will continue to work up until 2.0. At the time of writing, most documentation still uses djConfig; the two names are directly equivalent, but we'll adopt and encourage use of the new dojoConfig name from here on.

Getting Started

Let's run through some quick examples to see how dojoConfig works in practice. First, a programmatic example of setting dojoConfig directly:

<script>
	dojoConfig = {
		isDebug: true,
		parseOnLoad: true,
		foo: "bar"
	};
</script>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js"></script>
View Demo

Notice that dojoConfig is defined in a script block before dojo(.xd).js is loaded. This is of paramount importance—if reversed, the configuration properties will be ignored.

In this example, we have set two flags: isDebug: true and parseOnLoad: true. Additionally, a custom property has been specified: foo: "bar". For this demo, a dijit.Dialog has been placed in the page. Code that runs from dojo.ready converts the value of dojo.config to JSON and places it into the dialog for review. Among the results are our properties: isDebug, parseOnLoad, and foo. But there are also a few others, which are related to the fact that the demo page uses the cross-domain, Google-CDN-hosted version of Dojo 1.6.

It is important to note the distinction between dojoConfig and dojo.config. dojoConfig is purely for input purposes—this is how we communicate configuration parameters to the loader and modules. During the bootstrap process, dojo.config is populated from these parameters for later lookup by module code.

Here's the same example written declaratively:

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.6.3/dojo/dojo.xd.js"
		data-dojo-config="isDebug: true,parseOnLoad: true,foo: 'bar'">
</script>
View Demo

In this case, we use the same data-dojo-config attribute on the Dojo script element that you've seen in other tutorials and examples. This is entirely functionally equivalent to the previous example. In both cases, the config options we provide are ultimately mixed into the dojo.config object, where they can be retrieved immediately after the bootstrapping process that takes place as dojo(.xd).js loads.

You can confirm this by setting some new values in dojoConfig, and checking the dojo.config object in the console. So, dojoConfig is a generic configuration property-bag for Dojo. Lets see what options there are and how we can use them.

Debug Configuration

You should be familiar by now with the isDebug config flag. However, one purpose of this flag might not be entirely clear if you develop using a browser which has its own developer console. When false, it will create a dummy console object if necessary so that any console.* logging statements in your code safely and quietly execute without throwing exceptions. If isDebug is true, and you have Firebug or another console available and open, it does nothing. But if you don't have a console, it will load Dojo's version of Firebug Lite, and create the console UI at the bottom of the page. This can be handy when debugging in earlier versions of IE or other browsers without nice developer tools.

The following additional options are available to further configure this in-page console:

  • debugContainerId: specify a particular element to contain the console UI
  • popup: use a popup window rather than rendering the console into the current window

In addition to providing this console to browsers without their own, isDebug is also responsible for emitting dojo.deprecated and dojo.experimental warnings; if isDebug is false, these warnings will be suppressed.

Loading Configuration

Another important function of dojoConfig is passing parameters through to the loader. You may have noticed that loading a cross-domain build of dojo automatically set dojo.config.useXDomain to true in the previous demo. We can also set the following parameters:

  • xdWaitSeconds: How long to wait before giving up on loading a module when using the cross-domain loader.
  • baseUrl: The URL from which module paths should be resolved. This will default to the directory from which dojo(.xd).js was loaded.
  • require: An optional array of modules to load. Behaves the same as calling dojo.require after the Dojo script tag.
  • modulePaths: Equivalent to calling dojo.registerModulePath after the dojo script tag. The value should be a dictionary object, mapping module namespaces to URLs.

Let's see an example. The baseUrl and modulePaths options turn out to be especially useful when you want to load Dojo from one server (e.g. the Google CDN), but other namespaces from another (e.g. your own.)

<script>
	dojoConfig = {
		isDebug: true,
		parseOnLoad: true,
		baseUrl: '/documentation/tutorials/1.6/dojo_config/',
		modulePaths: {
			"demo": "demo"
		}
	};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.6.3/dojo/dojo.xd.js"></script>
<script>
	dojo.require("demo.AuthoredDialog");

	dojo.ready(function(){
		var dlg = dijit.byId("dialog");
		dlg.set("content", '<pre>'+dojo.toJson(dojo.config, true)+'</pre>');
		dlg.show();
	});
</script>

...In the body, the markup has been changed slightly to use the custom dialog widget:

<div id="dialog" data-dojo-type="demo.AuthoredDialog"
	data-dojo-props="title: 'dojo.config.baseUrl demo', authorAvatarSrc: '/includes/authors/sam_foster/avatar.jpg', authorName: 'Sam Foster'">
</div>
View Demo

By using baseUrl, we've told Dojo to resolve paths from this directory, rather than where we loaded dojo.js from. Furthermore, the mapping in the modulePaths object dictates that modules in the demo namespace should be loaded from the "demo" directory, relative to the baseUrl. The result is that demo.AuthoredDialog resolves to a directory on this server rather than the CDN. Again, the resulting dojo.config object is serialized to the dialog for inspection.

For more information on using baseUrl and modulePaths to load local custom modules while loading Dojo from a CDN, see our tutorial on Using Custom Modules with a CDN.

Lifecycle options

Using dojo.config we can also get access to when Dojo's "ready" moment happens and can configure what happens at that time. You may have encountered the parseOnLoad option before; it is the equivalent of:

	<script src="//ajax.googleapis.com/ajax/libs/dojo/1.6.3/dojo/dojo.xd.js"></script>
	<script>
		dojo.require("dojo.parser");
		dojo.ready(function(){
			dojo.parser.parse();
		});
	</script>

...But with one important change: when you use parseOnLoad, any functions you have passed to dojo.ready will not get executed until after the parser runs and any widgets it finds have been created and initialized.

You can also add require and addOnLoad options to dojo.config. In the following demo, we've set up a demo.logSequenceEntry method we can call to reveal the order in which events occur.

  • The page requires two modules—one from the dojoConfig declaration, and one from a script block after the Dojo script tag
  • The page is set up to either set dojoConfig.parseOnLoad to true, or false—in which case the parser is run from a dojo.ready function
  • The page has addOnLoad functions defined in the dojoConfig object, as well as dojo.ready functions
  • Each required module will log when it is loaded. The widget will log from its startup function—i.e. after it has been created, placed, and fully initialized

parseOnLoad = false

Demo with parseOnLoad: false

parseOnLoad = false

Demo with parseOnLoad: true

Notice, first of all, that it does not change the result: any ready/addOnLoad functions always fire after all required modules have loaded. The main difference is the effect of parseOnLoad: when set to true, parsing and widget creation happens and then ready functions run.

If you are injecting a built version of Dojo into a page after it has loaded, set dojoConfig.afterOnLoad to true. This tells Dojo not to wait for a DOMContentLoaded event that will never happen, and to proceed immediately with any ready functions as soon as dependencies are loaded. Keep in mind, however, that this works only with Dojo builds, not the source distribution.

Locale and Internationalization

Dojo's i18n system is documented in its own right, and worthy of its own tutorial, but we'll touch on it here just to show dojoConfig at work again.

You can configure the locale to use for any widgets or localized content using Dojo's i18n infrastructure from dojoConfig. The locale option lets you override the default provided to Dojo by your browser. A simple demo shows it at work:

locale = 'zh'

<script>
	var dojoConfig = {
		isDebug: true,
		parseOnLoad: true,
		// look for a locale=xx query string param, else default to 'en-us'
		locale: location.search.match(/locale=([\w\-]+)/) ? RegExp.$1 : "en-us"
	};
</script>
<script src="ajax.googleapis.com/ajax/libs/dojo/1.6.3/dojo/dojo.xd.js"></script>
<script>
	dojo.require("dojo.i18n");
	dojo.require("dojo.date.locale");
	dojo.require("dijit.Dialog");

	dojo.ready(function(){
		var now = new Date();
		var dlg = new dijit.Dialog({
			id: 'dialog',
			// set a title on the dialog of today's date,
			// using a localized date format
			title: 'Today: '+ dojo.date.locale.format(now, {
					formatLength:'full',selector:'date'
			})
		}).placeAt(dojo.body());
		dlg.startup();

		dlg.set("content", '<pre>'+dojo.toJson(dojo.config, true)+'</pre>');
		dlg.show();
	});
</script>

Demo with dojo.config.locale ='zh' (Chinese)

In the demo, where we define the locale property of the dojoConfig object, we look for a locale=xx parameter from the query string. That's a demo artifact; typically you might hard-code the locale. Setting the locale ahead of any module loading ensures that the correct localized message bundle dependencies are loaded where necessary. In this case, we use the dojo.data.locale module to format a date object to a localized string for the Dialog title.

For multi-lingual pages, you will need to load bundles for the other locales as well as the one specified by your browser or the dojoConfig.locale property. In this case, use the extraLocale config property, with an array of string locale names.

When using the dojo.parser, the lang= setting on an ancestor DOMNode overrides the dojoConfig.locale setting. This behavior will change in Dojo 2.0. You can also specify the lang for individual widgets, overriding the dojoConfig.locale setting for only that widget.

Custom Properties

Because dojo.config is always known to exist, and is the logical place to provide for page-scoped configuration, several other modules in Dojo use it for their own particular configuration properties. We see this in Dijit, and especially in DojoX, where module flags and behavior can be set:

Dijit Editor
allowXdRichTextSave
dojox GFX
dojoxGfxSvgProxyFrameUrl, forceGfxRenderer, gfxRenderer
dojox.html metrics
fontSizeWatch
dojox.io transports and plugins
xipClientUrl, dojoCallbackUrl
dojox.image
preloadImages
dojox.analytics plugins
sendInterval, inTransitRetry, analyticsUrl, sendMethod, maxRequestSize, idleTime, watchMouseOver, sampleDelay, targetProps, windowConnects, urchin
dojox.cometd
cometdRoot
dojox.form.FileUploader
uploaderPath
dojox.mobile
mblApplyPageStyles, mblHideAddressBar, mblAlwaysHideAddressBar, mobileAnim, mblLoadCompatCssFiles

What works for dojox modules also works for your own applications and modules. dojoConfig is an ideal place to provide configuration for behavior and page- or application-wide properties. Consider the following:

<script>
	dojoConfig = {
		isDebug: true,
		parseOnLoad: true,
		app: {
			userName: "Anonymous"
		}
	};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.6.3/dojo/dojo.xd.js"></script>
<script>
	dojo.require("dijit.Dialog");

	// pull configuration from the query string
	// and mix it into our app config
	var queryParams = dojo.queryToObject(location.search.substring(1));
	dojo.mixin(dojo.config.app, queryParams);

	dojo.ready(function(){
		var dlg = dijit.byId("dialog");
		// draw on the app config to put up a personalized message
		dlg.set("title", 'Welcome back ' + dojo.config.app.userName);
		dlg.set("content", '<pre>'+dojo.toJson(dojo.config, true)+'</pre>');
		dlg.show();
	});
</script>
View Application Config Demo

In this example, we've tacked on an "app" dojoConfig property, which we later reference via dojo.config to put up a personalized greeting in the Dialog. There are many ways to approach populating dojoConfig.app. It can be pre-populated with reasonable defaults and mixed-in with specific values later. In production, the dojoConfig script block might get written out on the server-side. Alternatively, you could populate it from a cookie with JSON-formatted configuration values, or—as in our earlier example—you could extract configuration data straight from the query string. In development and test mode, you could use a template that provides dummy values, or load a script or module that populates it.

Conclusion

In this tutorial, we've covered many common ways in which dojo.config can be populated—via dojoConfig or data-dojo-config—and how its values influence behavior and supply properties to Dojo modules.

The well-defined position and role dojo.config has in the Dojo bootstrap and lifecycle means that the same concept applies neatly to Dojo modules and even your own modules and applications.

Colophon

Error in the tutorial? Can’t find what you are looking for? Let us know!