Basic Dijit Knowledge in Dojo

Exclusive offer: get 50% off this eBook here
Learning Dojo

Learning Dojo — Save 50%

A practical, comprehensive tutorial to building beautiful, scalable interactive interfaces for your Web 2.0 applications with Dijits

$20.99    $10.50
by Peter Svensson | December 2008 | AJAX Open Source

In this article by Peter Svensson, we will have a look at Dijit or Dojo Widget which is an instance of a Dojo class that lives in the page and usually has a DOM node associated with it. Examples are FloatingPane, Tree, NumberSpinner, and ValidationtextBox.

The basic premise of a Dijit is that you should be able to create any number of widgets of the same type on the same page, regardless of where on the page you choose to put them. Certain Dijits have special requirements, naturally, such as the Layout Containers, which assume that they are surrounding ContentPane Dijits.

In general, Dijits are very versatile and much time has been spent to assure portability and modularization of the Dijit system. Best of all, this is accessible to you as a developer as well.

All Dijits can be subclassed to change parts of their behavior, and then used as the original Dijits, or you can create your own Dijits from scratch and include existing Dijits (Forms, buttons, calendars, and so on) in a hierarchical manner.

All Dijits can be created in either of the following two ways:

  • Using the dojoType markup property inside selected tags in the HTML page.
  • Programmatic creation inside any JavaScript.

For instance, if you want to have a ColorPalette in your page, you can write the following:

<div dojoType="dijit.ColorPalette"></div>

But you also need to load the required Dojo packages, which consist of the ColorPalette and any other things it needs. This is generally done in a script statement in the <head> part of the HTML page, along with any CSS resources and the djConfig declaration. So a complete example would look like this:

<html>
<head>
<title>ColorPalette</title>
<style>
@import "dojo-1.1b1/dojo/resources/dojo.css";
@import "dojo-1.1b1/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript">
djConfig=
{
parseOnLoad: true
}
</script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="dojo-1.1b1/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.ColorPalette");
</script>
</head>
<body class=”tundra”>
<div dojoType="dijit.ColorPalette"></div>
</body>
</html>

Obviously, this shows a simple color palette, which can be told to call a function when a choice has been made. But if we start from the top, I've chosen to include two CSS files in the <style> tag.

The first one, dojo.css, is a reset.css, which gives lists, table elements, and various other things their defaults. The file itself is quite small and well commented.

The second file is called tundra.css and is a wrapper around lots of other stylesheets; some are generic for the theme it represents, but most are specific for widgets or widget families.

The two ways to create Dijits

So putting a Dojo widget in your page is very simple. If you would want the ColorPalette dynamically in a script instead, remove the highlighted line just before the closing body tag and instead write the following:

<script>
new dijit.ColorPalette({}, dojo.byId('myPalette'));
</script>

This seems fairly easy, but what's up with the empty object literal ( {} ) as the first argument? Well, as some Dijits take few arguments and others more, all arguments to a Dijit get stuffed into the first argument and the others, the last argument is (if needed) the DOM node which the Dijit shall replace with its own content somewhere in the page.

The default is, for all Dijits, that if we only give one argument to the constructor, this will be taken as the DOM node where the Dijit is to be created.

Let's see how to create a more complex Dijit in our page, a NumberSpinner. This will create a NumberSpinner that is set at the value '200' and which has '500' as a maximum, showing no decimals. To create this NumberSpinner dynamically, we would write the following:

<input type="text" name="date1" value="2008-12-30"  
dojoType="dijit.form.DateTextBox"/>

One rather peculiar feature of markup-instantiation of Dijits is that you can use almost any kind of tag for the Dijit.

The Dijit will replace the element with its own template when it is initialized. Certain Dijits work in a more complicated fashion and do not replace child nodes of the element where they're defined, but wrap them instead.

However, each Dijit has support for template HTML which will be inserted, with variable substitutions whenever that Dijit is put in the page. This is a very powerful feature, since when you start creating your own widgets, you will have an excellent system in place already which constrains where things will be put and how they are called.

This means that when you finish your super-complicated graph drawing widget and your client or boss wants three more just like it on the same page, you just slap up three more tags which have the dojoType defining your widget.

How do I find my widget?

You already know that you can use dojo.byId('foo') as a shorter version of document.getElementById('foo'). If you still think that dojo.byId is too long, you can create a shorthand function like this:

var $ = dojo.byId;

And then use $('foo') instead of dojo.byId for simple DOM node lookup.

But Dijits also seem to have an id. Are those the same as the ids of the DOM node they reside in or what? Well, the answer is both yes and no.

All created Dijit widgets have a unique id. That id can be the same string as the id that defines the DOM node where they're created, but it doesn't have to be.

Suppose that you create a Dijit like this:

<div id='foo' dojoType='dijit._Calendar'></div>

The created Dijit will have the same Dijit id as the id of the DOM node it was created in, because no others were given. But can you define another id for the widget than for its DOM node? Sure thing. There's a magic attribute called widgetId. So we could do the following:

<div id='foo' dojoType='dijit._Calendar' widgetId='bar'></div>

This would give the widget the id of 'bar'.

But, really, what is the point? Why would we care the widget / Dijit has some kind of obscure id? All we really need is the DOM node, right? Not at all. Sure, you might want to reach out and do bad things to the DOM node of a widget, but that object will not be the widget and have none of its functions.

If you want to grab hold of a widget instance after it is created, you need to know its widget id, so you can call the functions defined in the widget. So it's almost its entire reason to exist!

So how do I get hold of a widget obejct now that I have its id? By using dijit.byId(). These two functions look pretty similar, so here is a clear and easy to find (when browsing the book) explanation:

  • dojo.byId(): Returns the DOM node for the given id.
  • dijit.byId(): Returns the widget object for the given widget id.

Just one more thing. What happens if we create a widget and don't give either a DOM or widget id? Does the created widget still get an id? How do we get at it?

Yes, the widget will get a generated id, if we write the following:

<div dojoType='dijit._Calendar'></div>

The widget will get a widget id like this: dijit__Calendar_0. The id will be the string of the file or namespace path down to the .js file which declares the widget, with / exchanged to _, and with a static widget counter attached to the end.

What's in the fridge? A smorgasbord of tasty Dijits

Most Dijits reside under the dijit subdirectory of your Dojo installation. Some reside under dojox, though, because they are in beta, or recently contributed to Dojo and not yet completely tested. Here is a fairly thorough list (for Dojo 1.1.0) that you can use as an inspiring starting point:

Learning Dojo A practical, comprehensive tutorial to building beautiful, scalable interactive interfaces for your Web 2.0 applications with Dijits
Published: November 2008
eBook Price: $20.99
Book Price: $34.99
See more
Select your format and quantity:

Dijit

Comment

dijit.ColorPalette

 

A simple color picker. For more advanced use, I recommend the recently introduced dojox.ColorPicker, mentioned further down.

dijit.Dialog

 

A modal dialog widget which is initially hidden, together with its content. Will "dim" the rest of the screen when shown.

dijit.Editor

 

An advanced editor, which sports a large toolbar support indents, lists, fonts, and more. It can return its content as either HTML or text.

diit.InlineEditBox

 

The famous inline editing widget. Only shows a small editing area for parts of a text when called for, otherwise hides.

dijit.Menu

 

Normally used as either a vertical or horizontal pop-up contextual menu, but can also be used "statically", i.e. shown all the time, where you please.

dijit.ProgressBar

 

A progress bar which can be updated in increments or played as an animation until stopped. Good for Ajax calls, etc.

dijit.TitlePane

 

Is a pane which can be collapsed (except for the title bar) either by a button on the title bar or programatically. It is similar to the AccordionContainer layout manager, except that it only manages one pane.

dijit.ToolBar

 

The same toolbar that the editor uses. Great when you're developing desktop-like web applications. Great for drop-down menus, buttons, or ComboBoxes

dijit.ToolTip

A classical tooltip that displays a hovering box of content on a mouseover event, for any element. Can contain arbitrary content and even lazily load content from a url.

Dijit.Tree

 

A tree that uses the dojo.data data model to build a collapsible tree which can be configured to call a function when any element in the tree is clicked.

dijit.form.Form

 

A very useful form wrapper which can override default actions and serialize all elements as an associative array, among other things

dijit.form.Button

 

Contains the variants Button, DropDownButton, and ComboButton which provide a nice-looking Button widget, and two variations of a Button containing a Menu.

dijit.form.CheckBox

 

Contains Dojo styled versions of Radio button and CheckBox. Also provides a ToggleButton, a Button element which can be set or unset (pressed in or not).

dijit.form.CurrencyTextBox, DateTextBox, NumberTextBox and TimeTextBox

 

These variations of the classic INPUT text tag, provide specialized input dialogs (for date and time selection) and specific constraints for string, time, date, and monetary input values. This means that they will give user feedback that the number was out of range, for example.

dijit.FilteringSelect

 

 

Is a SELECT tag which can be populated dynamically and is dojo.data enabled, so that it can be configured using Ajax from a url on the server

dijit.MultiSelect

 

 

A variant of FilteringSelect which can accept multiple choices

dijit.TextArea, dijit.SimpleTextArea

 

TextArea wraps the tag with the same name providing resizing for the text contained, whereas SimpleTextArea stays the same size.

dijit.Slider, dijit.Spinner

 

Two Dijits which allow either dragging a marker (Slider) or using up/down buttons (Spinner) to enter numeric values.

dijit.layout.ContentPane

 

Basic layout tile for other content, for the Container classes. It is usually recommended to set its title property, which is used in various containers, when presenting the Pane as minimized.

dijit.layout.AccordionContainer

 

Orders a number of ContentPanes so that only one is visible at a time, with the others shown minimized. It uses an easing motion to switch between ContentPanes.

dijit.layout.BorderContainer

 

Orders the ContentPanes it surrounds according to tag properties set on them, like region="left", "top", etc.

dijit.layout.TabContainer

 

Orders the ContentPanes it surrounds into Tabs, where each Tab presents the title property of each ContentPane. Pressing the tab icon reveals the corresponding ContentPane and hides the others.

dijit.layout.StackContainer

 

Works just like the tabContainer, but shows no tabs. Instead which ContentPane is displayed is controlled programmatically.

Dojox.Grid

 

A highly configurable table component with sorting, summary rows, custom rendering and sorting, and cell editors. Uses dojo.data for reading and writing (on cell editor changes) to and from the server. Can be found in a "data-free" version called Virtual grid which can be populated independently.

dojox.layout.DragPane

 

Makes its content draggable back and forth, bringing in different parts if larger than the pane.

dojox.layout.ExpandoPane

 

Works like a ContentPane, but can be expanded or contracted just like a TitlePane.

dojox.layout.FloatingPane

 

A non-modal floating window. Can sport buttons like minimize, maximize, and/or close. Can be dragged around, resized, and minimized to provide a default generated docking element. Good for jaw-dropping effects. Head-smackingly simple to use.

dojox.layout.RadioGroup

 

Works like TabContainer, except it uses onmouseover sensitive buttons to wipe in and out different ContentPanes.

dojox.layout.ResizeHandle

 

Really useful little widget. Takes a DOM node as the property to which it attaches itself and provides resizability. Nice.

dojox.layout.ScrollPane

 

Organizes all the elements it surrounds and creates horizontal or vertical stripes which roll the elements back or forth in the viewport, depending on which side of the ScrollPane the mouse is over. Reminiscent of an analog sliding scale.

dojox.widget.ColorPicker

 

This is a classical high-resolution color picker, in the vein of Photoshop. If you need rgb values with saturation, hue, etc., this is for you.

dojox.widget.FileInput

A widget which wraps the input type="file" chooser, and can send the file asynchronously with Ajax, without disturbing the loaded page.

dojox.widget.FisheyeLite

Creates a horizontal or vertical "fisheye lens" effect much like the Mac's program bar. As the mouse pointer gets closer to an element, its size increases, and then decreases again as it leaves the element.

dojox.widget.Loader

 

A discrete widget that listens to global xhr (Ajax) events and provides feedback if there are outstanding requests from the server. Is used in an example to change the mouse pointer when "loading".

dojox.widget.MultiComboBox

 

Accepts multiple values with Ajax-enabled drop-down choice list for each.

dojox.widget.Rating

 

You've been looking for this. Seriously. It shows stars that can be grayed out or starred depending on where the user clicks. Think about amazon.com. Choices are sent to the url of choice in big Ajax style.

dojox.widget.SortList

 

A simple alternative to the Grid, if all you want to do is to list elements in a sorted order.

dojox.widget.Toaster

 

The Toaster slides in its contents from either of the screens four sides. Useful for shopping-carts or menu-like effects.

dojox.widget.Wizard

 

A variation on the StackContainer theme, where a user is presented a series of choices, with buttons advancing to the next "screen" in the wizard each time.

 

 

Learning Dojo A practical, comprehensive tutorial to building beautiful, scalable interactive interfaces for your Web 2.0 applications with Dijits
Published: November 2008
eBook Price: $20.99
Book Price: $34.99
See more
Select your format and quantity:

Dijit structure

The Dijit string listed in the first row can be used in a dojo.require(""); statement. At times, several Dijits are provided in one requirement. Some Dijits have been left out, considered to be superfluous or of minor importance.

This is only a list of Dijits, though. There are quite a lot of other components that live in the page.

Also, several components (not only Tree and Grid, but also ComboBox and SortableList, among others) can consume data stores.

The most basic definition of a Dijit is that it is a Dojo class which is associated with a certain DOM element in a web page. It is, in any other aspects, a regular Dojo class. The _Widget base class (that is the ultimate root class of all Dijits) does add a number of extra handle properties and functions to all Dijits, such as the variable domNode which refers to the DOM node which the Dijit is associated with.

All Dijits also have a lifecycle where Dojo ensures that certain functions on the Dijit are called at various times. There is, for example, one function that will be called before the Dijit is actually displayed and another one, which is called before any child Dijits are created, and so on.

Lifecycle

Regardless of whether a widget gets instantiated by the parser searching the page (or parts of it) for widgets to create, or by you creating it programmatically, certain functions get called at certain times.

In the base widget class dijit._Widget, we see the following comments:

create: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
//summary:
//Kick off the lifecycle of a widget
//description:
//To understand the process by which widgets are instantiated, it
//is critical to understand what other methods create calls and
//which of them you'll want to override. Of course, adventurous
//developers could override create entirely, but this should
//only be done as a last resort.
//
//Below is a list of the methods that are called, in the order
//they are fired, along with notes about what they do and if when
//you should over-ride them in your widget:
//
//* postMixInProperties:
//* a stub function that you can over-ride to modify
//variables that may have been naively assigned by
//mixInProperties
//* widget is added to manager object here
//* buildRendering:
//* Subclasses use this method to handle all UI initialization
//Sets this.domNode. Templated widgets do this automatically
//and otherwise it just uses the source dom node.
//* postCreate:
//* a stub function that you can over-ride to modify take
//actions once the widget has been placed in the UI

The postMixInProperties function is called right after Dojo has mixed in all functions and properties of the widgets' superclasses. Most widgets have the classes _Widget and _Templated mixed in, or subclasses of them. This is the function where you set important properties of the widget before it is displayed.

The function buildRendering is then called, which normally builds the UI and sets the domNode property of the widget, to be used in functions as 'this.domNode'. The variable _Templated overrides this to build the widget according to a template string or file. Override this only if you've read the source code a couple of times. And understand it.

The function postCreate is next, which is provided as a stub function which is called once the widget is visually inserted in the page.

The function startUp is next, which gets called for all widgets once all widgets in the page have been rendered properly, but before any child widgets have been created, so that any necessary properties can be messaged first.

The function uninitialize gets called when the widget is being destroyed, usually due to a call to destroyRecursive on the widget itself or to a parent widget.

Now here comes an important fact: You never need to implement any of these functions, unless you feel that you need to. All are implemented fully, or as stubs for your convenience, in superclasses of all widgets.

Templates

The whole point with a widget is that it should be visible. All widgets comprise at least one HTML element. The element which makes up a widget can be created programmatically in an overridden function, but for most purposes you get much cleaner code by separating the looks from the logic, so to speak.

Dojo actually supports two different templating langauges: the simple default and the Django Template Language (DTL, implemented originally in the Python Web framework of the same name).

Note that if you're using the first (standard) templating language, you're only allowed one element in the template! This is not as bad as it sounds. What it means is that you can only have one element with any number of children.

What will get you into trouble is if you have more than one element in your template parallel, or side-by-side, then only the first will get parsed.

The first supports simple variable substitutions, using ${..} syntax. For instance, you can define a HTML template snippet for a widget that includes a div tag which gets a custom id based upon the id given to the widget using the following:

<div id="${id}_custom"></div>

That id would be the same property that is set as id="..." in the page where the widget is created and which also can be accessed using this.id inside the functions of the widget.

So all properties being set in the widget, by instantiation or dynamically (but before the template is rendered), can be used in this way inside the template string or file.

For a concrete example, look at the template for dijit.form.TextBox:

<input class="dijit dijitReset dijitLeft"
dojoAttachPoint='textbox,focusNode'
name="${name}"
dojoAttachEvent='onmouseenter:_onMouse,onmouseleave:_onMouse,
onfocus:_onMouse,onblur:_onMouse,onkeypress:_onKeyPress'
autocomplete="off"
type="${type}"
/>

Inside the dijit/form/TextBox.js file, there are no definitions for these variables, however. But if we walk the class hierarchy, we see that TextBox derives from a class called dijit.form._FormValueWidget. This class, in turn, inherits from dijit.form._FormWidget (and both superclasses are defined in the file with the same name.) Finally, we get to the variables:

...
//Name used when submitting form; same as "name" attribute or
//plain HTML elements
name: "",
// alt: String
//Corresponds to the native HTML <input> element's attribute.
alt: "",
// value: String
//Corresponds to the native HTML <input> element's attribute.
value: "",
// type: String
//Corresponds to the native HTML <input> element's attribute.
type: "text",
...

So now you see that there is no magic underlying basic templating in Dojo. As long as you have a variable defined in a widget, even if it comes from a superclass or mixin (as you remember, a mixin is another (or more) multiple superclass, or a superclass added at runtime), it can be referred to in the template for the widget with the ${} syntax.

Attach points

Templates might contain fairly complex things, and it is not at all unusual to have the need to access DOM nodes inside the widget template after it has been instantiated. You might want to show or hide a dialog, or maybe add items dynamically to a list.

Either way, the quick and dirty way of doing this (as shown above) is to give the DOM node you want to access inside the widget template a dynamic id based upon the id of the widget, like this:

<div id="{id}_foo">

One could then use the following code in the actual JavaScript of the widget:

var x = dojo.byId(this.id+"_foo");

And x would always resolve to that particular node in the template, regardless of how many widgets of the same kind has been created in the page.

As it turns out, Dojo has excellent support for this, and it is called "Attach Points". An Attach Point is a name you can give to any DOM node or Dijit in the template. Dojo will automatically scan the template for Attach Points and then create contextual this variables for the Dijit with the same names.

Consider a template that uses Attach Points instead, which looks like this:

<div><div dojoAttachPoint='foo'>XXXX</div><div dojoAttachPoint='bar'>
YYYY</div></div>

What will happen when the Dijit is rendered in the page is that two new variables will be instantiated in the context of the Dijit, with the names 'foo' and 'bar', being references to the DOM nodes in question.

In the postCreate function of the widget, one could then have a line which reads:

this.foo.style.background = "#f94444";

This will change the background of the DOM node in the template, without having to know what DOM id it actually has, and without colliding with any other Dijits of the same (or other) type.

Events

But there were some other funny things in the template for TextBox, weren't there? There was a property called dojoAttachEvent, which is used expressly for the same reasons that one would use dojo.connect inside a script.

Let's look closer at those events:

dojoAttachEvent='onmouseenter:_onMouse...' ...

It is a series of comma-separated event names and function names pairs. In the case above, the event onmouseenter for the DOM node is connected to the function _onMouse in the TextBox widget class. This would otherwise be the prime reason for using Attach Points, so the code gets cleaner still.

Extension points

An extension point is what Dojo calls a function override inside the usual page. Several widgets aren't particularly useful unless you tell them what to do, such as the Button family. One way of telling a Button what to do is to create a small JavaScript somewhere in the page and use dojo.connect.

Another way could be to create you own widget which subclasses the Button widget, and then override the onClick function defined inside that widget using an extension point. We begin by checking out parts of the code in dijit.Button.js:

_onClick: function(/*Event*/ e){
// summary: internal function to handle click actions
if(this.disabled || this.readOnly)
{
dojo.stopEvent(e); // needed for checkbox
return false;
}
this._clicked(); // widget click actions
return this.onClick(e); // user click actions
},

This function is wired up to take care of click events for the widget. The last line of the widget calls another internal function, onClick, and returns the result of that. onClick looks like this:

onClick: function(/*Event*/ e){
//summary: user callback for when button is clicked
//if type="submit", return true to perform submit
return true;
},

To override this function by using an extension point, we can put the following in our page when declaring the Button widget:

<script>
function myfunc(e)
{
//Do something really clever with the event argument
}
</script>
<div dojoType="dijit.form.Button" onClick="myfunc"></div>

Django Templating Language (DTL)

DTL is quite another order of templating language. Here you can define more complex widget markups using both loops and conditionals.

Where Dojo's classical templating system relied on variable substitutions, leaving the widget to create more complex dynamical markup in special functions and then put them in the template, DTL gives us much more power, or conversely allows our logic to become smaller.

To use DTL inside a widget, you must subclass dojox.dtl.Template and dojox.dtl.HtmlTemplate. The former manages all simple text substitutions, and the latter manages all other complex DOM manipulation.

So when defining a widget, instead of writing this:

dojo.declare("mycorp.charting.chart1", [ dijit._Widget,
dijit._Templated],{...

You'd instead write the following:

dojo.declare("mycorp.charting.chart1", [ dijit._Widget,
dojox.dtl._Templated],
{...

For example, we have a widget which reads data from the server using dojo.xhrGet and then puts all items read in a simple but sortable SortList.

Using a standard templating language, we might have built a template that looked something like this:

templateString="<ul dojoType="dojox.widget.SortList"></ul>";

And then have some widget code that looks like this:

// To be called when the server responds with data
handleData: function(data)
{
var obj = eval(“(“+data+”)”);
dojo.forEach(obj, function(o)
{
var li = document.createElement('li');
li.innerHTML = “” + o;
this.domNode.appendChild(li);
});
}

Instead, with DTL, we can change the template too look like this instead:

templateString="<ul dojoType="dojox.widget.SortList">{% for item in
obj %}<li>{{ item }}</li>{% endfor %}</ul>";

The code will be changed to only set the obj variable, which is used in the template, and the template itself then manages looping and variable substitution all on its own.

//insert code26

To actually see the rendered data, DTL requires an extra step. You must at one point, when your variables are set up correctly, call the render function from dojox.dtl._Templated. But since your widget has mixed that class in, it is part of the this context.

// changed to use DTL functionality instead. Obj is now an instance
//variable.
handleData: function(data)
{
this.obj = eval("("+data+")");
}

However, dojox.widget.SortList is actually able to load its contents dynamically from a dojo.data store without any intervening widgets at all. I only use it as a daft but simple example on how one usually can go about creating dynamic content in a widget.

First, let's take a look at the features of DTL before we dive down into a longer example.

Variable substitution

Variables that we want to display from the widget are marked up differently.

{{person_name}}

instead of

${person_name}

Loops

The loops in DTL are reminiscent of server-based templating languages of yore, especially ASP and JSP.

Of course, these days the server need not do any templating or web magic at all, it only sends us data which gets rendered every which way in the Dojo client.

The variable item_list showing up in the example below are variables that exist in the this context of the widget, and can be put there using widget parameter passing 'the usual way', just so you know.

<ul>
{% for item in item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>

Conditionals

{% if ordered_warranty %}
<p>Your warranty information will be included in the packaging.</p>
{% else %}
<p>No warranty for you!</p>
{% endif %}

Argument passing

A Dijit is just a Dojo class with some special properties. One of those properties is that if the Dijit class declares an explicit class variable, that variable will automatically be detected and initialized if present in the Dijit argument object.

A recommended widget structure

The function dojo.require is a very powerful JavaScript loader. By creating a separate directory parallel to the Dojo directories, you will be able to load you own widgets (including having them auto-loading any of their dependencies) using just one dojo.require statement in your page.

There's another way to point out where to load classes from (this does ,of course, not only relate to widgets, but we'll get to that in a minute).

This is how you might want to set things up for a new customer or project.

Learning Dojo

This is just an example, and you might want to set things up differently for a variety of reasons. We'll take each non-standard directory and file at a time and describe the reasons for where they're put.

 

File/Directory

Meaning

newcorp

This is the name of your new project. The reason for putting this directory here is to make it simpler do use dojo.require for your project, but also to encapsulate all you functionality in one folder.

templates

Have at least one separate folder for you templates. As you'll see, you can use inline string in the widget to avoid putting the widget template in a separate file. I advise against it, at least in the beginning. A separate file is great to pass around, and to change separately.

Sometimes you might choose to create separate subdirectories in the template folder, if you have many templates that yet can be divided into groups of widgets.

styling

Here I put the CSS files that are unique for each widget. Note that Dojo does not auto-load these CSS files, so you will still have to include them 'manually' into you main HTML file.

Even so, I have come to rely upon having a separate directory for styling, to further modularize things from each other and being able to focus on just the current widget.

charting

First things first here; charting is not a magic name in Dojo, it's just a sample name of the first widget created for the newcorp project. It could have been named 'foo' instead.

But following the structure of the rest of Dojo, each area of functionality has its own subdirectory. If you were to create another component for newcorp that was a simple shopping cart, the next directory might be named sc or cart, parallel to this one.

test_chart1.html

I usually put my test files in the root directory of the project. This is not completely normal, and Dojo usually provides a test subdirectory.

chart1.html

The HTML template for the mycorp.charting.chart1 widget

chart1.css

The CSS styles for the same

chart1.js

The actual widget class which declares the widget and points out the template file.

No matter how you choose to arrange the files, there are only two places which look up all the other things:

  • The prime HTML file which actually loads the widget which you've created.
  • The .js file that defines the widget.

The parts which are critical here come usually in the beginning of the widget. Let's look at a small example which fits into the scenario described above: the chart1.js widget:

dojo.provide("mycorp.charting.chart1");
dojo.require("dijit._Templated");
dojo.require("dijit._Widget");
dojo.require("dojox.charting.Chart2D");
dojo.declare("mycorp.charting.chart1", [ dijit._Widget, dijit._Templated],
{
templatePath: dojo.moduleUrl("mycorp","templates/chart1.html"),
widgetsInTemplate: true,
startup: function()
{
console.log("startup for mycorp.charting.chart1 called.");
var ch = this.corpchart;
console.log("corpchart "+ch+" has id "+ch.id);
var chart1 = new dojox.charting.Chart2D(this.corpchart.id);
chart1.addSeries("Series A", [1, 2, 5, 4, 1, 3, 2,3,2,4,3,4],
{stroke: {color: "red", width: 2}});
chart1.addSeries("Series B", [7, 6, 3, 5, 4, 6, 5,6,7,5,2,5],
{stroke: {color: "blue", width: 2}});
chart1.render();
}
});

The first line of the widget declaration is dojo.provide. That call must contain a string that exactly references where in the namespace this widget (or class, actually) exists. Since this widget exists in the file mycorp/charting/chart1.js, the string will be mycorp.charting.chart1.

Then follows a number of required statements. The big upside with having required statements inside the widget definition is that it leaves the main HTML page relatively uncluttered. In fact, with some luck, all the script references you'll need is the one for dojo.js, and then a required statement for your widget. The rest of the Dojo classes will be pulled in dynamically as their required statements get discovered.

Let's have a look at the test page for our class:

<html>
<head><title>Chart1 Test</title></head>
<style type="text/css">
@import "../../../dojo/resources/dojo.css";
@import "styling/chart1.css";
</style>
<script>
var djConfig={ parseOnLoad: true};
</script>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="../dojo/dojo.js"></script>
<script>
dojo.require("dojo.parser");
dojo.require("mycorp.charting.chart1");
</script>
<body>
<div dojoType="mycorp.charting.chart1"></div>
</body>
</html>

We include two CSS files: the Dojo reset styles and the specific styles for our widget. It can be a good idea to create versioned CSS files for each package (or project) that combine all styles into one file, for regular milestones. However, for everyday coding, it is generally better to have separate files.

After that we get the djConfig declaration, which only tells the parser to begin parsing the page for Dijits immediately after load.

Then we pull in the main dojo loader—dojo.js, and require first the parser, and then our widget.

The body of the test file is minimal, since all special markup for the widget is folded down into its template.

The CSS file is also very small and looks like this:

.mycorp_chart
{
height: 200px;
width: 400px;
}

And the template itself looks like this:

<div dojoAttachPoint="corpchart" class="mycorp_chart"></div>

Using the dojoAttachPoint property, a variable gets created inside our widget, which we can refer to as this.corpchart and which is a reference to the DOM node in question.

If you try out the example and use Firebug, you will see the following in the Firebug console:

Learning Dojo

The id of the widget has been set to the namespace path of the widget, with _ replacing /, and a static counter tucked at the end.

The chart displayed will look approximately like this:

Learning Dojo

	

About the Author :


Peter Svensson

Peter Svensson is an Ajax evangelist and front-end architect at Nethouse AB. He is
the instigator of the Thin Server Architecture Working Group and a Dojo contributor.
He's an avid JavaScript aficionado who really likes dynamic languages and would
very much appreciate if the rest of the world would catch up really soon.

Books From Packt

Drupal 6 JavaScript and jQuery: RAW
Drupal 6 JavaScript and jQuery: RAW

Alfresco Developer Guide
Alfresco Developer Guide

AJAX and PHP: Building Responsive Web Applications
AJAX and PHP: Building Responsive Web Applications

Expert Python Programming
Expert Python Programming

Google Web Toolkit GWT Java AJAX Programming
Google Web Toolkit GWT Java AJAX Programming

WordPress Complete
WordPress Complete

DWR JavaAJAX Applications
DWR Java AJAX Applications

Drupal 6 Themes
Drupal 6 Themes

Microsoft AJAX Library Essentials: Client-side ASP.NET AJAX 1.0 Explained
Microsoft AJAX Library Essentials: Client-side ASP.NET AJAX 1.0 Explained

No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
u
k
v
9
T
F
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software