The Basics Widgets Ajax/DOM Debugging
HIDE ALL NOTES

Getting Dojo

Download

http://www.dojotoolkit.org/download/

CDN (Content Delivery Network)

Google CDN

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js"></script>

Notes

In the CDN tag above, line breaks may be automatically added due to formatting constraints. This tag should be written as a single line.

These examples are using Dojo 1.9.1.

Git

Dojo's full source is made up of several repositories: dojo, dijit, util, and dojox. They can be cloned from https://github.com/dojo/[repository].git:

git clone https://github.com/dojo/dojo.git

Configuring Dojo

Using dojoConfig

<script>
  var dojoConfig = {
    isDebug: true // default is false
  };
</script>

Notes

The dojoConfig object must exist before the script tag that loads dojo.js.

Using data-dojo-config

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

Notes

In the data-dojo-config example above, line breaks may be added automatically due to formatting constraints. This attribute should be written as a single line.

Loading Modules

AMD API

Using the AMD API

require([
  "dojo/query"
], function(query) {
  // use the query module here
  query(".items");
});

AMD Module Method Notation Conventions

Module Methods: "."

A method that is used directly from the exported module is indicated with a period.
e.g. dojo/dom.byId should be invoked directly on a reference to the dojo/dom module.

require([
  "dojo/dom"
], function(dom) {
  var node = dom.byId("nodeId");
});

Instance Methods: "#"

A method that is used on an instance object is indicated with the pound sign.
e.g. dojo/Stateful#watch should be invoked on an instance created from the dojo/Stateful module.

require([
  "dojo/Stateful"
], function(Stateful) {
  var statefulInstance = new Stateful();
  statefulInstance.watch("propertyName",
    handler);
});

Custom Packages/Namespaces

AMD Configuration

Using Custom Packages/Namespaces

require({
  packages: [
    {name: "package",
      location: "../package"}
  ]
});

Notes

Relative paths are relative to the baseUrl which, by default, is the directory containing dojo.js.

If a package is not registered, Dojo will assume the package directory is a sibling of the directory containing dojo.js. This behavior can be disabled by setting tlmSiblingOfDojo to false in the Dojo configuration object, in which case package directories will be assumed to be inside the baseUrl directory.

Page Ready Events

dojo/domReady! Loader Plugin

require(["dojo/domReady!"], function() {
  // Your code
});

Notes

dojo/domReady! will wait until the DOM has finished loading.

Finding DOM Nodes

dojo/dom - by DOM id

Using dojo/dom

require(["dojo/dom"], function(dom) {
  // fetch a node by id="node"
  var node = dom.byId("node");
});

dojo/query - by CSS Selector

Using dojo/query

require([
  "dojo/query",
  "dojo/domReady!"
], function(query) {
  query(".Class");
  query("p > a.external");
  query("tr:nth-child(odd)");
});

Effects

dojo/_base/fx

Using dojo/_base/fx

require([
  "dojo/_base/fx"
], function(fx) {
  fx.animateProperty({
    node:"someId",
    properties: {
      width: 300
    }
  }).play();
});

Notes

Remember to call the play function on the returned object for the animation to start.

AJAX

dojo/request/xhr

dojo/request options

handleAs ("text", "json", "javascript", "xml"), sync, preventCache, content, headers, timeout, user, password, load, error, handle, failOk

Using dojo/request

require([
  "dojo/request"
], function(request) {
  request("helloworld.txt").then(
    function(text) {
      console.log("Text: " + text);
    },
    function(error) {
      console.log("Error: " + error);
    }
  );
});

Manipulating DOM Nodes

dojo/dom-construct

Using dojo/dom-construct

require([
  "dojo/dom-construct"
], function(domConstruct) {
  var node1 =
    domConstruct.toDom(
      "<div>I'm a Node</div>");
  domConstruct.place(node1,
    "refNode", "after");
  var node2 =
    domConstruct.create("div");
  domConstruct.empty(node1);
  domConstruct.destroy(node2);
});

Notes

A string that parses into multiple nodes will cause a DocumentFragment to be returned.

DOM Attributes & Styles

dojo/dom-attr - attributes

Using dojo/dom-attr

require([
  "dojo/dom-attr"
], function(domAttr) {
  var res = domAttr.has(node, "attr");
  var attr = domAttr.get(node, "attr");
  domAttr.set(node, "attr", "value");
  domAttr.remove(node, "attr");
});

dojo/dom-style - styles

Using dojo/dom-style

require([
  "dojo/dom-style"
], function(domStyle) {
  var w = domStyle.get(node, "width");
  domStyle.set(node, "width", "100px");
});

Notes

If the CSS style property is hyphenated, the JavaScript property is camelCased.

dojo/dom-class - CSS classes

Using dojo/dom-class

require([
  "dojo/dom-class"
], function(domClass) {
  domClass.addClass("node", "class");
  domClass.toggleClass("node", "class");
  var result = domClass.contains("node",
    "class");
  domClass.removeClass("node", "class");
});

Notes

className can be a space-separated list of classes.

Event binding / AOP

dojo/on

dojo/on is a is a general-purpose event handler module for DOM nodes and other event emitting objects.

Using dojo/on

require([
  "dojo/on",
  "dojo/query"
], function(on) {
  on(trgtNode, "trgtEvt", function() {
    // handle the event
  });
});

Notes

If event delegation is used, remember to require dojo/query or it won’t work.

See dojo/Evented base class for objects that emit their own events.

dojo/aspect - Aspect Oriented Programming (AOP)

dojo/aspect provides AOP to attach additional functionality to existing methods.

Using dojo/aspect

define([
  "dojo/store/Memory",
  "dojo/aspect"
], function(Memory, aspect) {
  var someData = [
    {id:0, name:"Zero"},
    {id:1, name:"One"}];
  var store =
    new Memory({data:someData});
  aspect.before(store, "get",
    function(arg) {
      // this is called before
      // any get call
      console.log(
        "store.get(" + arg + ")");
    });
  // this will execute the
  // the advising function, then
  // the original get method
  store.get(1);
});

Notes

If you are connecting to DOM Events rather than regular JS objects and functions, use dojo/on rather than dojo/aspect.

Use lang.hitch to bind a different context to the listener function.

Available DOM events

The following properties are available for all events: target, currentTarget, pageX/Y, layerX/Y, fromElement, toElement, charCode, charOrCode.

Keyboard events have codes assigned by name to the event object (e.g. event.KEY_ESC) as well as a reverse lookup assigned to event.revKeys. dojo/keys provides a map of constants for which values.

Using Dijit Widgets

Dijit Widgets

Using Dijit Widgets

Programmatic

JavaScript

require([
  "dijit/Widget",
  "dojo/domReady!"
], function(Widget) {
  var myWidget =
    new Widget({prop: "value"});
  myWidget.placeAt(window.body());
  myWidget.startup();
});

Notes

Remember that you must manually call startup() after adding a widget to the page. The Dojo parser only does this for you automatically for declarative widgets.

Declarative

HTML

<div data-dojo-type="dijit/WidgetName"
  data-dojo-props="wdgtProp: 'value',
    othWdgtProp: 'otherValue'">
  Optional content</div>

JavaScript

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

Notes

Remember to require any widgets you create declaratively. The parser will auto-require modules, however it is recommended that all modules be explicitly required. If isDebug is true, warnings will be issued for modules referenced but not required.

Dijit Lifecycle

Dijit Widget Lifecycle

  1. constructor
  2. Properties are mixed into the widget instance
  3. postMixInProperties
  4. buildRendering
  5. setters are called
  6. postCreate
  7. startup (must be called manually for programmatic widgets!)

Dijit Themes

Dijit themes

Using Dijit themes

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet"
   href="dijit/themes/claro/claro.css">
</head>
<body class="claro">
</body>
</html>

Notes

Adding the "claro" class to an element, such as body, applies the theme to the element and its descendents.

Dijit themes are written in LESS and compiled to CSS. Commonly used variables (colors, etc.) are in dijit/themes/[themeName]/variables.less.

Creating Custom Widgets

Creating Custom Widgets

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

External template

define([
  "dojo/_base/declare",
  "dijit/_WidgetBase",
  "dijit/_TemplatedMixin",
  "dojo/text!./templates/TemplatedWidget.html"
], function(
  declare,
  _WidgetBase,
  _TemplatedMixin,
  template
) {
  return declare([_WidgetBase,
    _TemplatedMixin], {
    templateString: template
  });
});

Template node attributes

data-dojo-attach-point

Assigns the node as a property of the widget.

<!-- widget.labelNode will point to this node -->
<label data-dojo-attach-point="labelNode"></label>

data-dojo-attach-event

Connects widget functions as event handlers on the node.

<!-- clicking on this label will fire widget._onClick -->
<label data-dojo-attach-event="onclick: _onClick, onmouseover: _doThing"></label>

To include widgets in templates

Use _WidgetsInTemplateMixin.

Debugging

When debugging, set dojoConfig.isDebug to true. Then use console.log (not alert!) to output debugger statements.