Dojo 1.x to 2.0 migration guide

Currently, many parts of Dojo 2.0 are under development. As with any major software that is under-development, it is hard to predict that the final solution will look like. These notes provide guidence though on how to try to “future proof” your application to make it easier to transistion to Dojo 2.0 when it release.

Since Dojo 1.X is backwards compatible with previous Dojo 1.x releases, none of these changes are necessary until Dojo 2.0, but refactoring your code earlier will not only make future porting easier, but also can deliver performance and code maintenance benefits early.

AMD

Dojo has been upgraded to use the Asynronous Module Definition (AMD) standard for all of its modules. This changes the way you load, access, and define modules.

Loading dojo.js

Dojo is loaded basically in the same way as before, except that in the <script> tag the djConfig attribute has been renamed to data-dojo-config.

To get the 2.0-like behavior in 1.7, you should set async: true.

<script src="dojo/dojo.js" data-dojo-config="async: true"></script>

If configuration options are specified outside of the <script> tag (rather than as a data-dojo-config attribute), instead of djConfig you should set dojoConfig:

var dojoConfig = { async: true }

Loading Modules

The syntax for loading modules has been changed from a series of dojo.require() calls like:

dojo.require("dijit.form.Button");
dojo.require("dojox.layout.ContentPane");
...
// CODE HERE

into a single require statement:

require(["dijit/form/Button", "dojox/layout/ContentPane", ...], function(Button, ContentPane, ...){
  // CODE HERE
});

Notice how the dots (e.g. dijit.form.Button) have been changed to slashes (e.g. dijit/form/Button). This is dot notation represented a global scope object where as the slash notation represent a Module ID (MID). While these are similiar in naming, there are actually wholly different concepts.

Also, be careful to never load a module using a <script> tag. This will not work; it causes “multiply defined” errors from the loader.

Accessing Modules

Each module you load is mapped to a function parameter:

require(["dijit/_base/Color", "dojox/layout/ContentPane"], function(Color, ContentPane){
    Color.fromRgb(...)
});

That function parameter is the way that you access methods or the class defined in that module. You should no longer access any functionality through global variables like dojo, dijit, or dojox.

One implication of this change is that every module you are (directly) using must be put into your dependency list. That includes any functionality previously loaded by dojo.js. The modules that formerly composed dojo.js (modules in dojo/_base) have been replaced with smaller, more specific modules in the top level dojo directory.

Also, note that some method names have been shortened to avoid redundancy. For example, the previous dojo.colorFromRgb() is now accessed as Color.fromRgb(), rather than Color.colorFromRgb().

Defining Modules

The syntax for defining a module is similar to require(). In other words, it has been changed from:

dojo.provide("acme.Dialog");
dojo.require("dijit._Widget");
dojo.require("dojo.date");
//CODE HERE

into:

define(["dijit/_Widget", "dojo/date"], function(_Widget, date){   ....
  // CODE HERE
  return MyWidget;
});

Notice that the module (a.k.a. file) itself is returning a value. That is the way other modules access your module, as explained in the section above.

Also, notice how the module name previously listed in the dojo.provide() call (acme.Dialog in the example above) is not listed anymore. The file name itself suffices.

I18N

dojo.requireLocalization() has been replaced by the dojo/i18n! loader plugin:

Old syntax:

dojo.require("dojo.i18n");
dojo.requireLocalization("dijit.form", "validate");
var validate = dojo.i18n.getLocalization("dijit.form", "validate");
console.log(validate.invalidMessage);

New syntax:

require(["dojo/i18n!dijit/form/nls/validate"], function(i18n){
  console.log(i18n.invalidMessage);
});

Loading Text Resources and Widget Templates

Use the dojo/text! plugin instead.

Old syntax:

var text = dojo.cache("my.module", "template.html");
// ...

New syntax:

require("dojo/text!my/module/template.html", function(text){
  //...
});

URLs

Most of the time you use the dojo/text! plugin to load text from a specific URL, but if you need an actual URL in your classes you should use require.toUrl().

See require.toUrl() and context sensitive require for details.

Quick Reference

1.x syntax 2.0 module 2.0 syntax
dojo.provide(“foo/bar”); dojo.require(“a/b”); ...   define([“a/b”], function(b){ ... });
dojo.require(a.b); a.b.foo();   require([“a/b”], function(b){ b.foo(); }
djConfig   data-dojo-config
dojo._Url   require.toUrl()
dojo.moduleUrl(“dijit”, “foo.template.html”) require require.toUrl(“dijit/foo/template.html”)
dojo.requireLocalization() dojo/i18n! see I18N section above
dojo.getLocalization() dojo/i18n! see I18N section above
dojo.cache(“my.module”, “template.html”) dojo/text! require(“dojo/text!my/module/template.html”, function(text){ ...

Dojo Core

Basic functions

Testing object types

2.0 will remove the isXXX() functions defined in dojo/_base/lang. In most cases they can be easily replaced with simple native tests:

1.x 2.0
dojo.isString(v) typeof v == "string"
dojo.isArray(v) v instanceof Array
dojo.isFunction(v) typeof v == "function"
dojo.isArrayLike(v) "length" in v, etc. (but see note below)

Notes:

  • On some browsers "length" in v will return true for strings and functions, so if you are trying to differentiate between strings and arrays of strings, use the typeof v == "string" test instead, and if you are trying to differentiate between functions and arrays of functions, use the typeof v == "function" test instead. It will also return true for built-in constructors (Number, String, etc.) which have length.
  • typeof value == "function" won’t match IE’s hosted functions (like alert).
  • v instanceof Array won’t work if v was created in a different frame.

dojo/_base/lang

1.x syntax 2.0 module 2.0 syntax
dojo.extend dojo/_base/lang lang.extend
dojo._hitchArgs dojo/_base/lang lang._hitchArgs
dojo.hitch dojo/_base/lang lang.hitch
dojo.delegate dojo/_base/lang lang.delegate
dojo._toArray dojo/_base/lang lang._toArray
dojo.partial dojo/_base/lang lang.partial
dojo.clone dojo/_base/lang lang.clone
dojo.trim dojo/_base/lang lang.trim
dojo.replace dojo/_base/lang lang.replace
dojo.mixin dojo/_base/lang lang.mixin
dojo._mixin dojo/_base/lang lang._mixin
dojo.exists dojo/_base/lang lang.exists
dojo.getObject dojo/_base/lang lang.getObject
dojo.setObject dojo/_base/lang lang.setObject

dojo/_base/kernel

1.x syntax 2.0 module 2.0 syntax
dojo.deprecated dojo/_base/kernel kernel.deprecated
dojo.experimental dojo/_base/kernel kernel.experimental
dojo.version dojo/_base/kernel kernel.version
dojo.eval dojo/json native eval() or json.parse() for json

dojo/_base/array

To be determined - Dojo 2.0 may have dojo/array, or dojo/each, or just shim Array prototype on IE to match behavior of modern browsers.

In 1.7 and later, use “dojo/_base/array” module to get forEach(), map(), etc:

1.x syntax 2.0 module 2.0 syntax
dojo.forEach dojo/_base/array array.forEach
dojo.map dojo/_base/array array.map
dojo.filter dojo/_base/array array.filter
dojo.every dojo/_base/array array.every
dojo.some dojo/_base/array array.some
dojo.indexOf dojo/_base/array array.indexOf

Browser/Device Sniffing

If your code uses browser sniffing, you should load dojo/sniff or dojox/mobile/sniff. Both these modules leverage the dojo/has API for feature detection.

For example, old code like:

if(dojo.isIE < 6){
  // ...
}

should be changed to:

require(["dojo/has", "dojo/_base/sniff"], function(has){
  if(has("ie") < 6){
    // ...
  }
});

Load and Unload Handlers

Loading and unloading have been moved to dojo/ready and dojo/_base/unload:

1.x syntax 2.0 module 2.0 syntax
dojo.addOnLoad(f) dojo/ready ready(f)
dojo.ready(f) dojo/ready ready(f)
dojo.addOnUnload dojo/_base/unload unload.addOnUnload
dojo.addOnWindowUnload dojo/_base/unload unload.addOnWindowUnload

Events

dojo.connect() / dojo.disconnect() for monitoring DOMNode events have been replaced by the on() method returned from the dojo/on module. (For dojo.connect() usage as advice on plain JavaScript functions/methods, see the Advice section below)

Old code like:

var handle = dojo.connect(node, "onclick", callback);
// ...
dojo.disconnect(handle);

should be converted to:

require(["dojo/on"], function(on){
  var handle = on(node, "click", callback);
  // ...
  handle.remove();
});

Note that:

  • the on prefix was dropped, and onclick became click
  • the “handle” has a remove() method, rather than there being a function like dojo.disconnect()

The NodeList objects returned from dojo/query also works with an .on() method rather than a .connect() method.

Old code like:

dojo.query("li").connect("onclick", callback);

should be converted to:

require(["dojo/query"], function(query){
  query("li").on("click", callback);
});

mouseenter/mouseleave

Dojo supports onmouseenter/onmouseleave synthetically for browsers that do not support those events natively. In 1.x these events were specified as strings, just like native events:

dojo.connect(node, "onmouseenter", callback);

Now they are specified by event objects defined in dojo/mouse, which must be explicitly loaded, and used like this:

require(["dojo/on", "dojo/mouse"], function(on, mouse){
  on(node, mouse.enter, callback);
});

Similarly, "onmouseleave" has become mouse.leave.

Mouse Buttons

dojo.mouseButtons has been replaced by the dojo/mouse module, which must be explicitly loaded.

Code like:

dojo.connect(node, "onmousedown", function(evt){
  if(dojo.mouseButtons.isLeft(evt){ ... }
});

should be converted to:

require(["dojo/on", "dojo/mouse"], function(on, mouse){
  on(node, "mousedown", function(evt){
    if(mouse.isLeft(evt)){ ... }
  });
});

Keys

The symbolic names for keys have been put into the dojo/keys module, which must be explicitly loaded and can be accessed like this:

require(["dojo/on", "dojo/keys"], function(on, keys){
  on(node, "keydown", function(evt){
    if(evt.keyCode == keys.F10){ ... }
  });
});

onkeypress

The Dojo onkeypress normalization to Firefox behavior has been desupported. For portable applications, you must use keypress for monitoring printable characters (e.g. A-Z, 1-9):

on(node, "keypress", function(evt){
  if(e.charCode <= 32){
    // Avoid duplicate events on firefox (this is an arrow key etc. that will be handled by keydown handler)
    return;
  }
  var char = String.fromCharCode(evt.charCode);
  // ...
});

and keydown for non-printable characters (e.g. arrow keys):

on(node, "keydown", function(evt){
  switch(evt.keyCode){
   case keys.UP_ARROW:
      // ...
      break;
  }
});

Note that the normalization of evt.charOrCode is also gone, so use evt.charCode for keypress events, or evt.keyCode for keydown events.

Event Delegation

The dojo.behavior and dojox.NodeList.delegate modules have been replaced by functionality built-in to dojo/on.

Old code:

var myBehavior = {
  "#mylist li:click" : {
    onclick: onListItemClickHandler
  }
};
dojo.behavior.add(myBehavior);
dojo.behavior.apply();

New code:

require(["dojo/on", "dojo/query", "dojo/_base/window"], function(on, query, win){
  on(win.doc(), "#mylist li:click", onListItemClickHandler);
});

connectPublisher()

dojo.connectPublisher() was an automation of this common form:

dojo.connect(myObject, "myEvent", function(){
  dojo.publish("/some/topic/name", arguments);
});

Which became:

dojo.connectPublisher("/some/topic/name", myObject, "myEvent");

But in 2.0 users should use the following for connecting to DOM events:

require(["dojo/on", "dojo/topic"], function(on, topic){
  on(myNode, "click", function(){
    topic.publish("/some/topic/name", arg1, arg2, arg3);
  });
});

Or this for after-advice on arbitrary methods of arbitrary objects:

require(["dojo/aspect", "dojo/topic"], function(aspect, topic){
  aspect.after(myObj, "myFunc", function(){
    topic.publish("/some/topic/name", arg1, arg2, arg3);
  });
});

Quick Reference

1.x syntax 2.0 module 2.0 syntax
dojo.connect(node,"onclick",cb) dojo/on on(node,"click",cb) (note that "on" prefix removed)
dojo.connect(node,"onmouseenter",cb) dojo/on,dojo/mouse on(node,mouse.enter,cb)
dojo.connect(node,"onmouseleave",cb) dojo/on,dojo/mouse on(node,mouse.leave,cb)
dojo.connect(node,"onkeypress",cb) dojo/on on(node,"keypress",cb) for printable or on(node,"keydown",cb) for arrows etc.
dojo.disconnect(handle)   handle.remove()
dojo.connectPublisher   see above
dojo.fixEvent dojo/_base/event event.fix
dojo.stopEvent dojo/_base/event event.stop
dojo.mouseButtons.is***() dojo/mouse mouse.is***()
dojo.isCopyKey ? ?

Advice

dojo.connect() could be used to perform after advice (based on the conecpts of Aspect Oriented Programming) on a method. In 2.0 that has been replaced by the dojo/aspect package.

Old code:

var handle = dojo.connect(myInstance, "execute", callback);
// ...
dojo.disconnect(handle);

is changed to:

require(["dojo/aspect"], function(aspect){
  var handle = aspect.after(myInstance, "execute", callback);
  /  ...
  handle.remove();
});

Note that callback() should not return a value, because if it did the returned value would be reported as the value that myInstance.execute() appeared to return, which is not what dojo.connect() did.

Quick Reference

1.x syntax 2.0 module 2.0 syntax
dojo.connect(obj,method,cb) dojo/aspect aspect.after(obj,method,cb)
dojo.disconnect(handle)   handle.remove();

Publish and subscribe

dojo.publish()/dojo.subscribe()/dojo.unsubscribe() have been replaced by the dojo/topic module.

Old code:

var handle = dojo.subscribe("some/topic", context, callback);
// ...
dojo.unsubscribe(handle);

is changed to:

require(["dojo/topic"], function(topic){
  var handle = topic.subscribe("some/topic", listener)
  // ...
  handle.remove();
});

And publishing code is changed from:

dojo.publish("some/topic", [1, 2, 3]);

to:

require(["dojo/topic"], function(topic){
  topic.publish("some/topic", 1, 2, 3);
});

Note that no array brackets are used anymore.

Quick Reference

1.x syntax 2.0 module 2.0 syntax
dojo.publish("/foo", [1,2,3]) dojo/topic topic.publish("/foo", 1, 2, 3)
dojo.subscribe("/foo", callback) dojo/topic topic.subscribe("/foo", callback)
dojo.unsubscribe(handle)   handle.remove()

DOM Manipulation

The Dojo DOM related functions previously available as part of dojo/dojo.js are now in a number of modules which must each be explicitly loaded. These modules are:

Note in particular that node attribute setting and property setting has been split up. dojo/dom-attr will eventually be deprecated in lieu of dojo/dom-prop.

Note also that combination accessor functions like dojo.marginBox(), dojo.contentBox(), and dojo.style() have been split into separate setter and getter methods.

Quick Reference

1.x syntax 2.0 module 2.0 syntax
dojo.byId dojo/dom dom.byId
dojo.isDescendant dojo/dom dom.isDescendant
dojo.setSelectable dojo/dom dom.setSelectable
dojo.attr(node, attr) dojo/dom-attr attr.get(node, attr)
dojo.attr(node, attr, val) dojo/dom-attr attr.set(node, attr, val)
dojo.hasAttr dojo/dom-attr attr.has
dojo.removeAttr dojo/dom-attr attr.remove
dojo.addClass dojo/dom-class domClass.add
dojo.hasClass dojo/dom-class domClass.contains
dojo.removeClass dojo/dom-class domClass.remove
dojo.replaceClass dojo/dom-class domClass.replace
dojo.toggleClass dojo/dom-class domClass.toggle
dojo.toDom dojo/dom-construct construct.toDom
dojo.place dojo/dom-construct construct.place
dojo.create dojo/dom-construct construct.create
dojo.empty dojo/dom-construct construct.empty
dojo.destroy dojo/dom-construct construct.destroy
dojo.fieldToObject dojo/dom-form form.fieldToObject
dojo.formToObject dojo/dom-form form.toObject
dojo.formToQuery dojo/dom-form form.toQuery
dojo.formToJson dojo/dom-form form.toJson
dojo._getPadExtents dojo/dom-geometry geometry.getPadExtents
dojo._getBorderExtents dojo/dom-geometry geometry.getBorderExtents
dojo._getPadBorderExtents dojo/dom-geometry geometry.getPadBorderExtents
dojo._getMarginExtents dojo/dom-geometry geometry.getMarginExtents
dojo._getMarginSize dojo/dom-geometry geometry.getMarginSize
dojo._getMarginBox dojo/dom-geometry geometry.getMarginBox
dojo._setMarginBox dojo/dom-geometry geometry.setMarginBox
dojo.marginBox(node) dojo/dom-geometry geometry.getMarginBox(node)
dojo.marginBox(node,size) dojo/dom-geometry geometry.setMarginBox(node,size)
dojo._getContentBox dojo/dom-geometry geometry.getContentBox
dojo.setContentSize dojo/dom-geometry geometry.setContentSize
dojo.contentBox(node) dojo/dom-geometry geometry.getContentBox(node)
dojo.contentBox(node,size) dojo/dom-geometry geometry.setContentSize(node,size)
dojo.position dojo/dom-geometry geometry.position
dojo._isBodyLtr dojo/dom-geometry geometry.isBodyLtr
dojo._docScroll dojo/dom-geometry geometry.docScroll
dojo._getIeDocumentElementOffset dojo/dom-geometry geometry.getIeDocumentElementOffset
dojo._fixIeBiDiScrollLeft dojo/dom-geometry geometry.fixIeBiDiScrollLeft
dojo.style(node, attr) dojo/dom-style style.get(node, attr)
dojo.style(node, attr, val) dojo/dom-style style.set(node, attr, val)
dojo.style(node, hash) dojo/dom-style style.set(node, hash)
dojo.getComputedStyle dojo/dom-style style.getComputedStyle
dojo._toPixelValue dojo/dom-style style.toPixelValue
dojo.queryToObject dojo/io-query ioQuery.queryToObject
dojo.objectToQuery dojo/io-query ioQuery.objectToQuery

dojo/_base/window

1.x syntax 2.0 module 2.0 syntax
dojo.global dojo/_base/window window.global
dojo.doc dojo/_base/window window.doc
dojo.body dojo/_base/window window.body
dojo.setContext dojo/_base/window window.setContext
dojo.withGlobal dojo/_base/window window.withGlobal
dojo.withDoc dojo/_base/window window.withDoc

JSON

The JSON methods are available from the dojo/json package, which must be loaded explicitly.

1.x syntax 2.0 module 2.0 syntax
dojo.fromJson dojo/json json.parse
dojo.toJson dojo/json json.stringify

Note that the new methods only accept true JSON, not arbitrary JavaScript. Even the keys in a hash must be quoted

Valid:

{ "foo": 1, "bar": 2 }

Invalid:

{ foo: 1, bar: 2 }

TODO: IIRC single quotes are also invalid.

Parser

Running the Parser

The parser is in the dojo/parser module, invoked like:

require(["dojo/parser"], function(parser){
  parser.parse();
});

Even if you are parsing declaratively via the parseOnLoad: true dojoConfig setting, you need to explicitly require the parser.

data-dojo-type and data-dojo-props

dojoType has been renamed to data-dojo-type, and a new data-dojo-props parameter has been created to specify non-native attributes in a way that doesn't violate HTML5 validation.

Old code:

<button dojoType="dijit.form.Button" tabIndex=2
    iconClass="checkmark">OK</button>

New code:

<button data-dojo-type="dijit/form/Button" tabIndex=2
    data-dojo-props="iconClass: 'checkmark'">OK</button>

data-dojo-props is a hash that contains name value pairs, for example: data-dojo-props=" name: 'hi', size: 123" .

Connecting to Widget Events

Previously you could use <script type="dojo/connect"> to monitor widget events and connect to methods:

<button data-dojo-type="dijit.form.Button">
  <span>Click Me!</span>
  <script type="dojo/connect" event="onclick" args="e">
    // ...
  </script>
</button>

Now the following is used: <script type="dojo/on"> for events like click, <script type="dojo/watch"> to monitor changes to a widget's attribute:

<button data-dojo-type="dijit/form/Button">Click Me!
  <script type="dojo/on" data-dojo-event="click" data-dojo-args="e">
    // ...
  </script>
</button>
<div data-dojo-type="dijit/form/TextBox" id="textBox1"
    data-dojo-props="value: 'Old Value'">
  <script type="dojo/watch" data-dojo-prop="value" data-dojo-args="prop,oldValue,newValue">
    console.log("Prop '"+prop+"' was '"+oldValue+"' and is now '"+newValue+"'");
  </script>
</div>

jsId

The jsId attribute has been removed. Replace all jsId references with data-dojo-id, the behavior is identical.

<div data-dojo-id="bar" data-dojo-type="some/Thinger">I am exported to window.bar by reference</div>

Query

dojo/query is a new module similar to the old dojo.query() function. In general you can use it like dojo.query(), so old code like:

dojo.query("li").connect("onclick", callback)

can been replaced by:

require(["dojo/query"], function(query){
  query("li").on("click", callback);
});

Points of caution:

1. As before, you need to require certain NodeList extension modules to get added methods on the NodeList return from query(). The difference is that now the NodeList DOM functions also need to be explicitly loaded. So you need to do:

require(["dojo/query", "dojo/NodeList-dom"], function(query){
  query("li").style("display", "none");
});

2. query() can load various selector engines. By default it uses the dojo/selector/light engine. If you have complicated queries you need to switch it to use a more powerful engine. See dojo/query for details.

There are a couple of ways to set the selector engine. First, we can define the selector engine as part of the dojo configuration for the whole page:

<script data-dojo-config="selectorEngine='css2.1'" src="dojo/dojo.js"></script>

You can also specify the selector engine level you are dependent on for each of your modules. This is done by indicating the CSS selector engine level after ! in the dojo/query module id. For example, if your module needed to do a CSS3 level query, you could write:

define(["dojo/query!css3"], function(query){
  query(".someClass:last-child").style("color", "red");
});

Stores

The dojo.data API stores have been replaced with the new dojo/store API.

dojo.data dojo/store
store.getValue(item, "foo") item.foo
store.getLabel(item) item.label
store.getItemByIdentitfier(id) store.byId(id) returns Deferred
store.fetch(...) store.query() returns Deferred

In order to aid transistion, there are two modules that are available:

  • dojo/store/DataStore - Can convert a legacy dojo.data API store and make it appear to be a native dojo/store.
  • dojo.data.ObjectStore - Wraps a dojo/store API store and makes it appear to be a legacy dojo.data store.

Many Dijits are now directly dojo/store aware, including: dijit/form/ComboBox, dijit/form/FilteringSelect, and dijit/Tree.

Declaring Classes

dojo.declare() has been migrated to dojo/_base/declare. There may be further changes for Dojo 2.0, for example replacing it by ComposeJS, or may have more modest changes. For now, for classes you don't need in the global scope, you should declare them as baseless. Something like this:

dojo.provide("package.myClass");
dojo.require("dijit._Widget");
dojo.declare("package.myWidget", [dijit._Widget], {
  // myWidget Class declaration
});

Should change to something like this:

define(["dojo/_base/declare", "dijit/_WidgetBase"],
function(declare, _WidgetBase){
  return declare([_WidgetBase], {
    // myWidget Class declaration
  });
});

Notice the omission of the first argument in the declare(). This means that nothing will be set in the global scope. Also, the mixin array uses the return values of the define requirement array, instead of the legacy class names. This means that your custom class will only be available within the closure scope of a require() or define() that has required it in.

This does mean your module can only return a single public class, which is more consistent with the concepts of AMD and baseless anyways, but if you need to create a private class that isn't referenced outside the current module, you can simply declare it as a variable. For example:

define(["dojo/_base/declare", "dijit/_WidgetBase"],
function(declare, _WidgetBase){
  var _myMixin = declare(null, {
    // _myMixin Class private declaration
  });

  return declare([_WidgetBase, _myMixin], {
    // myWidget Class
  });
});

FX

The base FX features of dojo/dojo.js have been moved to dojo/_base/fx and the additional features of the dojo.fx module are now in dojo/fx.

1.x syntax 2.0 module 2.0 syntax
dojo._Line dojo/_base/fx baseFx._Line
dojo.Animation dojo/_base/fx baseFx.Animation
dojo._fade dojo/_base/fx baseFx._fade
dojo.fadeIn dojo/_base/fx baseFx.fadeIn
dojo.fadeOut dojo/_base/fx baseFx.fadeOut
dojo._defaultEasing dojo/_base/fx baseFx._defaultEasing
dojo.animateProperty dojo/_base/fx baseFx.animateProperty
dojo.anim dojo/_base/fx baseFx.anim

Miscellaneous

1.x syntax 2.0 module 2.0 syntax
dojo.window dojo/window window
dojo.Color dojo/_base/Color Color
dojo.cookie dojo/cookie cookie
dojo.date.locale dojo/date/locale  
dojo.date.stamp dojo/date/stamp  
dojo.date dojo/date  
dojo.dnd.* dojo/dnd/*  
dojo.hash dojo/hash hash
dojo.html dojo/html html
dojo.currency dojo/currency currency
dojo.number dojo/number number
dojo.string dojo/string string
dojo.Stateful dojo/Stateful Stateful
dojo.window.* dojo/window window.*
dojo.config dojo/_base/config config

Dijit

Mapping table for dijit

This is a quick lookup table for methods, attributes, etc. in 1.x mapped to their equivalent method in that module in 2.0. Note that many methods that were previously included automatically now need to be explicitly loaded.

The sections underneath this give more detail on conversions.

1.x syntax 2.0 module 2.0 syntax
dijit.hasDefaultTabStop dijit/a11y a11y.hasDefaultTabStop
dijit.isTabNavigable dijit/a11y a11y.isTabNavigable
dijit._getTabNavigable dijit/a11y a11y._getTabNavigable
dijit.getFirstInTabbingOrder dijit/a11y a11y.getFirstInTabbingOrder
dijit.getLastInTabbingOrder dijit/a11y a11y.getLastInTabbingOrder
dijit.byId dijit/registry registry.byId
dijit.byNode dijit/registry registry.byNode
dijit.registry.toArray dijit/registry registry.toArray
dijit.registry.forEach() dijit/registry array.forEach(registry.toArray(), ...)
dijit.registry.filter() dijit/registry array.filter(registry.toArray(), ...)
dijit.registry.map() dijit/registry array.map(registry.toArray(), ...)
dijit.registry.every() dijit/registry array.every(registry.toArray(), ...)
dijit.registry.some() dijit/registry array.some(registry.toArray(), ...)
dijit.registry.byClass("dijit.form.Button") dijit/registry array.filter(registry.toArray(), function(widget){ return widget.constructor === require("dijit/form/Button"); })
dijit.findWidgets dijit/registry registry.findWidgets
dijit.getEnclosingWidget dijit/registry registry.getEnclosingWidget
dijit.focus dijit/focus focus.focus
dijit.registerWin dijit/focus focus.registerIframe
dijit._curNode dijit/focus focus.curNode
dijit.getFocus() dijit/focus focus.curNode (points to node not hash)
dijit._activeState dijit/focus focus.activeStack
dojo.require("dijit.sniff") dojo/uacss require dojo/uacss instead
dojo.subscribe("focusNode",cb) dijit/focus focus.watch("curNode",cb)
dojo.subscribe("widgetBlur",cb) dijit/focus focus.on("widget-blur",cb)
dojo.subscribe("widgetFocus",cb) dijit/focus focus.on("widget-focus",cb)
dijit.getViewport dojo/window window.getBox
dijit.placeOnScreen dijit/place:place.at  
dijit.placeOnScreenAroundElement(n,an,{BL: "TL" dijit/place place.around(n,an,["before","after"])
dijit.typematic dijit/typematic typematic
dijit.popup.open({orient:{BL: "TL",...}) dijit/popup popup.open({orient:["before","after"]})
dijit.hasWaiRole(node, role)   node.getAttribute("role")==role
dijit.getWaiRole(node)   node.getAttribute("role")
dijit.setWaiRole(node, role)   node.setAttribute("role", role)
dijit.removeWaiRole   node.setAttribute(role, "")
dijit.hasWaiState("selected")   node.hasAttribute("aria-selected")
dijit.getWaiState("describedby")   node.getAttribute("aria-describedby")
dijit.setWaiState("describedby", desc)   node.getAttribute("aria-describedby", desc)
dijit.removeWaiState("selected")   node.removeAttribute("aria-selected")
dijit.layout.marginBox2contentBox dijit/layout/utils utils.marginBox2contentBox
dijit.layout.layoutChildren dijit/layout/utils utils.layoutChildren
dojo.connect(myWidget, "onClick", cb)   myWidget.on("click", cb)
dojo.connect(myWidget, "onChange", cb)   myWidget.watch("value", function(name, o, n){...})
myWidget.setAttribute(name,val)   myWidget.set(name,val)
myWidget.attr(name)   myWidget.get(name)
myWidget.attr(name,val)   myWidget.set(name,val)
myWidget.attr(hash)   myWidget.set(hash)
myWidget.getDescendants   myWidget.getChildren
myWidget.setDisabled(bool)   myWidget.set("disabled", bool)
myWidget.setValue(val)   myWidget.set("value", val)
myWidget.getValue()   myWidget.get("value")
myWidget.getDisplayedValue()   myWidget.get("displayedValue")
myWidget.setDisplayedValue(val)   myWidget.set("displayedValue", val)
myWidget.setLabel(label)   myWidget.set("label", label)
myWidget.setChecked(val)   myWidget.set("checked", val)
myWidget.setHref()   myWidget.set("href", ...)
myWidget.setContent()   myWidget.set("content", ...)
dojo.connect(myCalendar, "onValueSelected", ...)   myCalendar.watch("value", ...)
Editor.focusOnLoad dijit/Editor perform manually
Editor.blur() dijit/Editor focus something else
dijit._editor.escapeXml() dijit/_editor/html html.escapeXml()
Editor.getNodeHtml() dijit/_editor/html html._getNodeHtml()
Editor.getNodeChildrenHtml() dijit/_editor/html html.getNodeChildrenHtml()
ProgressBar.progress dijit/ProgressBar ProgressBar.value
ProgressBar._setIndeterminateAttr(true) dijit/ProgressBar ProgressBar.set("value", Infinity)
ProgressBar._setIndeterminateAttr(false) dijit/ProgressBar ProgressBar.set("value", 123)
TitlePane.setTitle(title) dijit/TitlePane TitlePane.set("title", title)
Tooltip.addTarget() dijit/Tooltip Tooltip.set("connectId", ...)
Tooltip.removeTarget() dijit/Tooltip Tooltip.set("connectId", ...)
Tree.store dijit/Tree specify Tree.model instead
Tree.query dijit/Tree pass query to Tree.model instead
Tree.label dijit/Tree pass label to ForestStoreModel instead
Tree.childrenAttr dijit/Tree pass to model
Tree.mayHaveChildren dijit/Tree specify on model
Tree.getItemChildren dijit/Tree specify on model
_KeyNavContainer.startupKeyNavChildren dijit/_KeyNavContainer remove call to method
Form.execute dijit/form/Form Form.submit
Form.getValues() dijit/form/Form Form.get("value")
Form.setValues(val) dijit/form/Form Form.set("value", val)
Form.isValid() dijit/form/Form Form.get("state")
dijit._setSelectionRange dijit/form/_TextBoxMixin _TextBoxMixin._setSelectionRange
dojo.connect(myForm, "onValidStateChange", cb) dijit/form/Form myForm.watch("state", function(name, o, n){...})
dijit._Widget replaced widgets use dijit/_WidgetBase
dijit._Templated replaced widgets use dijit/_TemplatedMixin, dijit/_WidgetsInTemplate instead
dijit.form.Slider replaced widgets use dijit/form/HorizontalSlider, VerticalSlider, etc.
dijit.layout.LayoutContainer replaced widgets use dijit/layout/BorderContainer
dijit.layout.SplitContainer replaced widgets use dijit/layout/BorderContainer
dijit._Calendar replaced widgets use dijit/Calendar
dijit.layout.AccordionPane replaced widgets use dijit/layout/ContentPane
layoutAlign="top" widget parameters region="top"
dojoAttachPoint templates data-dojo-attach-point
dojoAttachEvent templates data-dojo-attach-event
waiRole="button" templates role="button"
waiState="selected-false,haspopup-true" templates aria-selected="false" aria-haspopup="true"
attributeMap:{foo:a,bar:b} widget definitions _setFooAttr:a,_setBarAttr:b
this._focused widget definitions this.focused

set(), get()

Old widget methods to set and get parameter values, such as:

myEditor.getValue()
myTextBox.attr("value")
myForm.setValue(...);

have been replaced by the standard set() and get() methods:

myEditor.get("value")
myTextBox.get("value")
myForm.set("value", ...);

watch(), on()

Old widget methods to monitor widget events or changes in widget parameters have been consolidated to use on() and watch():

Old code:

dojo.connect(myForm, "onValidStateChange", function(){ ... });
dojo.connect(myButton, "onClick", clickCallback);

New code:

myForm.watch("valid", function(name, oldVal, newVal){
  console.log(myForm.id + ": " + name + " changed from " +
  oldVal + " to " + newVal);
});
myButton.on("click", clickCallback);

Templated Widgets

The dijit/_Templated mixin has been split into dijit/_TemplatedMixin and dijit/_WidgetsInTemplateMixin. In addition, dojoAttachPoint and dojoAttachEvent have been changed to the HTML5 valid data-dojo-attach-point and data-dojo-attach-event.

For example, old code like:

dojo.require("dojo.declare");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare("SimpleTemplate", [dijit._Widget, dijit._Templated], {
  templateString: "<button><span dojoAttachPoint="label"></span></button>"
});

will change to:

require(["dojo/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin"],
function(declare, _WidgetBase, _TemplatedMixin){
  declare("SimpleTemplate", [_WidgetBase, _TemplatedMixin], {
    templateString: "<button><span data-dojo-attach-point="label"></span></button>"
  });
});

If the above example had widgets in the templates, it would also mixin dijit/_WidgetsInTemplateMixin.

To specify a template from a file, templatePath is no longer supported, and dojo.cache() shouldn't be used either.

Old code:

templatePath: dojo.moduleUrl("templates", "myTemplate.html")

New code:

define([..., "dojo/text!./templates/myTemplate.html",
function(..., myTemplate){
  ...
  templateString: myTemplate

The other change to widgets is that the waiRole and waiState parameters are no longer supported, since it's now easy to use role and state directly.

For instance. Replace:

<span waiRole="treeitem" waiState="selected-false,haspopup-true"></span>

With:

<span role="treeitem" aria-selected="false" aria-haspopup="true"></span>

attributeMap

attributeMap in 1.x was a hash mapping widget attributes to DOM nodes. For example:

attributeMap: {
  "index": "focusNode",
  "style": "domNode"
}

Currently, this is achieved by making separate _setXXXAttr attribute for each attribute to map. Originally _setXXXAttr was a function to set a widget attribute. It can still be a function, but now it can also be an object like one of the values from attributeMap.

The code above would be expressed as:

_setTabIndexAttr: "focusNode",
_setStyleAttr: "domNode"

Base Functionality

The methods previously loaded into dijit by default now must be explicitly loaded from various modules.

TODO: list stuff in dijit/registry, dijit/a11y.

dijit/focus, dijit/place, and dijit/popup

The focus, place, and popup modules in dijit/_base have been promoted to root of dijit, so they need included explicitly by applications that don't want to include all of dijit/_base.

There are a few API changes in the top level modules compared to the ones in dijit/_base (although for backwards compatibility the modules in dijit/_base maintain their old API):

  • Popup.around() (analogous to dijit.popup.placeAroundElement()) takes a position parameter like ["before", "after"] rather than a set of tuples like {BL: "TL", ...}. In other words, Popup.around() replaces dijit.popup.placeAroundElement() but instead of dijit.getPopupAroundAlignment(xyz), just pass in xzy directly.
  • dijit/focus doesn't include the selection related code, just focus related code
  • dijit/focus provides .watch() and .on() methods to monitor the focused node and active widgets, rather than publishing topics focusNode, widgetBlur, and widgetFocus.
  • Some methods in dijit/_base/popup used to take DOMNodes or widgets as a parameter; now they just take a widget

Also note that the new dijit/popup module is only available through the new AMD API, e.g.:

require(["dijit/popup"], function(popup){ popup.open(...); });

Some functions from dijit have been moved to dojo core.

  • dojo/uacss will add classes to the <html> node like dj_ie, representing the browser, browser version, box model, etc. Formerly dojo.require("dijit.sniff").
  • getBox() from dojo/window gets the viewport size. Formerly dijit.getViewport().
  • get() from dojo/window converts a document to the corresponding window. Formerly dijit.getDocumentWindow()
  • scrollIntoView() from dojo/window scrolls a node into view, similar to node.scrollIntoView() but working around browser quirks. Formerly dijit.scrollIntoView().

Editor

New way of registering plugins: TODO

SplitContainer, LayoutContainer

Use BorderContainer instead. (TODO: examples)

Miscellaneous changes

_Widget --> _WidgetBase

DojoX

The dojox namespace will be removed in Dojo 2.0. Some of the mature sub-packages will like migrate into Dojo Core or into Dijit. The remaining code will be "spun off" into seperate packages that will be available via package management tools and a repository of packages.

In order to ensure your code is easily migrateable, refactoring it to fully leverage AMD and not relay upon the dojox global variable is critically important.

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