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.
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:
<!-- set Dojo configuration, load Dojo -->
<script>
dojoConfig= {
has: {
"dojo-firebug": true
},
parseOnLoad: false,
foo: "bar",
async: true
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<script>
// Require the registry, parser, Dialog, and wait for domReady
require(["dijit/registry", "dojo/parser", "dojo/json", "dojo/_base/config", "dijit/Dialog", "dojo/domReady!"]
, function(registry, parser, JSON, config) {
// Explicitly parse the page
parser.parse();
// Find the dialog
var dialog = registry.byId("dialog");
// Set the content equal to what dojo.config is
dialog.set("content", "<pre>" + JSON.stringify(config, null, "\t") + "```");
// Show the dialog
dialog.show();
});
</script>
<!-- and later in the page -->
<div id="dialog" data-dojo-type="dijit/Dialog" data-dojo-props="title: 'dojoConfig / dojo/_base/config'"></div>
Notice that dojoConfig
is defined in a script block
before dojo.js is loaded. This is of paramount
importance—if reversed, the configuration properties will be ignored.
In this example, we have set three flags: parseOnLoad: false
, has
(dojo-firebug
sub-property), and async: 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 within the require
callback converts the value of dojo.config
to JSON and places it into the dialog for review.
Among the results are our properties: parseOnLoad
, has
, 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.10.
It is important to note the distinction between dojoConfig
and dojo/_base/config
.
dojoConfig
is purely for input purposes—this is how we
communicate configuration parameters to the loader and modules.
During the bootstrap process, dojo/_base/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.10.4/dojo/dojo.js"
data-dojo-config="has:{'dojo-firebug': true}, parseOnLoad: false, foo: 'bar', async: 1">
</script>
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/_base/config
object, where they can be retrieved immediately after
the bootstrapping process that takes place as dojo.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.
has() Configuration
One of the major features added in Dojo 1.7+ was the use of the has() pattern for feature detection. We can specify features for the has() feature set in dojoConfig
, by including an object hash of features as the value of the has
property. This feature set is now used for determining certain supported capabilities in Dojo. For example, we could disable the amd factory scan (scanning the module for CommonJS require(module) statements to load as deps) with:
<script>
dojoConfig = {
has: {
"dojo-amd-factory-scan": false
}
};
</script>
Debug/Firebug Lite Configuration
You may be familiar by now with the isDebug
config flag from other tutorials or usage of Dojo in versions prior to Dojo 1.7, to explicitly enable debug information. In Dojo 1.7+, this is now also specified with a has() feature at a higher level of granularity. To enable debugging assistance with Firebug Lite for older versions of Internet Explorer, we can set the dojo-firebug feature (isDebug can still be used to load this, but using the feature will load earlier in the loading cycle in async mode). If 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.
To enable debugging messages for deprecated and experimental features, we can set dojo-debug-messages to true (this defaults to false, unless you have set isDebug). if this feature is set to false
, these warnings will be suppressed. For example, to enable a developer console (browser provided or use Firebug Lite) and log debugging messages:
<script>
dojoConfig = {
has: {
"dojo-firebug": true,
"dojo-debug-messages": true
}
};
</script>
To disable a guaranteed console object, we can set dojo-guarantee-console feature to false. This feature defaults to true and will create a dummy
console
object if necessary so that any console.*
logging statements in your code safely and quietly execute without throwing exceptions.
The following additional options are available to further configure this in-page console:
debugContainerId
: specify a particular element to contain the console UIpopup
: use a popup window rather than rendering the console into the current window
Loader Configuration
Dojo received a new loader in Dojo 1.7 to accommodate for the toolkit's new AMD module format. This new loader added a few new configuration options that are crucial to defining packages, maps, and more. For details on the loader, see the Advanced AMD Usage tutorial. Important loader configuration parameters include:
baseUrl
: The base URL prepended to a module identifier when converting it to a path or URL.
baseUrl: "/js"
packages
: An array of objects which provide the package name and location:
packages: [{
name: "myapp",
location: "/js/myapp"
}]
map
: Allows you to map paths in module identifiers to different paths:
map: {
dijit16: {
dojo: "dojo16"
}
}
paths
: a map of module id fragments to file paths:
var dojoConfig = {
packages: [
"package1",
"package2"
],
paths: {
package1: "../lib/package1",
package2: "/js/package2"
}
};
// ...is equivalent to:
var dojoConfig = {
packages: [
{ name: "package1", location: "../lib/package1" },
{ name: "package2", location: "/js/package2" }
]
};
async
: Defines if Dojo core should be loaded asynchronously. Values can betrue
,false
orlegacyAsync
, which puts the loader permanently in legacy cross-domain mode.
async: true
parseOnLoad
: If true, parses the page withdojo/parser
when the DOM and all initial dependencies (including those in thedojoConfig.deps
array) have loaded.
parseOnLoad: true
It is recommended that
parseOnLoad
be left at false (it defaults to false, so you can simply omit this property), and that developers explicitly requiredojo/parser
and callparser.parse()
.
deps
: An array of resource paths which should load immediately once Dojo has loaded:
deps: ["dojo/parser"]
callback
: The callback to execute oncedeps
have been retrieved:
callback: function(parser) {
// Use the resources provided here
}
waitSeconds
: Amount of time to wait before signaling load timeout for a module; defaults to 0 (wait forever):
waitSeconds: 5
cacheBust
: If true, appends the time as a querystring to each module URL to avoid module caching:
cacheBust: true
Now let's create a simple demo that puts the basic parameters to use. One very common scenario is using Dojo Toolkit from CDN with local modules. Let's say we use Google CDN with modules in the /documentation/tutorials/1.10/dojo_config/demo
space:
<!-- Configure Dojo first -->
<script>
dojoConfig = {
has: {
"dojo-firebug": true,
"dojo-debug-messages": true
},
// Don't attempt to parse the page for widgets
parseOnLoad: false,
packages: [
// Any references to a "demo" resource should load modules locally, *not* from CDN
{
name: "demo",
location: "/documentation/tutorials/1.10/dojo_config/demo"
}
],
// Timeout after 10 seconds
waitSeconds: 10,
map: {
// Instead of having to type "dojo/domReady!", we just want "ready!" instead
"*": {
ready: "dojo/domReady"
}
},
// Get "fresh" resources
cacheBust: true
};
</script>
<!-- Load Dojo, Dijit, and DojoX resources from Google CDN -->
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<!-- Load a "demo" module -->
<script>
require(["demo/AuthoredDialog", "dojo/parser", "ready!"], function(AuthoredDialog, parser) {
// Parse the page
parser.parse();
// Do something with demo/AuthoredDialog...
});
</script>
By using the packages
configuration, we've made all references to demo/*
point to our local /documentation/tutorials/1.10/dojo_config/demo/
directory, while allowing any references to dojo
, dijit
, and dojox
to come from Google CDN. Had the demo
package not been defined, the request for demo/AuthoredDialog
would have gone to //ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/demo/AuthoredDialog.js
. We also used alias, by associating ready
with dojo/domReady
.
Extensive documentation about the new loader provides even more details.
The new loader also supports the legacy
dojo.require()
resource loading and configuration properties likemodulePaths
covered in this same tutorial for Dojo 1.6, thus allowing developers to safely upgrade existing applications easily and without worry.
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:
<script>
var dojoConfig = {
has: {
"dojo-firebug": true,
"dojo-debug-messages": 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.10.4/dojo/dojo.js"></script>
<script>
require(["dojo/date/locale", "dijit/Dialog", "dojo/json", "dojo/_base/config",
"dojo/_base/window", "dojo/i18n", "dojo/domReady!"]
, function(locale, Dialog, JSON, config, win) {
var now = new Date();
var dialog = new Dialog({
id: "dialog",
// set a title on the dialog of today's date,
// using a localized date format
title: "Today: " + locale.format(now, {
formatLength:"full",
selector:"date"
})
}).placeAt(win.body());
dialog.startup();
dialog.set("content", "<pre>" + JSON.stringify(config, null, "\t") + "```");
dialog.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/date/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 theextraLocale
config property, with an array of string locale names.When using the
dojo/parser
, thelang=
setting on an ancestor DOMNode overrides thedojoConfig.locale
setting. This behavior will change in Dojo 2.0. You can also specify thelang
for individual widgets, overriding thedojoConfig.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 = {
has: {
"dojo-firebug": true
},
app: {
userName: "Anonymous"
}
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<script>
require(["dijit/Dialog", "dijit/registry", "dojo/parser", "dojo/_base/lang",
"dojo/json", "dojo/_base/config", "dojo/io-query", "dojo/domReady!"]
, function(Dialog, registry, parser, lang, JSON, config, ioQuery) {
// pull configuration from the query string
// and mix it into our app config
var queryParams = ioQuery.queryToObject(location.search.substring(1));
lang.mixin(config.app, queryParams);
// Create a dialog
var dialog = new Dialog({
title: "Welcome back " + config.app.userName,
content: "<pre>" + JSON.stringify(config, null, "\t") + "```"
});
// Draw on the app config to put up a personalized message
dialog.show();
});
</script>
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.