Dijit for Designers

The fundamentals for using an existing dijit in markup are quite simple: a dojoType tag specifies the type of dijit that should be placed in the page, attributes pass data into the widget upon creation, and extension points allow you to override existing widget behavior. While the dojoType tag is required, attributes usually are set to reasonable default values, and extension points always fall back to a reasonable implementation.

Tip

The difference between "methods" and "extension points" is purely a semantic one: methods are operations that the application programmer call directly to control a dijit. Extension points are methods that the application programmer does not call directly; the dijits calls them itself when an appropriate condition arises. For example, a widget might have an explicit method like setValue that could be called to programmatically adjust it, while a method like onKeyUp would be an extension point in that it gets called automatically each time a key is pressed.

There are several attributes, listed in Table 11-2, that are especially important to be aware of for out-of-the-box usage because these attributes are set directly on a widget's DOM Node. These attributes ultimately ensure that the dijit's underlying HTML markup is as customizable and "proper" as possible.

Table 11-2. Common dijit attributes

Attribute

Type

Comment

id

String

A unique identifier for the widget. By default, this value is automatically generated and guaranteed to be unique. If an explicit value is provided that is known already to be in use, the value is ignored, and a unique value is generated.

lang

String

The language to use for displaying the widget. The browser's locale settings are used by default. If an additional locale is desired, specify it via djConfig.extraLocale so the bundle will be available. (In general, this attribute is not used unless it's necessary to display multiple languages on a single page.)

dir

String

Bidirectional support as defined by the HTML DIR attribute. By default, this value is set to ltr (left to right) unless rtl is provided. No other values are valid.

style

String

HTML style attributes that should be passed into the widget's outermost DOM node. By default, no additional style attributes are passed.

title

String

The standard HTML title attribute that can be used for displaying tooltips when hovering over a dijit's DOM node.

class

String

CSS class information to apply to the outermost DOM node. This attribute is particularly useful for overriding all or part of a default theme.

Themes

A Dijit theme is a fully consistent collection of CSS rules that span across the entire set of widgets. To say that another way, you might think of Dijit as being skinnable, where a theme is a kind skin that you apply. If you need to pull some widgets off the shelf and put together something quickly, themes are especially good because CSS becomes one less thing that you have to worry about implementing. As of version 1.1, Dojo includes three great-looking, prepackaged themes:

Tundra

Predominantly light grey and light blue hues named after the Arctic landscape.

Soria

Predominantly blue on blue, both of which are fairly light hues. Controls have a noticeably glossy "Web 2.0 sheen" look to them. The inspiration for this theme was the beautiful blue sky from a set of photos from Soria, Spain.

Nihilo

Predominantly white with soft grey outlines with some greyish blue text. Some controls use a yellow shade to denote color. It is rumored that the inspiration for this theme is inspired from the ex nihilo concept (to create something out of nothing), with the goal of minimalist elegance—you barely notice it's there.

In your toolkit checkout, you can find a theme tester at dijit/themes/themeTester.html that demos the various dijits with a theme of your choice. Actually looking at the themes on your own screen is the best way to feel them out, as a black and white page can't really do them justice.

The structure of the themes directory has the following pattern, although each primary CSS file generally includes @import statements that pull in various other CSS files as part of a maintainable design (the build tools consolidate CSS files, so official builds only deliver the final file, which minimizes HTTP latency in fetching resources):

themes/
    tundra/
        tundra.css
        images/
            lots of static images
    soria/
        soria.css
        images/
            lots of static images
    nihilo/
        nihilo.css
            images/
                lots of static images
    <your custom theme could go here; just follow the pattern...>

Example 11-1 explicitly emphasizes the parts of the page that are pertinent to the theme.

Example 11-1. Using a theme

<html>
    <head>
        <title>Fun With the Themes!</title>

        <!-- pull in the tundra theme -->
        <link rel="stylesheet" type="text/css"
          href="http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css" />
        <link rel="stylesheet" type="text/css"
          href="http://o.aolcdn.com/dojo/1.1/dijit/themes/tundra/tundra.css" />

        <script
            type="text/javascript"
            src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
        ></script>

        <script type="text/javascript">
            //require your dijits here
        </script>
    <head>

    <body class="tundra">
        <!-- use your dijits here -->
    </body>
</html>

You'll notice that actually using a theme is as simple as pulling in a stylesheet and applying the appropriate class name to the BODY tag, although you could have applied the class name to a different tag on the page if you had a good reason not to style the entire page with a single theme. Themes are designed to be applied to any arbitrary page element, whether it is the entire page, a specific DIV section, or a particular widget. This listing also shows that the dojo.css file is also retrieved, which is generally assumed to be the case because it contains some baseline style.

Switching out the theme would be as simple as replacing all of the tundra references with either soria or nihilo. That's it. And that's also as easy as it should be to reskin the page.

We won't belabor the topic of themes because it's really just a system of well-engineered CSS rules, and while it absolutely and positively makes all of the difference to the credibility and desirability of Dijit, it just isn't a topic that lends itself well to the current discussion. If you're interested in themes, however, be sure to pick up a good reference on CSS and start reading through the various CSS files. You'll see definitions like .tundra .dojoButton { /* style goes here */ }, which are usually self-descriptive and easy to locate in Dijit template files or in the page if you are inspecting with Firebug.

Nodes Versus Dijits, DOM Events Versus Dijit Methods

Important distinctions must be made between a dijit versus a DOM node: a dijit is a JavaScript Function object that is instantiated from a collection of resources that may include HTML markup, CSS, JavaScript, and static resources like images; the dijit's visible manifestation is inserted into the page by assigning its domNode attribute (the outermost node in its template) into the page.

The distinction between a dijit and DOM node can be further highlighted by juxtaposing the dojo.byId function, which returns a DOM node given a string value, and Dijit's own dijit.byId, which returns the dijit that is associated with a particular DOM node. The differences are listed in Table 11-3. Using Firebug to execute the two commands on the following Button accentuates the differences:

<button id="foo" dojoType="dijit.form.Button">click me</button>

Table 11-3. Difference between dojo.byId and dijit.byId

Command

Firebug console result

dojo.byId("foo")

<button
    id="foo"
    class="dijitStretch
    dijitButtonNode
    dijitButtonContents"
    waistate="labelledby-foo_label"
    wairole="button"
    type="button"
    dojoattachpoint="focusNode,titleNode"
    role="wairole:button"
    labelledby="foo_label"
    tabindex="0"
    valuenow=""
    disabled="false">

dijit.byId("foo")

[Widget dijit.form.Button, foo] _connects=[4] _attaches=[0] id=foo

The dojo.byId command returns the DOM node that provides the visible manifestation of an instantiated dijit.form.Button, while the dijit.byId returns a JavaScript Function object that can be examined for all of the standard dijit machinery.

Warning

An incredibly common mistake is to try and run a method on the result of a dojo.byId command. Remember that DOM nodes do not have dijit-related methods.

The corollary to the distinction between a dijit and a DOM node is the analogous distinction between a Dijit event and a DOM event. While many dijits have an onClick event, this event is quite different from a DOM node's onclick event in spite of the obvious similarity in naming convention. Take a moment to load and run the following page in the Firebug console; the output highlights the crux of the matter:

<html>
    <head>
        <title>Fun with Button Clicking!</title>


        <link rel="stylesheet" type="text/css"
          href="http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css" />
        <link rel="stylesheet" type="text/css"
          href="http://o.aolcdn.com/dojo/1.1/dijit/themes/tundra/tundra.css" />

        <script
            djConfig="parseOnLoad:true"
            type="text/javascript"
            src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
        ></script>

        <script type="text/javascript">
            dojo.require("dojo.parser");
            dojo.require("dijit.form.Button");
            dojo.addOnLoad(function(  ) {
                dojo.connect(dojo.byId("foo"), "onclick", function(evt) {
                    console.log("connect fired for DOM Node onclick");
                });

                dojo.connect(dijit.byId("foo"), "onclick", function(evt) {
                    console.log("connect fired for dijit onclick");    //never!
                });

                dojo.connect(dijit.byId("foo"), "onClick", function(evt) {
                    console.log("connect fired for dijit onClick");
                });
            });
        </script>
    </head>
    <body class="tundra">
        <button id="foo" dojoType="dijit.form.Button" onclick="foo">click me
            <script type="dojo/method" event="onClick" args="evt">
                console.log("Button fired onClick");
            </script>
        </button>
    </body>
</html>

To summarize, this page defines a simple method in markup for a simple Button, provides an implementation for its onClick method, and defines three connections: one for the DOM node's onclick event, and connections for the dijit's onclick and onClick events. However, dijits do not have an onclick event, so the example demonstrates that the common mistake of trying to connect to it is a pitfall that can produce bugs that are quite hard to track down and fix.

Get Dojo: The Definitive Guide now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.