- The Book of Dojo
- The Dojo Book, 0.4
- Part 1: "Introduction"
- Part 2: "Out of the Box" Dojo
- Part 3: "The Dojo Programming Model"
- Part 4: "More on Widgets"
- Part 5: "Connecting the pieces"
- Part 6: "Customizing Dojo Builds for Better Performance"
- Part 7: "Utilities"
- Part 8: "Internationalization and Accessiblity"
- Part 9: "Dojo Community"
- Part 10: "Fresh From The Shed" Dojo
- BookWriting
- Glossary
The Memo
Submitted by lance on Mon, 01/22/2007 - 03:44.
Overview
This page serves as an introduction to the art and science of creating one's own dojo widgets, and invoking them in html code just like mainstream Dojo widgets.
The following walk through will take you through all the steps needed to create a simple widget, ie a widget that contains only dom elements, not any nested dojo widgets.
Following this walk through are some instructions for creating compound widgets (ie, widgets that include other dojo widgets).
Getting Started
Let's say that you want to make a memo widget. Just a yellow sticky note to remind yourself of your dentist appointment, or whatever. Something that you can put on the screen and then erase later. Something so that a call like this:
<div dojoType="Memo" title="Reminder"> Pick up milk on the way home </div>
will produce something that looks like this:
Reminder
X
Pick up milk on the way home.
The Template
The first step is to write HTML and CSS that prototypes how the widget will look. You can do this in any editor of your choice. I made the prototype above using this HTML:
<div class="memo"> <div class="title">Reminder</div> <div class="close">X</div> <div class="contents">Pick up milk on the way home.</div> </div>
And this CSS:
.memo {
background: yellow;
font-family: cursive;
width: 10em;
}
.title {
font-weight: bold;
text-decoration: underline;
float: left;
}
.close {
float: right;
background: black;
color: yellow;
font-size: x-small;
cursor: pointer;
}
.contents {
clear: both;
font-style: italic;
}
Note how I put as much of the formatting code into the CSS. This isn't necessary, but it does make it easier for other people to customize the widget, merely by altering the CSS.
Turning it into a widget
To make this memo into a widget, you need to declare a javascript object that connects with the HTML and CSS template above. So, put the HTML in a file called Memo.html, the CSS in a file called Memo.css, and make the Memo.js file below:
dojo.widget.defineWidget(
// widget name and class
"acme.widget.Memo",
// superclass
dojo.widget.HtmlWidget,
// properties and methods
{
templatePath: dojo.uri.dojoUri("../acme/widget/Memo.html"),
templateCssPath: dojo.uri.dojoUri("../acme/widget/Memo.css")
}
);
Contents and Parameters
The obvious problem with this widget is that no matter what is inside the source div, it always says "Pick up milk on the way home". What you need is for the contents of the source div to be inserted into the generated output. This is what the "containerNode" is for, and you use it like this...
First, in the template, get rid of the static content, and instead mark that the div should hold the content from the source.
<div class="memo">
<div class="title">Reminder</div>
<div class="close">X</div>
<div class="contents" dojoAttachPoint="containerNode"></div>
</div>
Then, in the javascript object, denote that this widget is a container:
dojo.widget.defineWidget(
// widget name and class
"acme.widget.Memo",
// superclass
dojo.widget.HtmlWidget,
// properties and methods
{
isContainer: true,
templatePath: dojo.uri.dojoUri("../acme/widget/Memo.html"),
templateCssPath: dojo.uri.dojoUri("../acme/widget/Memo.css")
}
);
OK, what about the title? The title is specified as an attribute:
<div dojoType="Memo" title="Reminder">
Pick up milk on the way home
</div>
That means that it's a parameter to the widget. Parameters are specified as normal widget properties. In this case, the widget properties would look like this:
// properties and methods
{
// parameters
title: "Note",
// settings
isContainer: true,
templatePath: dojo.uri.dojoUri("../acme/widget/Memo.html"),
templateCssPath: dojo.uri.dojoUri("../acme/widget/Memo.css")
}
This widget now has a "title" parameter, with a default value of "Note"
How do you stick this parameter's value into the widget? Luckily widget templates have variable substitution, so no coding is necessary. Just modify the template to use this parameter:
<div class="memo">
<div class="title">${this.title}</div>
<div class="close">X</div>
<div class="contents" dojoAttachPoint="containerNode"></div>
</div>
Events
OK, the content of the widget is showing up correctly, but how to you make clicking the X cause the widget to disappear? It's pretty simple, and hardly requires any javascript. The first step is to modify the template to handle click events on the X:
<div class="memo">
<div class="title">${this.title}</div>
<div class="close" dojoAttachEvent="onClick">X</div>
<div class="contents" dojoAttachPoint="containerNode"></div>
</div>
Then you simply add a method to the widget javascript object to handle the click:
onClick: function(evt){
this.destroy();
}
That's it! Your first functioning widget!
Final code
Memo.html
<div class="memo">
<div class="title">${this.title}</div>
<div class="close" dojoAttachEvent="onClick">X</div>
<div class="contents" dojoAttachPoint="containerNode"></div>
</div>
Memo.css
.memo {
background: yellow;
font-family: cursive;
width: 10em;
}
.title {
font-weight: bold;
text-decoration: underline;
float: left;
}
.close {
float: right;
background: black;
color: yellow;
font-size: x-small;
cursor: pointer;
}
.contents {
clear: both;
font-style: italic;
}
Memo.js
dojo.widget.defineWidget(
// widget name and class
"acme.widget.Memo",
// superclass
dojo.widget.HtmlWidget,
// properties and methods
{
// parameters
title: "Note",
// settings
isContainer: true,
templatePath: dojo.uri.dojoUri("../acme/widget/Memo.html"),
templateCssPath: dojo.uri.dojoUri("../acme/widget/Memo.css"),
// callbacks
onClick: function(evt){
this.destroy();
}
}
);
